reverted to keycloak from angular-oidc due to unfixable infinite loops
This commit is contained in:
parent
5a6ece7daa
commit
0e686008c6
@ -39,14 +39,12 @@ import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
import { environment } from '../environments/environment';
|
||||
import { ProjectDetailsDialogComponent } from './screens/project-overview-screen/project-details-dialog/project-details-dialog.component';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { AuthGuard } from './auth/auth.guard';
|
||||
import { FileUploadModule } from './upload/file-upload.module';
|
||||
import { FullPageLoadingIndicatorComponent } from './utils/full-page-loading-indicator/full-page-loading-indicator.component';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { InitialsAvatarComponent } from './common/initials-avatar/initials-avatar.component';
|
||||
import { StatusBarComponent } from './components/status-bar/status-bar.component';
|
||||
import { LogoComponent } from './logo/logo.component';
|
||||
import { AuthInterceptorService } from './interceptor/auth-interceptor.service';
|
||||
import { CompositeRouteGuard } from './utils/composite-route.guard';
|
||||
import { AppStateGuard } from './state/app-state.guard';
|
||||
import { SimpleDoughnutChartComponent } from './components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
@ -54,6 +52,7 @@ import { ManualRedactionDialogComponent } from './screens/file/manual-redaction-
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { AnnotationIconComponent } from './components/annotation-icon/annotation-icon.component';
|
||||
import { AuthGuard } from "./auth/auth.guard";
|
||||
|
||||
export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||
@ -157,10 +156,6 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
multi: true,
|
||||
useClass: ApiPathInterceptorService
|
||||
}, {
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
multi: true,
|
||||
useClass: AuthInterceptorService
|
||||
}, {
|
||||
provide: APP_INITIALIZER,
|
||||
multi: true,
|
||||
|
||||
@ -1,78 +1,30 @@
|
||||
import {Injectable} from "@angular/core";
|
||||
import {ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree} from "@angular/router";
|
||||
import {Observable} from "rxjs";
|
||||
import {AuthConfig, OAuthService} from "angular-oauth2-oidc";
|
||||
import {AppConfigKey, AppConfigService} from "../app-config/app-config.service";
|
||||
import {map} from "rxjs/operators";
|
||||
import {ActivatedRouteSnapshot, Router, RouterStateSnapshot} from "@angular/router";
|
||||
import {KeycloakAuthGuard, KeycloakService} from "keycloak-angular";
|
||||
import {UserService} from "../user/user.service";
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AuthGuard implements CanActivate {
|
||||
|
||||
private _configured = false;
|
||||
|
||||
constructor(private readonly _oauthService: OAuthService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _appConfigService: AppConfigService) {
|
||||
export class AuthGuard extends KeycloakAuthGuard {
|
||||
constructor(
|
||||
protected readonly _router: Router,
|
||||
protected readonly _keycloak: KeycloakService,
|
||||
private readonly _userService: UserService
|
||||
) {
|
||||
super(_router, _keycloak);
|
||||
}
|
||||
|
||||
private async _configure() {
|
||||
this._configured = true;
|
||||
const authConfig = await this._createConfiguration().toPromise();
|
||||
this._oauthService.configure(authConfig);
|
||||
this._oauthService.setupAutomaticSilentRefresh();
|
||||
public async isAccessAllowed(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
|
||||
|
||||
window['silentRefresh'] =() =>{
|
||||
this
|
||||
._oauthService
|
||||
.silentRefresh()
|
||||
.then(info => console.log('refresh ok', info))
|
||||
.catch(err => console.log('refresh error', err));
|
||||
};
|
||||
|
||||
return this._oauthService.loadDiscoveryDocumentAndTryLogin();
|
||||
}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
||||
if (!this._configured) {
|
||||
return this._configure().then(() => this._checkToken());
|
||||
if (!this.authenticated) {
|
||||
await this._keycloak.login({
|
||||
redirectUri: window.location.origin + state.url,
|
||||
});
|
||||
}
|
||||
|
||||
return this._checkToken();
|
||||
}
|
||||
await this._userService.loadCurrentUser();
|
||||
|
||||
private async _checkToken() {
|
||||
const timeLeft= ((this._oauthService.getAccessTokenExpiration() - new Date().getTime()) / 1000);
|
||||
const expired = timeLeft < 60;
|
||||
|
||||
if (!this._oauthService.getAccessToken() || expired) {
|
||||
this._oauthService.initLoginFlow();
|
||||
return false;
|
||||
}
|
||||
if (!this._userService.user) {
|
||||
await this._userService.loadCurrentUser();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private _createConfiguration(): Observable<AuthConfig> {
|
||||
return this._appConfigService.loadAppConfig().pipe(map(config => {
|
||||
return {
|
||||
issuer: config[AppConfigKey.OAUTH_URL],
|
||||
redirectUri: window.location.origin,
|
||||
clientId: config[AppConfigKey.OAUTH_CLIENT_ID],
|
||||
scope: 'openid profile email offline_access',
|
||||
responseType: 'code',
|
||||
showDebugInformation: true,
|
||||
silentRefreshRedirectUri: window.location.origin + '/assets/oauth/silent-refresh.html',
|
||||
useSilentRefresh: true,
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,28 +1,55 @@
|
||||
import {NgModule} from "@angular/core";
|
||||
import {APP_INITIALIZER, NgModule} from "@angular/core";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {HttpClientModule} from "@angular/common/http";
|
||||
import {OAuthModule} from "angular-oauth2-oidc";
|
||||
import {AuthGuard} from "./auth.guard";
|
||||
import {AppConfigModule} from "../app-config/app-config.module";
|
||||
|
||||
|
||||
import {KeycloakService} from "keycloak-angular";
|
||||
import {AppConfigKey, AppConfigService} from "../app-config/app-config.service";
|
||||
|
||||
|
||||
export function keycloakInitializer(keycloak: KeycloakService, appConfigService: AppConfigService) {
|
||||
return () => {
|
||||
return appConfigService.loadAppConfig().toPromise().then(() => {
|
||||
|
||||
let url = appConfigService.getConfig(AppConfigKey.OAUTH_URL);
|
||||
url = url.replace(/\/$/, ""); // remove trailing slash
|
||||
const realm = url.substring(url.lastIndexOf("/") + 1, url.length);
|
||||
url = url.substr(0, url.lastIndexOf("/"));
|
||||
return keycloak.init({
|
||||
config: {
|
||||
url: url,
|
||||
realm: realm,
|
||||
clientId: appConfigService.getConfig(AppConfigKey.OAUTH_CLIENT_ID)
|
||||
},
|
||||
initOptions: {
|
||||
checkLoginIframe: false,
|
||||
onLoad: 'check-sso',
|
||||
silentCheckSsoRedirectUri:
|
||||
window.location.origin + '/assets/keycloak/silent-check-sso.html',
|
||||
flow: 'standard'
|
||||
},
|
||||
enableBearerInterceptor: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
CommonModule,
|
||||
HttpClientModule,
|
||||
AppConfigModule,
|
||||
OAuthModule.forRoot(
|
||||
{
|
||||
resourceServer: {
|
||||
allowedUrls: ['/'],
|
||||
sendAccessToken: true
|
||||
}
|
||||
}
|
||||
)
|
||||
],
|
||||
providers: [
|
||||
AuthGuard
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: keycloakInitializer,
|
||||
multi: true,
|
||||
deps: [KeycloakService, AppConfigService],
|
||||
},
|
||||
],
|
||||
})
|
||||
export class AuthModule {
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Observable, of} from 'rxjs';
|
||||
import {AppConfigService} from "../app-config/app-config.service";
|
||||
import {catchError} from "rxjs/operators";
|
||||
import {OAuthService} from "angular-oauth2-oidc";
|
||||
|
||||
@Injectable()
|
||||
export class AuthInterceptorService implements HttpInterceptor {
|
||||
|
||||
constructor(private readonly _appConfigService: AppConfigService, private readonly _oauthService: OAuthService) {
|
||||
}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
return next.handle(req).pipe(catchError((err: any) => {
|
||||
if (err instanceof HttpErrorResponse) {
|
||||
if (err.status === 401) {
|
||||
this._oauthService.initLoginFlow();
|
||||
}
|
||||
}
|
||||
return of(err);
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -1,22 +1,37 @@
|
||||
import {Injectable} from "@angular/core";
|
||||
import {OAuthService, UserInfo} from "angular-oauth2-oidc";
|
||||
import {KeycloakService} from "keycloak-angular";
|
||||
import {KeycloakProfile} from "keycloak-js";
|
||||
|
||||
|
||||
export class UserWrapper {
|
||||
|
||||
constructor(private _currentUser: KeycloakProfile, public roles: string[]) {
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._currentUser.firstName + " " + this._currentUser.lastName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UserService {
|
||||
|
||||
private _currentUser: UserInfo;
|
||||
private _currentUser: UserWrapper;
|
||||
|
||||
constructor(private _oauthService: OAuthService) {
|
||||
constructor(private _keycloakService: KeycloakService) {
|
||||
}
|
||||
|
||||
logout() {
|
||||
this._oauthService.logOut();
|
||||
this._keycloakService.logout();
|
||||
}
|
||||
|
||||
async loadCurrentUser() {
|
||||
this._currentUser = await this._oauthService.loadUserProfile();
|
||||
this._currentUser = new UserWrapper(await this._keycloakService.loadUserProfile(false),this._keycloakService.getUserRoles(true));
|
||||
console.log(this._currentUser);
|
||||
}
|
||||
|
||||
get user() {
|
||||
|
||||
@ -43,9 +43,9 @@
|
||||
"@ngx-translate/http-loader": "^6.0.0",
|
||||
"@nrwl/angular": "^10.2.0",
|
||||
"@pdftron/webviewer": "^7.0.1",
|
||||
"angular-oauth2-oidc": "^10.0.3",
|
||||
"angular-oauth2-oidc-jwks": "^9.0.0",
|
||||
"file-saver": "^2.0.2",
|
||||
"keycloak-angular": "^8.0.1",
|
||||
"keycloak-js": "^11.0.2",
|
||||
"ng2-file-upload": "^1.4.0",
|
||||
"ngp-sort-pipe": "^0.0.4",
|
||||
"ngx-dropzone": "^2.2.2",
|
||||
|
||||
@ -2,7 +2,10 @@
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
|
||||
41
yarn.lock
41
yarn.lock
@ -2263,20 +2263,6 @@ alphanum-sort@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
|
||||
integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=
|
||||
|
||||
angular-oauth2-oidc-jwks@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/angular-oauth2-oidc-jwks/-/angular-oauth2-oidc-jwks-9.0.0.tgz#f11e4e561ff423928ab63ca2cca84703a00ff85d"
|
||||
integrity sha512-3hTJc7vEI/ka/nnliMcCQuDnszzL3AhGInBBbn96BO+ZOdvP/4PbEumUsDto2WRpPMPxD6HAmExwYeQWljcc5A==
|
||||
dependencies:
|
||||
jsrsasign "^8.0.12"
|
||||
|
||||
angular-oauth2-oidc@^10.0.3:
|
||||
version "10.0.3"
|
||||
resolved "https://registry.yarnpkg.com/angular-oauth2-oidc/-/angular-oauth2-oidc-10.0.3.tgz#612ef75c2e07b56592d2506f9618ee6a61857ad9"
|
||||
integrity sha512-9wC8I3e3cN6rMBOlo5JB2y3Fd2erp8pJ67t4vEVzyPbnRG6BJ4rreSOznSL9zw/2SjhC9kRV2OfFie29CUCzEg==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
ansi-colors@4.1.1, ansi-colors@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||
@ -2694,7 +2680,7 @@ balanced-match@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
base64-js@^1.0.2:
|
||||
base64-js@1.3.1, base64-js@^1.0.2:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
|
||||
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
|
||||
@ -6787,6 +6773,11 @@ jest@26.2.2:
|
||||
import-local "^3.0.2"
|
||||
jest-cli "^26.2.2"
|
||||
|
||||
js-sha256@0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966"
|
||||
integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
@ -6937,11 +6928,6 @@ jsprim@^1.2.2:
|
||||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
jsrsasign@^8.0.12:
|
||||
version "8.0.24"
|
||||
resolved "https://registry.yarnpkg.com/jsrsasign/-/jsrsasign-8.0.24.tgz#fc26bac45494caac3dd8f69c1f95847c4bda6c83"
|
||||
integrity sha512-u45jAyusqUpyGbFc2IbHoeE4rSkoBWQgLe/w99temHenX+GyCz4nflU5sjK7ajU1ffZTezl6le7u43Yjr/lkQg==
|
||||
|
||||
karma-source-map-support@1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz#58526ceccf7e8730e56effd97a4de8d712ac0d6b"
|
||||
@ -6949,6 +6935,21 @@ karma-source-map-support@1.4.0:
|
||||
dependencies:
|
||||
source-map-support "^0.5.5"
|
||||
|
||||
keycloak-angular@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/keycloak-angular/-/keycloak-angular-8.0.1.tgz#29851e7aded21925faa051c69dfa5872bda6661f"
|
||||
integrity sha512-q68vcaFiSYNjbzPM1v+6LohMpWUyus9hcQBi2rNz06xOtWuRU4U6t5vQgoim6bDhtkhWpR5+a3SYl0lzUJKyrw==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
keycloak-js@^11.0.2:
|
||||
version "11.0.2"
|
||||
resolved "https://registry.yarnpkg.com/keycloak-js/-/keycloak-js-11.0.2.tgz#e981c5270e72066e38b2a1bd98f1138d6cd560c1"
|
||||
integrity sha512-dnvzgTetovu3eTjJtvBQQhxRN4jqvd/DaA2wFaE4aWIFXhwRcoPpZT8ZJ7MwlICDPdCgzbCsOsBjpL8CbYOZsg==
|
||||
dependencies:
|
||||
base64-js "1.3.1"
|
||||
js-sha256 "0.9.0"
|
||||
|
||||
killable@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user