Refactor authconfig
FarmMaps.Develop/FarmMapsLib/develop This commit looks good Details

pull/1/head
Willem Dantuma 2019-12-19 13:32:51 +01:00
parent e1fef2d7f3
commit 560c426bc0
4 changed files with 181 additions and 167 deletions

View File

@ -1,105 +1,106 @@
// angular modules // angular modules
import { NgModule, APP_INITIALIZER, ModuleWithProviders, Injector,Optional,SkipSelf } from '@angular/core'; import { NgModule, APP_INITIALIZER, ModuleWithProviders, Injector,Optional,SkipSelf } from '@angular/core';
import { CommonModule, DatePipe } from '@angular/common'; import { CommonModule, DatePipe } from '@angular/common';
import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http'; import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
// external modules // external modules
import { OAuthModule,AuthConfig, OAuthService, OAuthStorage } from 'angular-oauth2-oidc'; import { OAuthModule,AuthConfig, OAuthService, OAuthStorage } from 'angular-oauth2-oidc';
// routing module // routing module
import { AppCommonRoutingModule } from './common-routing.module'; import { AppCommonRoutingModule } from './common-routing.module';
import { MODULE_NAME } from './module-name'; import { MODULE_NAME } from './module-name';
//components //components
import { ItemTypeService } from './services/itemtype.service'; import { ItemTypeService } from './services/itemtype.service';
import { FolderService } from './services/folder.service'; import { FolderService } from './services/folder.service';
import { TimespanService} from './services/timespan.service'; import { TimespanService} from './services/timespan.service';
import { ItemService} from './services/item.service'; import { ItemService} from './services/item.service';
import { EventService } from './services/event.service'; import { EventService } from './services/event.service';
import { TypeaheadService } from './services/typeahead.service'; import { TypeaheadService } from './services/typeahead.service';
import { UserService } from './services/user.service'; import { UserService } from './services/user.service';
import { AppConfig } from './shared/app.config'; import { AppConfig } from './shared/app.config';
import { AccessTokenInterceptor } from "./shared/accesstoken.interceptor"; import { AccessTokenInterceptor } from "./shared/accesstoken.interceptor";
import { appConfigFactory } from "./shared/app.config.factory"; import { appConfigFactory } from "./shared/app.config.factory";
import { AuthGuard } from './services/auth-guard.service'; import { AuthGuard } from './services/auth-guard.service';
import { NavBarGuard } from './services/nav-bar-guard.service'; import { NavBarGuard } from './services/nav-bar-guard.service';
import { FullScreenGuard } from './services/full-screen-guard.service'; import { FullScreenGuard } from './services/full-screen-guard.service';
import { SafePipe } from './shared/safe.pipe'; import { SafePipe } from './shared/safe.pipe';
import { AppComponent} from './components/app/app.component'; import { AppComponent} from './components/app/app.component';
import { AuthCallbackComponent } from './components/auth-callback/auth-callback.component'; import { AuthCallbackComponent } from './components/auth-callback/auth-callback.component';
import { AuthCallbackGuard } from './components/auth-callback/auth-callback.guard'; import { AuthCallbackGuard } from './components/auth-callback/auth-callback.guard';
import { SessionClearedComponent } from './components/session-cleared/session-cleared.component'; import { SessionClearedComponent } from './components/session-cleared/session-cleared.component';
import { ResumableFileUploadService } from './components/resumable-file-upload/resumable-file-upload.service'; import { ResumableFileUploadService } from './components/resumable-file-upload/resumable-file-upload.service';
import { ResumableFileUploadComponent } from './components/resumable-file-upload/resumable-file-upload.component'; import { ResumableFileUploadComponent } from './components/resumable-file-upload/resumable-file-upload.component';
import { NotFoundComponent } from './components/not-found/not-found.component'; import { NotFoundComponent } from './components/not-found/not-found.component';
import { NotImplementedComponent } from './components/not-implemented/not-implemented.component'; import { NotImplementedComponent } from './components/not-implemented/not-implemented.component';
import { SidePanelComponent } from './components/side-panel/side-panel.component'; import { SidePanelComponent } from './components/side-panel/side-panel.component';
import { TimespanComponent } from './components/timespan/timespan.component'; import { TimespanComponent } from './components/timespan/timespan.component';
import { TagInputComponent } from './components/tag-input/tag-input.component'; import { TagInputComponent } from './components/tag-input/tag-input.component';
import {IEventMessage } from './models/event.message'; import {IEventMessage } from './models/event.message';
import { IItem, Item } from './models/item'; import { IItem, Item } from './models/item';
import {IItemType} from './models/item.type'; import {IItemType} from './models/item.type';
import {IItemTypes} from './models/item.types'; import {IItemTypes} from './models/item.types';
import {IItemTask,ItemTask} from './models/itemTask'; import {IItemTask,ItemTask} from './models/itemTask';
import {IListItem} from './models/list.item'; import {IListItem} from './models/list.item';
import {ITypeaheadItem} from './models/typeahead.item'; import {ITypeaheadItem} from './models/typeahead.item';
import {IUser} from './models/user'; import {IUser} from './models/user';
import * as commonActions from './actions/app-common.actions'; import * as commonActions from './actions/app-common.actions';
import * as commonReducers from './reducers/app-common.reducer'; import * as commonReducers from './reducers/app-common.reducer';
import * as commonEffects from './effects/app-common.effects'; import * as commonEffects from './effects/app-common.effects';
import {NgbDateNativeAdapter} from './services/date-adapter.service' import {NgbDateNativeAdapter} from './services/date-adapter.service'
import { from } from 'rxjs'; import { from } from 'rxjs';
import {AuthConfigFactory} from './shared/authconfigFactory';
export {FolderService,
ItemTypeService, export {FolderService,
TimespanService, ItemTypeService,
ItemService, TimespanService,
EventService, ItemService,
TypeaheadService, EventService,
UserService, TypeaheadService,
AppConfig, UserService,
AccessTokenInterceptor, AppConfig,
AuthGuard, AccessTokenInterceptor,
NavBarGuard, AuthGuard,
FullScreenGuard, NavBarGuard,
AuthCallbackGuard, FullScreenGuard,
ResumableFileUploadService, AuthCallbackGuard,
NgbDateNativeAdapter ResumableFileUploadService,
}; NgbDateNativeAdapter
};
@NgModule({
imports: [ @NgModule({
OAuthModule.forRoot(), imports: [
] OAuthModule.forRoot(),
}) ]
export class AppCommonServiceModule { })
constructor (@Optional() @SkipSelf() parentModule: AppCommonServiceModule) { export class AppCommonServiceModule {
if (parentModule) { constructor (@Optional() @SkipSelf() parentModule: AppCommonServiceModule) {
throw new Error( if (parentModule) {
'AppCommonServiceModule is already loaded. Import it in the AppModule only'); throw new Error(
} 'AppCommonServiceModule is already loaded. Import it in the AppModule only');
} }
static forRoot(): ModuleWithProviders { }
return { static forRoot(): ModuleWithProviders {
ngModule: AppCommonServiceModule, return {
providers: [ ngModule: AppCommonServiceModule,
AppConfig, providers: [
{ AppConfig,
provide: APP_INITIALIZER, {
useFactory: appConfigFactory, provide: APP_INITIALIZER,
deps: [Injector, AppConfig, OAuthService], useFactory: appConfigFactory,
multi: true deps: [Injector, AppConfig, OAuthService,AuthConfigFactory],
}, multi: true
{ },
provide: HTTP_INTERCEPTORS, {
useClass: AccessTokenInterceptor, provide: HTTP_INTERCEPTORS,
multi: true useClass: AccessTokenInterceptor,
}, multi: true
DatePipe },
] DatePipe
}; ]
} };
} }
}

View File

@ -19,6 +19,7 @@ import { MODULE_NAME } from './module-name';
//components //components
import { SafePipe } from './shared/safe.pipe'; import { SafePipe } from './shared/safe.pipe';
import { AuthConfigFactory,IAuthconfigFactory} from './shared/authconfigFactory';
import { AppComponent} from './components/app/app.component'; import { AppComponent} from './components/app/app.component';
import { AuthCallbackComponent } from './components/auth-callback/auth-callback.component'; import { AuthCallbackComponent } from './components/auth-callback/auth-callback.component';
import { SessionClearedComponent } from './components/session-cleared/session-cleared.component'; import { SessionClearedComponent } from './components/session-cleared/session-cleared.component';
@ -62,7 +63,9 @@ export {
ITypeaheadItem, ITypeaheadItem,
IUser, IUser,
commonActions, commonActions,
commonReducers commonReducers,
IAuthconfigFactory,
AuthConfigFactory
}; };
@NgModule({ @NgModule({

View File

@ -1,61 +1,49 @@
import { Injector } from '@angular/core'; import { Injector } from '@angular/core';
import { Router,UrlSerializer } from '@angular/router'; import { Router,UrlSerializer } from '@angular/router';
import { AuthConfig, OAuthService, JwksValidationHandler, OAuthErrorEvent } from 'angular-oauth2-oidc'; import { AuthConfig, OAuthService, JwksValidationHandler, OAuthErrorEvent } from 'angular-oauth2-oidc';
import { AppConfig } from "./app.config"; import { AppConfig } from "./app.config";
import { IAuthconfigFactory } from './authconfigFactory';
function getAuthConfig(appConfig: AppConfig): AuthConfig {
let authConfig: AuthConfig = new AuthConfig();
authConfig.issuer = appConfig.getConfig("issuer"); export function appConfigFactory(injector:Injector, appConfig: AppConfig, oauthService: OAuthService, authconfigFactory:IAuthconfigFactory): () => Promise<any> {
authConfig.redirectUri = window.location.origin + "/cb"; return (): Promise<any> => {
authConfig.silentRefreshRedirectUri = window.location.origin + "/silent-refresh.html"; return appConfig.load().then(() => {
authConfig.clientId = appConfig.getConfig("clientId"); oauthService.events.subscribe((event) => {
authConfig.customQueryParams = { audience: appConfig.getConfig("audience") }; console.debug(event.type);
authConfig.scope = "openid profile email"; if (event.type == 'token_error' || event.type == 'silent_refresh_timeout') {
authConfig.oidc = true; let e = event as OAuthErrorEvent;
authConfig.disableAtHashCheck = true; let p = e.params as any;
authConfig.requireHttps = appConfig.getConfig("requireHttps"); if (event.type == 'silent_refresh_timeout' || (p.error && p.error == 'login_required')) {
return authConfig; let router = injector.get(Router);
} console.debug("Session expired");
router.navigate(['loggedout'], { queryParams: { redirectTo: router.url } });
export function appConfigFactory(injector:Injector, appConfig: AppConfig, oauthService: OAuthService): () => Promise<any> { }
return (): Promise<any> => { }
return appConfig.load().then(() => { });
oauthService.events.subscribe((event) => { oauthService.configure(authconfigFactory.getAuthConfig(appConfig));
console.debug(event.type); oauthService.tokenValidationHandler = new JwksValidationHandler();
if (event.type == 'token_error' || event.type == 'silent_refresh_timeout') { oauthService.tokenValidationHandler.validateAtHash = function () {
let e = event as OAuthErrorEvent; return new Promise<boolean>((res) => { res(true); })
let p = e.params as any; };
if (event.type == 'silent_refresh_timeout' || (p.error && p.error == 'login_required')) { oauthService.setupAutomaticSilentRefresh();
let router = injector.get(Router); let router = injector.get(Router);
console.debug("Session expired"); var urlTree = router.parseUrl(window.location.href);
router.navigate(['loggedout'], { queryParams: { redirectTo: router.url } }); var urlPath = window.location.pathname;
} oauthService.loadDiscoveryDocument().then(() => {
} oauthService.tryLogin({
}); onTokenReceived: (info) => {
oauthService.configure(getAuthConfig(appConfig)); urlPath = info.state;
oauthService.tokenValidationHandler = new JwksValidationHandler(); }
oauthService.tokenValidationHandler.validateAtHash = function () { }).then(() => {
return new Promise<boolean>((res) => { res(true); }) let router = injector.get(Router);
}; if (!oauthService.hasValidAccessToken()) {
oauthService.setupAutomaticSilentRefresh(); oauthService.initImplicitFlow(urlPath);
let router = injector.get(Router); } else {
var urlTree = router.parseUrl(window.location.href); router.navigateByUrl(urlPath);
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);
}
});
})
});
}
}

View File

@ -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;
}
}