Create a new angular service which can hold all of the authentication logic:
ng generate service auth
CREATE src/app/auth.service.spec.ts (347 bytes)
CREATE src/app/auth.service.ts (133 bytes)
Open auth.service.ts
and replace the contents of the file with the code below. Ensure that you place the correct values for issuer
and clientId
within the authConfig
:
import { Injectable } from '@angular/core';
import { OAuthService, AuthConfig, OAuthErrorEvent, OAuthSuccessEvent, NullValidationHandler } from 'angular-oauth2-oidc';
import { Router } from '@angular/router';
import { filter } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthService {
/**
* The OpenID-Connect configuration using the Authorization Code flow
*/
authConfig: AuthConfig = {
issuer: 'http://localhost:8080/auth/realms/my-realm',
redirectUri: window.location.origin + '/callback',
postLogoutRedirectUri: window.location.origin + '/logout',
clientId: 'demo',
scope: 'openid profile email offline_access',
responseType: 'code',
sessionChecksEnabled: true
};
constructor(private oauthService: OAuthService,
private router: Router) {
this.configure();
// For SSO logout
this.oauthService.events.pipe(filter(e => e.type === 'session_changed')).subscribe(e => {
this.logout();
});
}
/**
* Extract the roles from the realm_access claim within the Keycloak generated access token (JWT)
*/
public getClaims(): string[] {
const accessToken: string = this.oauthService.getAccessToken();
const tokens: string[] = accessToken.split('.');
const claims = JSON.parse(atob(tokens[1]));
return claims.realm_access.roles;
}
/**
* Extracts the OpenID Connect clientId from the Keycloak generated access token (JWT)
*/
public getClientId(): string {
const claims = this.getJwtAsObject();
return claims['azp'];
}
/**
* Extracts the JWT Issuer from the Keycloak generated access token
*/
public getIssuer(): string {
const claims = this.getJwtAsObject();
return claims['iss'];
}
/**
* Will kick-off the OpenID Connect Authorization Code flow (Based on the configured authConfig#issuer)
*/
public login(): void {
this.oauthService.initLoginFlow();
}
/**
* Will execute a logout operation by re-directing to Keycloaks logout endpoint and successively to
* to a configured logout path (Configured above in authConfig#postLogoutRedirectUri)
*/
public logout(): void {
this.oauthService.logOut();
}
/**
* Will hook into the OAuth 'token_recieved' event and perform a re-direct to the profile page.
*/
public redirectOnCallback(): void {
this.oauthService.events.subscribe(event => {
if (event instanceof OAuthErrorEvent) {
console.error(event);
} else if (event instanceof OAuthSuccessEvent) {
if (event.type === 'token_received') {
this.router.navigateByUrl('/profile');
}
} else {
console.warn(event);
}
});
}
/**
* Determines if the current user has a valid id token
* Returns true if an IdToken exists within the session storage, false otherwise
*/
public hasValidIdToken(): boolean {
return this.oauthService.hasValidIdToken();
}
/**
* Configures the Angular OpenID Connect client
*/
private configure(): void {
this.oauthService.configure(this.authConfig);
this.oauthService.setupAutomaticSilentRefresh();
this.oauthService.tokenValidationHandler = new NullValidationHandler();
this.oauthService.loadDiscoveryDocumentAndTryLogin().then(() => {
this.oauthService.loadUserProfile();
});
}
/**
* Helper method to extract the claims from the body component of the signed access token
*/
private getJwtAsObject(): object {
const accessToken: string = this.oauthService.getAccessToken();
const tokens: string[] = accessToken.split('.');
return JSON.parse(atob(tokens[1]));
}
}
Comments
0 comments
Please sign in to leave a comment.