Resubida app de ejemplo, la anterior no logueaba.

This commit is contained in:
Eneko Nieto
2021-01-20 10:38:04 +01:00
parent 88949dbadf
commit a70f652221
35 changed files with 1762 additions and 1163 deletions

View File

@@ -1,35 +1,28 @@
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { AppModule } from './app.module';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [AppModule]
}).compileComponents();
});
}));
it('should create the app', () => {
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
}));
it(`should have as title 'okupamicoche-angular'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('okupamicoche-angular');
});
it('should render title', () => {
it('should render link to flight in a a tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('okupamicoche-angular app is running!');
});
const compiled = fixture.debugElement.nativeElement;
console.log(compiled);
expect(compiled.querySelectorAll(' li a')[2].textContent).toContain(
'Book a Flight'
);
}));
});

View File

@@ -1,32 +1,39 @@
import { noDiscoveryAuthConfig } from './auth-no-discovery.config';
import { authConfig } from './auth.config';
import { Component } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { OAuthService, NullValidationHandler } from 'angular-oauth2-oidc';
import { Router } from '@angular/router';
import { filter } from 'rxjs/operators';
import { authCodeFlowConfig } from './auth-code-flow.config';
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
import { useHash } from '../flags';
@Component({
// tslint:disable-next-line:component-selector
selector: 'app-root',
templateUrl: './app.component.html',
selector: 'flight-app',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(private router: Router, private oauthService: OAuthService) {
this.configureCodeFlow();
// Remember the selected configuration
if (sessionStorage.getItem('flow') === 'code') {
this.configureCodeFlow();
} else {
this.configureImplicitFlow();
}
// Automatically load user profile
this.oauthService.events
.pipe(filter((e) => e.type === 'token_received'))
.subscribe((_) => {
console.log('state', this.oauthService.state);
.pipe(filter(e => e.type === 'token_received'))
.subscribe(_ => {
console.debug('state', this.oauthService.state);
this.oauthService.loadUserProfile();
});
}
private configureCodeFlow(): void {
private configureCodeFlow() {
this.oauthService.configure(authCodeFlowConfig);
this.oauthService.loadDiscoveryDocumentAndTryLogin().then((success) => {
console.error('LOGIN success=' + success);
this.oauthService.loadDiscoveryDocumentAndTryLogin().then(_ => {
if (useHash) {
this.router.navigate(['/']);
}
@@ -35,4 +42,95 @@ export class AppComponent {
// Optional
this.oauthService.setupAutomaticSilentRefresh();
}
private configureImplicitFlow() {
this.oauthService.configure(authConfig);
this.oauthService.setStorage(localStorage);
// this.oauthService.tokenValidationHandler = new JwksValidationHandler();
this.oauthService.loadDiscoveryDocumentAndTryLogin().then(_ => {
if (useHash) {
this.router.navigate(['/']);
}
});
// Optional
this.oauthService.setupAutomaticSilentRefresh();
// Display all events
this.oauthService.events.subscribe(e => {
// tslint:disable-next-line:no-console
console.debug('oauth/oidc event', e);
});
this.oauthService.events
.pipe(filter(e => e.type === 'session_terminated'))
.subscribe(e => {
// tslint:disable-next-line:no-console
console.debug('Your session has been terminated!');
});
}
//
// Below you find further examples for configuration functions
//
private configureWithoutDiscovery() {
this.oauthService.configure(noDiscoveryAuthConfig);
this.oauthService.tokenValidationHandler = new NullValidationHandler();
this.oauthService.tryLogin();
}
private configureAuth() {
//
// This method demonstrated the old API; see configureWithNewConfigApi for new one
//
// URL of the SPA to redirect the user to after login
this.oauthService.redirectUri = window.location.origin + '/index.html';
// URL of the SPA to redirect the user after silent refresh
this.oauthService.silentRefreshRedirectUri =
window.location.origin + '/silent-refresh.html';
// The SPA's id. The SPA is registerd with this id at the auth-server
this.oauthService.clientId = 'spa-demo';
// set the scope for the permissions the client should request
// The first three are defined by OIDC. The 4th is a usecase-specific one
this.oauthService.scope = 'openid profile email voucher';
// Url of the Identity Provider
this.oauthService.issuer =
'https://steyer-identity-server.azurewebsites.net/identity';
this.oauthService.tokenValidationHandler = new NullValidationHandler();
this.oauthService.events.subscribe(e => {
// tslint:disable-next-line:no-console
console.debug('oauth/oidc event', e);
});
// Load Discovery Document and then try to login the user
this.oauthService.loadDiscoveryDocument().then(doc => {
this.oauthService.tryLogin();
});
this.oauthService.events
.pipe(filter(e => e.type === 'token_expires'))
.subscribe(e => {
// tslint:disable-next-line:no-console
console.debug('received token_expires event', e);
this.oauthService.silentRefresh();
});
}
private configurePasswordFlow() {
// Set a dummy secret
// Please note that the auth-server used here demand the client to transmit a client secret, although
// the standard explicitly cites that the password flow can also be used without it. Using a client secret
// does not make sense for a SPA that runs in the browser. That's why the property is called dummyClientSecret
// Using such a dummy secreat is as safe as using no secret.
this.oauthService.dummyClientSecret = 'geheim';
}
}

View File

@@ -1,7 +1,7 @@
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { OAuthModule } from 'angular-oauth2-oidc';
import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
@@ -9,14 +9,17 @@ import { APP_ROUTES } from './app.routes';
import { BASE_URL } from './app.tokens';
import { FlightHistoryComponent } from './flight-history/flight-history.component';
import { HomeComponent } from './home/home.component';
import { PasswordFlowLoginComponent } from './password-flow-login/password-flow-login.component';
import { SharedModule } from './shared/shared.module';
import { RouterModule, ExtraOptions } from '@angular/router';
import { CustomPreloadingStrategy } from './shared/preload/custom-preloading.strategy';
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
import { useHash } from '../flags';
const ROUTING_OPTIONS: ExtraOptions = {
// preloadingStrategy: CustomPreloadingStrategy,
useHash,
initialNavigation: 'enabled'
useHash: useHash,
initialNavigation: !useHash
};
@NgModule({
@@ -29,7 +32,7 @@ const ROUTING_OPTIONS: ExtraOptions = {
SharedModule.forRoot(),
OAuthModule.forRoot({
resourceServer: {
allowedUrls: ['http://localhost:8080/api'],
allowedUrls: ['http://www.angular.at/api'],
sendAccessToken: true
}
})
@@ -37,14 +40,15 @@ const ROUTING_OPTIONS: ExtraOptions = {
declarations: [
AppComponent,
HomeComponent,
FlightHistoryComponent
FlightHistoryComponent,
PasswordFlowLoginComponent
],
providers: [
// (useHash) ? { provide: LocationStrategy, useClass: HashLocationStrategy } : [],
// {provide: AuthConfig, useValue: authConfig },
// { provide: OAuthStorage, useValue: localStorage },
// { provide: ValidationHandler, useClass: JwksValidationHandler },
{ provide: BASE_URL, useValue: 'http://localhost:8080' }
{ provide: BASE_URL, useValue: 'http://www.angular.at' }
],
bootstrap: [AppComponent]
})

View File

@@ -1,4 +1,5 @@
import { Routes } from '@angular/router';
import { PasswordFlowLoginComponent } from './password-flow-login/password-flow-login.component';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { FlightHistoryComponent } from './flight-history/flight-history.component';
@@ -12,6 +13,10 @@ export let APP_ROUTES: Routes = [
path: 'home',
component: HomeComponent
},
{
path: 'password-flow-login',
component: PasswordFlowLoginComponent
},
{
path: 'flight-booking',
loadChildren: () =>

View File

@@ -1,3 +1,3 @@
import { InjectionToken } from '@angular/core';
export const BASE_URL = new InjectionToken<string>('http://localhost:8080');
export const BASE_URL = new InjectionToken<string>('BASE_URL');

View File

@@ -28,8 +28,8 @@ export const authCodeFlowConfig: AuthConfig = {
// Important: Request offline_access to get a refresh token
// The api scope is a usecase specific one
scope: useSilentRefreshForCodeFlow
? 'openid profile email'
: 'openid profile email offline_access',
? 'openid profile email api'
: 'openid profile email offline_access api',
// ^^ Please note that offline_access is not needed for silent refresh
// At least when using idsvr, this even prevents silent refresh

View File

@@ -0,0 +1,69 @@
import { AuthConfig } from 'angular-oauth2-oidc';
export const noDiscoveryAuthConfig: AuthConfig = {
clientId:
'1004270452653-m396kcs7jc3970turlp7ffh6bv4t1b86.apps.googleusercontent.com',
redirectUri: 'http://localhost:4200/index.html',
postLogoutRedirectUri: '',
loginUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
scope: 'openid profile email',
resource: '',
rngUrl: '',
oidc: true,
requestAccessToken: true,
options: null,
issuer: 'https://accounts.google.com',
clearHashAfterLogin: true,
tokenEndpoint: 'https://www.googleapis.com/oauth2/v4/token',
userinfoEndpoint: 'https://www.googleapis.com/oauth2/v3/userinfo',
responseType: 'token',
showDebugInformation: true,
silentRefreshRedirectUri: 'http://localhost:4200/silent-refresh.html',
silentRefreshMessagePrefix: '',
silentRefreshShowIFrame: false,
silentRefreshTimeout: 20000,
dummyClientSecret: null,
requireHttps: 'remoteOnly',
strictDiscoveryDocumentValidation: false,
jwks: {
keys: [
{
kty: 'RSA',
alg: 'RS256',
use: 'sig',
kid: '7540561fdb04b89d824a1b7b9e8849873e7cb50e',
n:
// tslint:disable-next-line: max-line-length
'sSFZrLIrXzvXBCehdPR10T-mfHWFU5ZtGzW9buI7wT_tJzZ1SRUc2l1NH92kGV9bmWRtDLjWcWFwMG7rbjX25-R-62lD1k15gQiO4bhx7gbV05e36os2vXTs0ypj9GS9y8X_2fYAnxxulMLwz4m24Ejo2tQI43-V-3Tec6cSXe0FjhRaPbGdS8GHPDKkhpJ1NHMZ38vhddIImOfvtVuz3lt_zwjBsAC6Q7PHs2GOm3KtC22DCwXMYSri4QOQcasuvTlZxIQSIksTyuH0T02IH5SJvQZSx46Vfq8BM4JP-zEEjzadoyxQPouRM6TrUeaqNv5B1f1lbH6G0G_r_ddYWQ',
e: 'AQAB'
},
{
kty: 'RSA',
alg: 'RS256',
use: 'sig',
kid: '778233e8f6f342ea09e867aad25f543adeebf372',
n:
// tslint:disable-next-line: max-line-length
'8MMxQ9F7R1zJ57QvLX-HqUlTVLLofCzZ3-lxohJr8ivJDGZoCqll7ZTNO0nGMgnPpIO-3BQLkaNGQDCpnID1vNIjClFFl0E3cN5bDX15uxCQeQDsm25fTlphpy5FkdoHCviswtrsl2KKUPeRlKqCqMjlDO27KuxIwzIPdNSqv4tseZmI-biFt2JlO9htgODrVqaawdm27t9HcWfOK_a5czRFDHWck2-ZwjbCOF9CtF1ggYm11aV0TElExXr5fgjAQdZ1yGmJvir127BRUgyIy5cpyf7VRRf2Cv7whSMoVJr4W3OK0H9vkuFLnlBiBNYQmH_eWy5U4jBfZjBqvA7Oww',
e: 'AQAB'
},
{
kty: 'RSA',
alg: 'RS256',
use: 'sig',
kid: '8ec17994394464d95b0b3d906326f1cdde8aee64',
n:
// tslint:disable-next-line: max-line-length
'w49KfvzGWVXH4vyUxvP29_QTmJfvLp4RPT1WlI6Wo2aNvn6j9vRSLDrK2CnOvvrrlUKvR-8FTcyNi9pRKXDwDhEJcyVFBJVi4PqDh0KIX_dOGYCulr5FUvU0HXQxlMWSHIsJjfGbMMUwM0p09y8KHL-kipiipzn80EpBmrI4Q3t6XOAZJSmbIPaGZJDjyoWWV0TDdVDBMfkqII6tOOB7Ha189AZjz7FHYXR9CIc0Jm6rFy0tVpdHFEG3ptcNQEDQ5ghyMM4PDM4ZmQ5uk3WgHVqnpdmGEfKekLwmYFWgnI-ux_MabltIxr9TE1qubEmebM64rOusHBF0mSbEwggbyw',
e: 'AQAB'
}
]
},
customQueryParams: null,
silentRefreshIFrameName: 'angular-oauth-oidc-silent-refresh-iframe',
timeoutFactor: 0.75,
sessionCheckIntervall: 3000,
sessionCheckIFrameName: 'angular-oauth-oidc-check-session-iframe',
disableAtHashCheck: false,
skipSubjectCheck: false
};

View File

@@ -0,0 +1,27 @@
// This api will come in the next version
import { AuthConfig } from 'angular-oauth2-oidc';
export const authPasswordFlowConfig: AuthConfig = {
// Url of the Identity Provider
issuer: 'https://steyer-identity-server.azurewebsites.net/identity',
// URL of the SPA to redirect the user to after login
redirectUri: window.location.origin + '/index.html',
// URL of the SPA to redirect the user after silent refresh
silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html',
// The SPA's id. The SPA is registerd with this id at the auth-server
clientId: 'demo-resource-owner',
dummyClientSecret: 'geheim',
// set the scope for the permissions the client should request
// The first three are defined by OIDC. The 4th is a usecase-specific one
scope: 'openid profile email voucher',
showDebugInformation: true,
oidc: false
};

34
src/app/auth.config.ts Normal file
View File

@@ -0,0 +1,34 @@
// This api will come in the next version
import { AuthConfig } from 'angular-oauth2-oidc';
export const authConfig: AuthConfig = {
// Url of the Identity Provider
issuer: 'https://idsvr4.azurewebsites.net',
// URL of the SPA to redirect the user to after login
// redirectUri: window.location.origin
// + ((localStorage.getItem('useHashLocationStrategy') === 'true')
// ? '/#/index.html'
// : '/index.html'),
redirectUri: window.location.origin + '/index.html',
// URL of the SPA to redirect the user after silent refresh
silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html',
// The SPA's id. The SPA is registerd with this id at the auth-server
clientId: 'implicit',
// set the scope for the permissions the client should request
// The first three are defined by OIDC. The 4th is a usecase-specific one
scope: 'openid profile email api',
// silentRefreshShowIFrame: true,
showDebugInformation: true,
sessionChecksEnabled: true
// timeoutFactor: 0.01,
};

View File

@@ -0,0 +1,28 @@
// This api will come in the next version
import { AuthConfig } from 'angular-oauth2-oidc';
export const googleAuthConfig: AuthConfig = {
// Url of the Identity Provider
issuer: 'https://accounts.google.com',
// URL of the SPA to redirect the user to after login
redirectUri: window.location.origin + '/index.html',
// URL of the SPA to redirect the user after silent refresh
silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html',
// The SPA's id. The SPA is registerd with this id at the auth-server
clientId:
'1004270452653-m396kcs7jc3970turlp7ffh6bv4t1b86.apps.googleusercontent.com',
strictDiscoveryDocumentValidation: false,
// set the scope for the permissions the client should request
// The first three are defined by OIDC. The 4th is a usecase-specific one
scope: 'openid profile email',
showDebugInformation: true,
sessionChecksEnabled: true
};

View File

@@ -27,6 +27,34 @@
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<h2>Login with Implicit Flow</h2>
<p>
<button class="btn btn-default" (click)="loginImplicit()">Login</button>
<button class="btn btn-default" (click)="logout()">Logout</button>
</p>
<b>Username/Password:</b> max/geheim
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<h2>Login with Implicit Flow in popup</h2>
<p>
<button class="btn btn-default" (click)="loginImplicitInPopup()">
Login
</button>
<button class="btn btn-default" (click)="logout()">Logout</button>
</p>
<p><b>Username/Password:</b> max/geheim</p>
<p>
<b>Note:</b> When using IE, some security settings block the communication
with popups. This prevents that this feature works.
</p>
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<h2>Login with Code Flow</h2>

View File

@@ -1,3 +1,4 @@
import { authConfig } from '../auth.config';
import { Component, OnInit } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { authCodeFlowConfig } from '../auth-code-flow.config';
@@ -7,7 +8,7 @@ import { ActivatedRoute } from '@angular/router';
templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {
loginFailed = false;
loginFailed: boolean = false;
userProfile: object;
usePopup: boolean;
login: false;
@@ -17,9 +18,9 @@ export class HomeComponent implements OnInit {
private oauthService: OAuthService
) {}
ngOnInit(): void {
ngOnInit() {
this.route.params.subscribe(p => {
this.login = p.login;
this.login = p['login'];
});
// This would directly (w/o user interaction) redirect the user to the
@@ -33,7 +34,29 @@ export class HomeComponent implements OnInit {
*/
}
async loginCode(): Promise<void> {
async loginImplicit() {
// Tweak config for implicit flow
this.oauthService.configure(authConfig);
await this.oauthService.loadDiscoveryDocument();
sessionStorage.setItem('flow', 'implicit');
this.oauthService.initLoginFlow('/some-state;p1=1;p2=2?p3=3&p4=4');
// the parameter here is optional. It's passed around and can be used after logging in
}
async loginImplicitInPopup() {
// Tweak config for implicit flow
this.oauthService.configure(authConfig);
await this.oauthService.loadDiscoveryDocument();
sessionStorage.setItem('flow', 'implicit');
this.oauthService.initLoginFlowInPopup().then(() => {
this.loadUserProfile();
});
// the parameter here is optional. It's passed around and can be used after logging in
}
async loginCode() {
// Tweak config for code flow
this.oauthService.configure(authCodeFlowConfig);
await this.oauthService.loadDiscoveryDocument();
@@ -43,7 +66,7 @@ export class HomeComponent implements OnInit {
// the parameter here is optional. It's passed around and can be used after logging in
}
async loginCodeInPopup(): Promise<void> {
async loginCodeInPopup() {
// Tweak config for code flow
this.oauthService.configure(authCodeFlowConfig);
await this.oauthService.loadDiscoveryDocument();
@@ -54,7 +77,7 @@ export class HomeComponent implements OnInit {
});
}
logout(): void {
logout() {
// this.oauthService.logOut();
this.oauthService.revokeTokenAndLogout();
}
@@ -63,19 +86,19 @@ export class HomeComponent implements OnInit {
this.oauthService.loadUserProfile().then(up => (this.userProfile = up));
}
get givenName(): any {
const claims = this.oauthService.getIdentityClaims();
if (!claims) { return null; }
get givenName() {
var claims = this.oauthService.getIdentityClaims();
if (!claims) return null;
return claims['given_name'];
}
get familyName(): any {
const claims = this.oauthService.getIdentityClaims();
if (!claims) { return null; }
get familyName() {
var claims = this.oauthService.getIdentityClaims();
if (!claims) return null;
return claims['family_name'];
}
refresh(): void {
refresh() {
this.oauthService.oidc = true;
if (
@@ -84,12 +107,12 @@ export class HomeComponent implements OnInit {
) {
this.oauthService
.refreshToken()
.then(info => console.log('refresh ok', info))
.then(info => console.debug('refresh ok', info))
.catch(err => console.error('refresh error', err));
} else {
this.oauthService
.silentRefresh()
.then(info => console.log('silent refresh ok', info))
.then(info => console.debug('silent refresh ok', info))
.catch(err => console.error('silent refresh error', err));
}
}
@@ -99,7 +122,7 @@ export class HomeComponent implements OnInit {
localStorage.setItem('requestAccessToken', '' + value);
}
get requestAccessToken(): boolean {
get requestAccessToken() {
return this.oauthService.requestAccessToken;
}
@@ -111,23 +134,23 @@ export class HomeComponent implements OnInit {
}
}
get useHashLocationStrategy(): boolean {
get useHashLocationStrategy() {
return localStorage.getItem('useHashLocationStrategy') === 'true';
}
get id_token(): string {
get id_token() {
return this.oauthService.getIdToken();
}
get access_token(): string {
get access_token() {
return this.oauthService.getAccessToken();
}
get id_token_expiration(): number {
get id_token_expiration() {
return this.oauthService.getIdTokenExpiration();
}
get access_token_expiration(): number {
get access_token_expiration() {
return this.oauthService.getAccessTokenExpiration();
}
}

View File

@@ -0,0 +1,47 @@
<h1 *ngIf="!givenName">Welcome!</h1>
<h1 *ngIf="givenName">Welcome, {{ givenName }} {{ familyName }}!</h1>
<div class="panel panel-default">
<div class="panel-body">
<p>Login with Username/Password</p>
<p style="color:red; font-weight:bold" *ngIf="loginFailed">
Login wasn't successfull.
</p>
<div class="form-group">
<label>Username</label>
<input class="form-control" [(ngModel)]="userName" />
</div>
<div class="form-group">
<label>Password</label>
<input class="form-control" type="password" [(ngModel)]="password" />
</div>
<div class="form-group">
<button class="btn btn-default" (click)="loginWithPassword()">
Login
</button>
<button class="btn btn-default" (click)="logout()">Logout</button>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-body"><b>Username/Password:</b> max/geheim</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<p><b>access_token_expiration:</b> {{ access_token_expiration }}</p>
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<p><b>access_token:</b> {{ access_token }}</p>
<div *ngIf="userProfile">
<b>user profile:</b>
<pre>{{ userProfile | json }}</pre>
</div>
</div>
</div>

View File

@@ -0,0 +1,69 @@
import { authPasswordFlowConfig } from '../auth-password-flow.config';
import { OAuthService } from 'angular-oauth2-oidc';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-password-flow-login',
templateUrl: './password-flow-login.component.html'
})
export class PasswordFlowLoginComponent implements OnInit {
userName: string;
password: string;
loginFailed: boolean = false;
userProfile: object;
constructor(private oauthService: OAuthService) {
// Tweak config for password flow
// This is just needed b/c this demo uses both,
// implicit flow as well as password flow
this.oauthService.configure(authPasswordFlowConfig);
this.oauthService.loadDiscoveryDocument();
}
ngOnInit() {}
loadUserProfile(): void {
this.oauthService.loadUserProfile().then(up => (this.userProfile = up));
}
get access_token() {
return this.oauthService.getAccessToken();
}
get access_token_expiration() {
return this.oauthService.getAccessTokenExpiration();
}
get givenName() {
var claims = this.oauthService.getIdentityClaims();
if (!claims) return null;
return claims['given_name'];
}
get familyName() {
var claims = this.oauthService.getIdentityClaims();
if (!claims) return null;
return claims['family_name'];
}
loginWithPassword() {
this.oauthService
.fetchTokenUsingPasswordFlowAndLoadUserProfile(
this.userName,
this.password
)
.then(() => {
console.debug('successfully logged in');
this.loginFailed = false;
})
.catch(err => {
console.error('error logging in', err);
this.loginFailed = true;
});
}
logout() {
this.oauthService.logOut(true);
}
}

View File

@@ -6,7 +6,7 @@ import { OAuthService } from 'angular-oauth2-oidc';
export class AuthGuard implements CanActivate {
constructor(private router: Router, private oauthService: OAuthService) {}
canActivate(): boolean {
canActivate() {
if (
this.oauthService.hasValidAccessToken() &&
this.oauthService.hasValidIdToken()