2

Angular4 azure active directory authentication using ng2-adal library removes id_token from the url.

I referred the following blog for the implementation. https://dotronald.be/add-azure-active-directory-to-an-existing-angular-2-single-page-application/

  1. Installed ng4-adal

  2. Created a typescript config file for ng4-adal to set azure connection details as follows, import {Injectable} from '@angular/core';

            @Injectable()
           export class AdalConfig {
                  public get getAdalConfig(): any {
                  return {
                      tenant: 'YOUR TENANT NAME',
                      clientId: 'YOUR CLIENT ID',           
                      redirectUri: window.location.origin + '/',
                       postLogoutRedirectUri: window.location.origin + 
                      '/logout'
                };
                }
             }
    
  3. Created a canActivate guard that authenticates the angular routes before navigation as follows,

             import { Injectable } from '@angular/core';
             import { Router, CanActivate,   
             ActivatedRouteSnapshot,RouterStateSnapshot, NavigationExtras } 
             from '@angular/router';
             import {AdalService} from "ng4-adal/core";
    
             @Injectable()
             export class AuthenticationGuard implements CanActivate {
    
             constructor(private _adalService: AdalService, private router: 
             Router) { }
    
             canActivate(route: ActivatedRouteSnapshot, state: 
             RouterStateSnapshot): boolean{
    
                if (this._adalService.userInfo.isAuthenticated) {
                    return true;
                }
                else {
                        this._adalService.login();
                        return false;
                }   }  }
    
  4. Added the following code in the constructor of the app.component.ts to initiate the ng4-adal service as follows,

                constructor(
                     private _adalService: AdalService,
                     private _adalConfigService: AdalConfig
               )                 
         {this._adalService.init(this._adalConfigService.getAdalConfig);}
    
  5. To prevent the user having to log in every time again, the authentication token is stored in the browser cache. This allows us to try to retrieve this token and continue using the application without being redirected again to the Azure login page.

Added the following code in the ngOninit of the app.component.ts to overcome the above issue as follows,

              ngOnInit() {
                 this._adalService.handleWindowCallback();
                 this._adalService.getUser();
              }
  1. Set the guard created in step 3 for required routes in the app-routing.ts file as follows,

            const routes: Routes = [
            { path: '', redirectTo: '/home', pathMatch: 'full', canActivate: 
             [AuthenticationGuard]},
             { path: 'admin-measure', redirectTo: '/#admin-measure'},
             { path: 'home', component: HomeComponent, canActivate: 
               [AuthenticationGuard] },                 
             { path: 'logout', component: LogoutComponent },
             { path: 'unauthorized', component: UnauthorizedComponent }
           ];
    
  2. Registered the services in app.module.

The error i'm getting in console follows, ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'id_token'

Problem found by research: There's an issue with redirects when using hashes in Angular 2. The problem is that when the authResult comes back in the redirect after authentication, Angular thinks it's a route called access_token.

Any solution for this?

2
  • Can you please provide the code snippets for a minimum, complete, verifiable example, and share the specific error or issue you're experiencing? Commented Mar 19, 2018 at 16:37
  • @Philippe Signoret, I have added the code to the question as you mentioned. Thanks. Commented Mar 22, 2018 at 8:41

1 Answer 1

5

I found the solution.

The callback from the Service Provider is using #/id_token which Angular2 router cannot understand. Will get an error in console – “Error: Cannot match any routes. Url Segment: ‘id_token’”. To address this, we will add a callback route to digest the JWT Token then redirect to our destination page.

a. Create oauth-callback.component as follows,

        import { Component, OnInit } from '@angular/core';
        import { Router } from '@angular/router';
        import {AdalService} from "ng4-adal/core";

        @Component({
                template: '<div>Please wait...</div>'
        })

        export class OAuthCallbackComponent implements OnInit {

        constructor(private router: Router, private _adalService: 
        AdalService) {}

        ngOnInit() {
                if (!this._adalService.userInfo) {
                    this._adalService.login();
                } else {
                    this.router.navigate(['home']);
               }
              }
        }

b. Create an oauth-callback-handler.guard for the “id_token” route as follows,

        import { Injectable } from '@angular/core';
        import { Router, CanActivate, ActivatedRouteSnapshot, 
        RouterStateSnapshot } from '@angular/router';
        import { AdalService } from 'ng4-adal/core';

        @Injectable()
        export class OAuthCallbackHandlerGuard implements CanActivate {

        constructor(private router: Router, private _adalService: 
        AdalService) { }

        canActivate(route: ActivatedRouteSnapshot, state: 
        RouterStateSnapshot): boolean {

            this._adalService.handleWindowCallback();

            if (this._adalService.userInfo.isAuthenticated) {

                var returnUrl = route.queryParams['returnUrl'];
                if (!returnUrl) {
                    this.router.navigate(['home']);
                } else {
                    this.router.navigate([returnUrl], { queryParams: 
                    route.queryParams });
                }
            }
            else {
                    this._adalService.login();
            }

            return false;
            }
         }

c. Register the oauth-callback.component and oauth-callback-handler.guard in app.module.

d. Register the route for “id_token” to be handled by oauth-callback.component and oauth-callback-handler.guard as follows,

          const routes: Routes = [
         { path: 'id_token', component: OAuthCallbackComponent, canActivate: 
           [OAuthCallbackHandlerGuard] }[AuthenticationGuard]},              
         { path: 'logout', component: LogoutComponent }];       

For further reference please see the below link,

https://blogs.msdn.microsoft.com/premier_developer/2017/04/26/using-adal-with-angular2/

Sign up to request clarification or add additional context in comments.

2 Comments

It's great you got this working! In order to help future developers, can you also include the part of the solution in the answer itself? (stackoverflow.com/help/how-to-answer) (Oh, and don't forget to mark your answers as the answer!)
@Philippe Signoret, Done. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.