From 560c426bc0dbf440716da2554bc28560bbb3841d Mon Sep 17 00:00:00 2001 From: Willem Dantuma Date: Thu, 19 Dec 2019 13:32:51 +0100 Subject: [PATCH] Refactor authconfig --- .../common/src/fm/common-service.module.ts | 211 +++++++++--------- projects/common/src/fm/common.module.ts | 5 +- .../src/fm/shared/app.config.factory.ts | 110 ++++----- .../common/src/fm/shared/authconfigFactory.ts | 22 ++ 4 files changed, 181 insertions(+), 167 deletions(-) create mode 100644 projects/common/src/fm/shared/authconfigFactory.ts diff --git a/projects/common/src/fm/common-service.module.ts b/projects/common/src/fm/common-service.module.ts index d9dcdfe..7acf908 100644 --- a/projects/common/src/fm/common-service.module.ts +++ b/projects/common/src/fm/common-service.module.ts @@ -1,105 +1,106 @@ -// angular modules -import { NgModule, APP_INITIALIZER, ModuleWithProviders, Injector,Optional,SkipSelf } from '@angular/core'; -import { CommonModule, DatePipe } from '@angular/common'; -import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http'; -import { FormsModule } from '@angular/forms'; - -// external modules -import { OAuthModule,AuthConfig, OAuthService, OAuthStorage } from 'angular-oauth2-oidc'; - - -// routing module -import { AppCommonRoutingModule } from './common-routing.module'; - -import { MODULE_NAME } from './module-name'; - -//components -import { ItemTypeService } from './services/itemtype.service'; -import { FolderService } from './services/folder.service'; -import { TimespanService} from './services/timespan.service'; -import { ItemService} from './services/item.service'; -import { EventService } from './services/event.service'; -import { TypeaheadService } from './services/typeahead.service'; -import { UserService } from './services/user.service'; -import { AppConfig } from './shared/app.config'; -import { AccessTokenInterceptor } from "./shared/accesstoken.interceptor"; -import { appConfigFactory } from "./shared/app.config.factory"; -import { AuthGuard } from './services/auth-guard.service'; -import { NavBarGuard } from './services/nav-bar-guard.service'; -import { FullScreenGuard } from './services/full-screen-guard.service'; -import { SafePipe } from './shared/safe.pipe'; -import { AppComponent} from './components/app/app.component'; -import { AuthCallbackComponent } from './components/auth-callback/auth-callback.component'; -import { AuthCallbackGuard } from './components/auth-callback/auth-callback.guard'; -import { SessionClearedComponent } from './components/session-cleared/session-cleared.component'; -import { ResumableFileUploadService } from './components/resumable-file-upload/resumable-file-upload.service'; -import { ResumableFileUploadComponent } from './components/resumable-file-upload/resumable-file-upload.component'; -import { NotFoundComponent } from './components/not-found/not-found.component'; -import { NotImplementedComponent } from './components/not-implemented/not-implemented.component'; -import { SidePanelComponent } from './components/side-panel/side-panel.component'; -import { TimespanComponent } from './components/timespan/timespan.component'; -import { TagInputComponent } from './components/tag-input/tag-input.component'; -import {IEventMessage } from './models/event.message'; -import { IItem, Item } from './models/item'; -import {IItemType} from './models/item.type'; -import {IItemTypes} from './models/item.types'; -import {IItemTask,ItemTask} from './models/itemTask'; -import {IListItem} from './models/list.item'; -import {ITypeaheadItem} from './models/typeahead.item'; -import {IUser} from './models/user'; -import * as commonActions from './actions/app-common.actions'; -import * as commonReducers from './reducers/app-common.reducer'; -import * as commonEffects from './effects/app-common.effects'; -import {NgbDateNativeAdapter} from './services/date-adapter.service' -import { from } from 'rxjs'; - -export {FolderService, - ItemTypeService, - TimespanService, - ItemService, - EventService, - TypeaheadService, - UserService, - AppConfig, - AccessTokenInterceptor, - AuthGuard, - NavBarGuard, - FullScreenGuard, - AuthCallbackGuard, - ResumableFileUploadService, - NgbDateNativeAdapter -}; - -@NgModule({ - imports: [ - OAuthModule.forRoot(), - ] -}) -export class AppCommonServiceModule { - constructor (@Optional() @SkipSelf() parentModule: AppCommonServiceModule) { - if (parentModule) { - throw new Error( - 'AppCommonServiceModule is already loaded. Import it in the AppModule only'); - } - } - static forRoot(): ModuleWithProviders { - return { - ngModule: AppCommonServiceModule, - providers: [ - AppConfig, - { - provide: APP_INITIALIZER, - useFactory: appConfigFactory, - deps: [Injector, AppConfig, OAuthService], - multi: true - }, - { - provide: HTTP_INTERCEPTORS, - useClass: AccessTokenInterceptor, - multi: true - }, - DatePipe - ] - }; - } -} +// angular modules +import { NgModule, APP_INITIALIZER, ModuleWithProviders, Injector,Optional,SkipSelf } from '@angular/core'; +import { CommonModule, DatePipe } from '@angular/common'; +import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; + +// external modules +import { OAuthModule,AuthConfig, OAuthService, OAuthStorage } from 'angular-oauth2-oidc'; + + +// routing module +import { AppCommonRoutingModule } from './common-routing.module'; + +import { MODULE_NAME } from './module-name'; + +//components +import { ItemTypeService } from './services/itemtype.service'; +import { FolderService } from './services/folder.service'; +import { TimespanService} from './services/timespan.service'; +import { ItemService} from './services/item.service'; +import { EventService } from './services/event.service'; +import { TypeaheadService } from './services/typeahead.service'; +import { UserService } from './services/user.service'; +import { AppConfig } from './shared/app.config'; +import { AccessTokenInterceptor } from "./shared/accesstoken.interceptor"; +import { appConfigFactory } from "./shared/app.config.factory"; +import { AuthGuard } from './services/auth-guard.service'; +import { NavBarGuard } from './services/nav-bar-guard.service'; +import { FullScreenGuard } from './services/full-screen-guard.service'; +import { SafePipe } from './shared/safe.pipe'; +import { AppComponent} from './components/app/app.component'; +import { AuthCallbackComponent } from './components/auth-callback/auth-callback.component'; +import { AuthCallbackGuard } from './components/auth-callback/auth-callback.guard'; +import { SessionClearedComponent } from './components/session-cleared/session-cleared.component'; +import { ResumableFileUploadService } from './components/resumable-file-upload/resumable-file-upload.service'; +import { ResumableFileUploadComponent } from './components/resumable-file-upload/resumable-file-upload.component'; +import { NotFoundComponent } from './components/not-found/not-found.component'; +import { NotImplementedComponent } from './components/not-implemented/not-implemented.component'; +import { SidePanelComponent } from './components/side-panel/side-panel.component'; +import { TimespanComponent } from './components/timespan/timespan.component'; +import { TagInputComponent } from './components/tag-input/tag-input.component'; +import {IEventMessage } from './models/event.message'; +import { IItem, Item } from './models/item'; +import {IItemType} from './models/item.type'; +import {IItemTypes} from './models/item.types'; +import {IItemTask,ItemTask} from './models/itemTask'; +import {IListItem} from './models/list.item'; +import {ITypeaheadItem} from './models/typeahead.item'; +import {IUser} from './models/user'; +import * as commonActions from './actions/app-common.actions'; +import * as commonReducers from './reducers/app-common.reducer'; +import * as commonEffects from './effects/app-common.effects'; +import {NgbDateNativeAdapter} from './services/date-adapter.service' +import { from } from 'rxjs'; +import {AuthConfigFactory} from './shared/authconfigFactory'; + +export {FolderService, + ItemTypeService, + TimespanService, + ItemService, + EventService, + TypeaheadService, + UserService, + AppConfig, + AccessTokenInterceptor, + AuthGuard, + NavBarGuard, + FullScreenGuard, + AuthCallbackGuard, + ResumableFileUploadService, + NgbDateNativeAdapter +}; + +@NgModule({ + imports: [ + OAuthModule.forRoot(), + ] +}) +export class AppCommonServiceModule { + constructor (@Optional() @SkipSelf() parentModule: AppCommonServiceModule) { + if (parentModule) { + throw new Error( + 'AppCommonServiceModule is already loaded. Import it in the AppModule only'); + } + } + static forRoot(): ModuleWithProviders { + return { + ngModule: AppCommonServiceModule, + providers: [ + AppConfig, + { + provide: APP_INITIALIZER, + useFactory: appConfigFactory, + deps: [Injector, AppConfig, OAuthService,AuthConfigFactory], + multi: true + }, + { + provide: HTTP_INTERCEPTORS, + useClass: AccessTokenInterceptor, + multi: true + }, + DatePipe + ] + }; + } +} diff --git a/projects/common/src/fm/common.module.ts b/projects/common/src/fm/common.module.ts index 41e49a7..ae3edad 100644 --- a/projects/common/src/fm/common.module.ts +++ b/projects/common/src/fm/common.module.ts @@ -19,6 +19,7 @@ import { MODULE_NAME } from './module-name'; //components import { SafePipe } from './shared/safe.pipe'; +import { AuthConfigFactory,IAuthconfigFactory} from './shared/authconfigFactory'; import { AppComponent} from './components/app/app.component'; import { AuthCallbackComponent } from './components/auth-callback/auth-callback.component'; import { SessionClearedComponent } from './components/session-cleared/session-cleared.component'; @@ -62,7 +63,9 @@ export { ITypeaheadItem, IUser, commonActions, - commonReducers + commonReducers, + IAuthconfigFactory, + AuthConfigFactory }; @NgModule({ diff --git a/projects/common/src/fm/shared/app.config.factory.ts b/projects/common/src/fm/shared/app.config.factory.ts index f5634ef..8da019c 100644 --- a/projects/common/src/fm/shared/app.config.factory.ts +++ b/projects/common/src/fm/shared/app.config.factory.ts @@ -1,61 +1,49 @@ -import { Injector } from '@angular/core'; -import { Router,UrlSerializer } from '@angular/router'; -import { AuthConfig, OAuthService, JwksValidationHandler, OAuthErrorEvent } from 'angular-oauth2-oidc'; -import { AppConfig } from "./app.config"; - -function getAuthConfig(appConfig: AppConfig): AuthConfig { - let authConfig: AuthConfig = new AuthConfig(); - authConfig.issuer = appConfig.getConfig("issuer"); - authConfig.redirectUri = window.location.origin + "/cb"; - authConfig.silentRefreshRedirectUri = window.location.origin + "/silent-refresh.html"; - authConfig.clientId = appConfig.getConfig("clientId"); - authConfig.customQueryParams = { audience: appConfig.getConfig("audience") }; - authConfig.scope = "openid profile email"; - authConfig.oidc = true; - authConfig.disableAtHashCheck = true; - authConfig.requireHttps = appConfig.getConfig("requireHttps"); - return authConfig; -} - -export function appConfigFactory(injector:Injector, appConfig: AppConfig, oauthService: OAuthService): () => Promise { - return (): Promise => { - return appConfig.load().then(() => { - oauthService.events.subscribe((event) => { - console.debug(event.type); - if (event.type == 'token_error' || event.type == 'silent_refresh_timeout') { - let e = event as OAuthErrorEvent; - let p = e.params as any; - if (event.type == 'silent_refresh_timeout' || (p.error && p.error == 'login_required')) { - let router = injector.get(Router); - console.debug("Session expired"); - router.navigate(['loggedout'], { queryParams: { redirectTo: router.url } }); - } - } - }); - oauthService.configure(getAuthConfig(appConfig)); - oauthService.tokenValidationHandler = new JwksValidationHandler(); - oauthService.tokenValidationHandler.validateAtHash = function () { - return new Promise((res) => { res(true); }) - }; - oauthService.setupAutomaticSilentRefresh(); - let router = injector.get(Router); - var urlTree = router.parseUrl(window.location.href); - var urlPath = window.location.pathname; - oauthService.loadDiscoveryDocument().then(() => { - oauthService.tryLogin({ - onTokenReceived: (info) => { - urlPath = info.state; - } - }).then(() => { - let router = injector.get(Router); - if (!oauthService.hasValidAccessToken()) { - oauthService.initImplicitFlow(urlPath); - } else { - router.navigateByUrl(urlPath); - } - }); - }) - }); - } -} - +import { Injector } from '@angular/core'; +import { Router,UrlSerializer } from '@angular/router'; +import { AuthConfig, OAuthService, JwksValidationHandler, OAuthErrorEvent } from 'angular-oauth2-oidc'; +import { AppConfig } from "./app.config"; +import { IAuthconfigFactory } from './authconfigFactory'; + + +export function appConfigFactory(injector:Injector, appConfig: AppConfig, oauthService: OAuthService, authconfigFactory:IAuthconfigFactory): () => Promise { + return (): Promise => { + return appConfig.load().then(() => { + oauthService.events.subscribe((event) => { + console.debug(event.type); + if (event.type == 'token_error' || event.type == 'silent_refresh_timeout') { + let e = event as OAuthErrorEvent; + let p = e.params as any; + if (event.type == 'silent_refresh_timeout' || (p.error && p.error == 'login_required')) { + let router = injector.get(Router); + console.debug("Session expired"); + router.navigate(['loggedout'], { queryParams: { redirectTo: router.url } }); + } + } + }); + oauthService.configure(authconfigFactory.getAuthConfig(appConfig)); + oauthService.tokenValidationHandler = new JwksValidationHandler(); + oauthService.tokenValidationHandler.validateAtHash = function () { + return new Promise((res) => { res(true); }) + }; + oauthService.setupAutomaticSilentRefresh(); + let router = injector.get(Router); + var urlTree = router.parseUrl(window.location.href); + var urlPath = window.location.pathname; + oauthService.loadDiscoveryDocument().then(() => { + oauthService.tryLogin({ + onTokenReceived: (info) => { + urlPath = info.state; + } + }).then(() => { + let router = injector.get(Router); + if (!oauthService.hasValidAccessToken()) { + oauthService.initImplicitFlow(urlPath); + } else { + router.navigateByUrl(urlPath); + } + }); + }) + }); + } +} + diff --git a/projects/common/src/fm/shared/authconfigFactory.ts b/projects/common/src/fm/shared/authconfigFactory.ts new file mode 100644 index 0000000..1ae1689 --- /dev/null +++ b/projects/common/src/fm/shared/authconfigFactory.ts @@ -0,0 +1,22 @@ +import { AuthConfig } from 'angular-oauth2-oidc'; +import {AppConfig} from './app.config'; + +export interface IAuthconfigFactory { + getAuthConfig(appConfig: AppConfig): AuthConfig; +} + +export class AuthConfigFactory implements IAuthconfigFactory { + getAuthConfig(appConfig: AppConfig): AuthConfig { + let authConfig: AuthConfig = new AuthConfig(); + authConfig.issuer = appConfig.getConfig("issuer"); + authConfig.redirectUri = window.location.origin + "/cb"; + authConfig.silentRefreshRedirectUri = window.location.origin + "/silent-refresh.html"; + authConfig.clientId = appConfig.getConfig("clientId"); + authConfig.customQueryParams = { audience: appConfig.getConfig("audience") }; + authConfig.scope = "openid profile email"; + authConfig.oidc = true; + authConfig.disableAtHashCheck = true; + authConfig.requireHttps = appConfig.getConfig("requireHttps"); + return authConfig; + } + } \ No newline at end of file