Auto redirect to an STS server in an Angular app using oidc Implicit Flow

This article shows how to implement an auto redirect in an Angular application, if using the OIDC Implicit Flow with an STS server. When a user opens the application, it is sometimes required that the user is automatically redirected to the login page on the STS server. This can be tricky to implement, as you need to know when to redirect and when not. The OIDC client is implemented using the angular-auth-oidc-client npm package.

Code: https://github.com/damienbod/angular-auth-oidc-sample-google-openid

The angular-auth-oidc-client npm package provides an event when the OIDC module is ready to use and also can be configured to emit an event to inform the using component when the callback from the STS server has been processed. These 2 events, can be used to implement the auto redirect to the STS server, when not authorized.

The app.component can subscribe to these 2 events in the constructor.

constructor(public oidcSecurityService: OidcSecurityService,
	private router: Router
) {
	if (this.oidcSecurityService.moduleSetup) {
		this.onOidcModuleSetup();
	} else {
		this.oidcSecurityService.onModuleSetup.subscribe(() => {
			this.onOidcModuleSetup();
		});
	}

	this.oidcSecurityService.onAuthorizationResult.subscribe(
		(authorizationResult: AuthorizationResult) => {
			this.onAuthorizationResultComplete(authorizationResult);
		});
}

The onOidcModuleSetup function handles the onModuleSetup event. The Angular app is configured not to use hash (#) urls so that the STS callback is the only redirect which uses the hash. Due to this, all urls with a hash can be sent on to be processed from the OIDC module. If any other path is called, apart from the auto-login, the path is saved to the local storage. This is done so that after a successful token validation, the user is redirected back to the correct route. If the user is not authorized, the auto-login component is called.

private onOidcModuleSetup() {
	if (window.location.hash) {
		this.oidcSecurityService.authorizedCallback();
	} else {
		if ('/autologin' !== window.location.pathname) {
			this.write('redirect', window.location.pathname);
		}
		console.log('AppComponent:onModuleSetup');
		this.oidcSecurityService.getIsAuthorized().subscribe((authorized: boolean) => {
			if (!authorized) {
				this.router.navigate(['/autologin']);
			}
		});
	}
}

The onAuthorizationResultComplete function handles the onAuthorizationResult event. If the response from the server is valid, the user of the application is redirected using the saved path from the local storage.

private onAuthorizationResultComplete(authorizationResult: AuthorizationResult) {
	console.log('AppComponent:onAuthorizationResultComplete');
	const path = this.read('redirect');
	if (authorizationResult === AuthorizationResult.authorized) {
		this.router.navigate([path]);
	} else {
		this.router.navigate(['/Unauthorized']);
	}
}

The onAuthorizationResult event is only emitted if the trigger_authorization_result_event configuration property is set to true.

constructor(public oidcSecurityService: OidcSecurityService) {

 let openIDImplicitFlowConfiguration = new OpenIDImplicitFlowConfiguration();
 openIDImplicitFlowConfiguration.stsServer = 'https://accounts.google.com';
 ...
 openIDImplicitFlowConfiguration.trigger_authorization_result_event = true;

 this.oidcSecurityService.setupModule(openIDImplicitFlowConfiguration);
}

The auto-login component redirects correctly to the STS server with the correct parameters for the application without any user interaction.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';
import { OidcSecurityService, AuthorizationResult } from 'angular-auth-oidc-client';

@Component({
    selector: 'app-auto-component',
    templateUrl: './auto-login.component.html'
})

export class AutoLoginComponent implements OnInit, OnDestroy {
    lang: any;

    constructor(public oidcSecurityService: OidcSecurityService
    ) {
        this.oidcSecurityService.onModuleSetup.subscribe(() => { this.onModuleSetup(); });
    }

    ngOnInit() {
        if (this.oidcSecurityService.moduleSetup) {
            this.onModuleSetup();
        }
    }

    ngOnDestroy(): void {
        this.oidcSecurityService.onModuleSetup.unsubscribe();
    }

    private onModuleSetup() {
        this.oidcSecurityService.authorize();
    }
}

The auto-login component is also added to the routes.

import { Routes, RouterModule } from '@angular/router';
import { AutoLoginComponent } from './auto-login/auto-login.component';
...

const appRoutes: Routes = [
    { path: '', component: HomeComponent },
    { path: 'home', component: HomeComponent },
    { path: 'autologin', component: AutoLoginComponent },
    ...
];

export const routing = RouterModule.forRoot(appRoutes);

Now the user is auto redirected to the login page of the STS server when opening the Angular SPA application.

Links:

https://www.npmjs.com/package/angular-auth-oidc-client

https://github.com/damienbod/angular-auth-oidc-client

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: