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/signup", handler.AuthSignup)
|
||||||
api.POST("/auth/signin", handler.AuthSignin)
|
api.POST("/auth/signin", handler.AuthSignin)
|
||||||
|
|
||||||
api.POST("/source", handler.CreateSource)
|
secure := api.Group("/secure").Use(middleware.RequireAuth())
|
||||||
api.GET("/source", handler.ListSource)
|
{
|
||||||
api.GET("/source/raw/:sourceType/*path", handler.RawRequestSource)
|
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 {ResourceDetailComponent} from './pages/resource-detail/resource-detail.component';
|
||||||
import {AuthSigninComponent} from './pages/auth-signin/auth-signin.component';
|
import {AuthSigninComponent} from './pages/auth-signin/auth-signin.component';
|
||||||
import {AuthSignupComponent} from './pages/auth-signup/auth-signup.component';
|
import {AuthSignupComponent} from './pages/auth-signup/auth-signup.component';
|
||||||
|
import {CanActivateAuthGuard} from './services/can-activate.auth-guard';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
|
|
||||||
|
@ -14,9 +15,9 @@ const routes: Routes = [
|
||||||
{ path: 'auth/signup', component: AuthSignupComponent },
|
{ path: 'auth/signup', component: AuthSignupComponent },
|
||||||
|
|
||||||
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
||||||
{ path: 'dashboard', component: DashboardComponent },
|
{ path: 'dashboard', component: DashboardComponent, canActivate: [ CanActivateAuthGuard] },
|
||||||
{ path: 'detail', component: ResourceDetailComponent },
|
{ path: 'detail', component: ResourceDetailComponent, canActivate: [ CanActivateAuthGuard] },
|
||||||
{ path: 'sources', component: MedicalSourcesComponent },
|
{ path: 'sources', component: MedicalSourcesComponent, canActivate: [ CanActivateAuthGuard] },
|
||||||
// { path: 'general-pages', loadChildren: () => import('./general-pages/general-pages.module').then(m => m.GeneralPagesModule) },
|
// { 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: 'ui-elements', loadChildren: () => import('./ui-elements/ui-elements.module').then(m => m.UiElementsModule) },
|
||||||
// { path: 'form', loadChildren: () => import('./form/form.module').then(m => m.FormModule) },
|
// { 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 { AppRoutingModule } from './app-routing.module';
|
||||||
import { AppComponent } from './app.component';
|
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 { NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
||||||
import { HeaderComponent } from './components/header/header.component';
|
import { HeaderComponent } from './components/header/header.component';
|
||||||
import { FooterComponent } from './components/footer/footer.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 { AuthSignupComponent } from './pages/auth-signup/auth-signup.component';
|
||||||
import { AuthSigninComponent } from './pages/auth-signin/auth-signin.component';
|
import { AuthSigninComponent } from './pages/auth-signin/auth-signin.component';
|
||||||
import { FormsModule } from '@angular/forms';
|
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({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
@ -39,7 +43,15 @@ import { FormsModule } from '@angular/forms';
|
||||||
NgbModule,
|
NgbModule,
|
||||||
ChartsModule
|
ChartsModule
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [
|
||||||
|
FastenApiService,
|
||||||
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: AuthInterceptorService,
|
||||||
|
multi: true
|
||||||
|
},
|
||||||
|
CanActivateAuthGuard
|
||||||
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule {
|
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> {
|
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(
|
.pipe(
|
||||||
map((response: ResponseWrapper) => {
|
map((response: ResponseWrapper) => {
|
||||||
console.log("SOURCE RESPONSE", response)
|
console.log("SOURCE RESPONSE", response)
|
||||||
|
@ -77,7 +81,7 @@ export class FastenApiService {
|
||||||
}
|
}
|
||||||
|
|
||||||
getResources(resourceType: string, resourceId?: string ) {
|
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(
|
.pipe(
|
||||||
map((response: ResponseWrapper) => {
|
map((response: ResponseWrapper) => {
|
||||||
console.log("RESPONSE", response)
|
console.log("RESPONSE", response)
|
||||||
|
|
Loading…
Reference in New Issue