working authentication check (via token presence in localstorage).
HTTP interceptor to always add token to header.
This commit is contained in:
parent
1a3dce77cb
commit
6aa92674bc
|
@ -0,0 +1,25 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/auth"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func RequireAuth() gin.HandlerFunc {
|
||||
return func(context *gin.Context) {
|
||||
tokenString := context.GetHeader("Authorization")
|
||||
if tokenString == "" {
|
||||
context.JSON(http.StatusUnauthorized, gin.H{"success": false, "error": "request does not contain an access token"})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
err := auth.ValidateToken(tokenString)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusUnauthorized, gin.H{"success": false, "error": err.Error()})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
context.Next()
|
||||
}
|
||||
}
|
|
@ -43,11 +43,14 @@ func (ae *AppEngine) Setup(logger *logrus.Entry) *gin.Engine {
|
|||
api.POST("/auth/signup", handler.AuthSignup)
|
||||
api.POST("/auth/signin", handler.AuthSignin)
|
||||
|
||||
api.POST("/source", handler.CreateSource)
|
||||
api.GET("/source", handler.ListSource)
|
||||
api.GET("/source/raw/:sourceType/*path", handler.RawRequestSource)
|
||||
secure := api.Group("/secure").Use(middleware.RequireAuth())
|
||||
{
|
||||
secure.POST("/source", handler.CreateSource)
|
||||
secure.GET("/source", handler.ListSource)
|
||||
secure.GET("/source/raw/:sourceType/*path", handler.RawRequestSource)
|
||||
|
||||
api.GET("/fhir/:sourceResourceType/*sourceResourceId", handler.RequestResourceFhir)
|
||||
secure.GET("/fhir/:sourceResourceType/*sourceResourceId", handler.RequestResourceFhir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import { MedicalSourcesComponent } from './pages/medical-sources/medical-sources
|
|||
import {ResourceDetailComponent} from './pages/resource-detail/resource-detail.component';
|
||||
import {AuthSigninComponent} from './pages/auth-signin/auth-signin.component';
|
||||
import {AuthSignupComponent} from './pages/auth-signup/auth-signup.component';
|
||||
import {CanActivateAuthGuard} from './services/can-activate.auth-guard';
|
||||
|
||||
const routes: Routes = [
|
||||
|
||||
|
@ -14,9 +15,9 @@ const routes: Routes = [
|
|||
{ path: 'auth/signup', component: AuthSignupComponent },
|
||||
|
||||
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
||||
{ path: 'dashboard', component: DashboardComponent },
|
||||
{ path: 'detail', component: ResourceDetailComponent },
|
||||
{ path: 'sources', component: MedicalSourcesComponent },
|
||||
{ path: 'dashboard', component: DashboardComponent, canActivate: [ CanActivateAuthGuard] },
|
||||
{ path: 'detail', component: ResourceDetailComponent, canActivate: [ CanActivateAuthGuard] },
|
||||
{ path: 'sources', component: MedicalSourcesComponent, canActivate: [ CanActivateAuthGuard] },
|
||||
// { path: 'general-pages', loadChildren: () => import('./general-pages/general-pages.module').then(m => m.GeneralPagesModule) },
|
||||
// { path: 'ui-elements', loadChildren: () => import('./ui-elements/ui-elements.module').then(m => m.UiElementsModule) },
|
||||
// { path: 'form', loadChildren: () => import('./form/form.module').then(m => m.FormModule) },
|
||||
|
|
|
@ -3,7 +3,7 @@ import { NgModule } from '@angular/core';
|
|||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
||||
import { HeaderComponent } from './components/header/header.component';
|
||||
import { FooterComponent } from './components/footer/footer.component';
|
||||
|
@ -18,6 +18,10 @@ import { ResourceDetailComponent } from './pages/resource-detail/resource-detail
|
|||
import { AuthSignupComponent } from './pages/auth-signup/auth-signup.component';
|
||||
import { AuthSigninComponent } from './pages/auth-signin/auth-signin.component';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AuthInterceptorService } from './services/auth-interceptor.service';
|
||||
import { CanActivateAuthGuard } from './services/can-activate.auth-guard';
|
||||
import {FastenApiService} from './services/fasten-api.service';
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
|
@ -39,7 +43,15 @@ import { FormsModule } from '@angular/forms';
|
|||
NgbModule,
|
||||
ChartsModule
|
||||
],
|
||||
providers: [],
|
||||
providers: [
|
||||
FastenApiService,
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: AuthInterceptorService,
|
||||
multi: true
|
||||
},
|
||||
CanActivateAuthGuard
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AuthInterceptorService } from './auth-interceptor.service';
|
||||
|
||||
describe('AuthInterceptorService', () => {
|
||||
let service: AuthInterceptorService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(AuthInterceptorService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
import { Injectable, Injector } from '@angular/core';
|
||||
import { HttpInterceptor } from '@angular/common/http';
|
||||
import { FastenApiService } from './fasten-api.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuthInterceptorService {
|
||||
|
||||
constructor(private injector: Injector) { }
|
||||
|
||||
intercept(req, next) {
|
||||
const fastenApiService = this.injector.get(FastenApiService);
|
||||
const fastenApiRequest = req.clone({
|
||||
// tslint:disable-next-line:max-line-length
|
||||
headers: req.headers.set('Authorization', 'Bearer ' + fastenApiService.token)
|
||||
});
|
||||
|
||||
return next.handle(fastenApiRequest);
|
||||
|
||||
//TODO: check if the response is 401, if so we should always redirect to /login
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router} from '@angular/router';
|
||||
import { FastenApiService } from './fasten-api.service';
|
||||
|
||||
@Injectable()
|
||||
export class CanActivateAuthGuard implements CanActivate {
|
||||
constructor(private fastenApiService: FastenApiService, private router: Router) {
|
||||
|
||||
}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||
//check if the user is authenticated, if not, redirect to login
|
||||
if (!this.fastenApiService.isAuthenticated()) {
|
||||
this.router.navigate(['/auth/signin']);
|
||||
}
|
||||
// continue as normal
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -66,8 +66,12 @@ export class FastenApiService {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
SECURE ENDPOINTS
|
||||
*/
|
||||
|
||||
createSource(source: Source): Observable<Source> {
|
||||
return this._httpClient.post<any>(`${this.getBasePath()}/api/source`, source)
|
||||
return this._httpClient.post<any>(`${this.getBasePath()}/api/secure/source`, source)
|
||||
.pipe(
|
||||
map((response: ResponseWrapper) => {
|
||||
console.log("SOURCE RESPONSE", response)
|
||||
|
@ -77,7 +81,7 @@ export class FastenApiService {
|
|||
}
|
||||
|
||||
getResources(resourceType: string, resourceId?: string ) {
|
||||
return this._httpClient.get<any>(`${this.getBasePath()}/api/fhir/${resourceType}/${resourceId ? resourceId : ''}`)
|
||||
return this._httpClient.get<any>(`${this.getBasePath()}/api/secure/fhir/${resourceType}/${resourceId ? resourceId : ''}`)
|
||||
.pipe(
|
||||
map((response: ResponseWrapper) => {
|
||||
console.log("RESPONSE", response)
|
||||
|
|
Loading…
Reference in New Issue