angular - How to use the HashLocationStrategy with the Auth0 Lock widget for user login -


after updating auth0 login sample use hashlocationstrategy in app.module.ts:

import { locationstrategy, hashlocationstrategy } '@angular/common'; // (...) @ngmodule({   providers: [     {provide: locationstrategy, useclass: hashlocationstrategy},     approutingproviders,     auth_providers   ],   //(...) 

the auth0 lock authenticated event not raised anymore:

import { injectable } '@angular/core'; import { tokennotexpired } 'angular2-jwt';  // avoid name not found warnings declare var auth0lock: any;  @injectable() export class auth0service {    // configure auth0   lock = new auth0lock('i21eajbbpf...', '....au.auth0.com', {});    constructor() {     // add callback lock `authenticated` event     this.lock.on("authenticated", (authresult) => {       // use token in authresult getprofile() , save localstorage       this.lock.getprofile(authresult.idtoken, function(error, profile) {         if (error) {           // handle error           return;         }          localstorage.setitem('id_token', authresult.idtoken);         localstorage.setitem('profile', json.stringify(profile));       });     });       } // (...) 

the reason you're experiencing issue because angular 2 router automatically cleanup url upon route navigation causing auth0 lock never see data required authenticate user. judging github, behavior not this, it's current one. see rc2 router strips arguments path after matching route , navigation should not preserve query params , fragment background.

upon performing login auth0 request browser navigate url similar this:

http://example.com/#access_token=renh3twuqx&id_token=eyj0.epcoidrwc.qdx3ac&token_type=bearer 

this url contains necessary information lock recognize user authenticated, however, the mentioned angular router behavior means before lock having chance process information, authentication data contained in url fragment stripped, leaving url (http://example.com/#/). happens because have configured catch-all route matches url.

assuming have following routes configured:

const approutes: routes = [   { path: '', component: homecomponent },   { path: '**', redirectto: '' } ]; 

disclaimer: first solution shown below provided workaround proved functional angular 2.0.0, angular router 3.0.0 used lock 10.2. since then, seems router and/or lock suffered changes made initial workaround fail. i'm providing second workaround seems functional angular 2.4.1, angular router 3.4.1 , lock 10.7.


workaround #1 - (angular/core@2.0.0, angular/router@3.0.0, lock@10.2)

one possible way try circumvent default behavior perform following steps:

  1. add activation guard route handling authentication callback request in such way not allow route activate if current url seems result of login (for example, contains access_token keyword in fragment.
  2. upon authenticated event being triggered force navigation desired route application recognizes login.

you create following class:

import { injectable } '@angular/core'; import { canactivate } '@angular/router'; import { location } '@angular/common';  @injectable() export class authenticationcallbackactivateguard implements canactivate {    constructor(private location: location) { }    canactivate() {     // may want make more robust check here     return this.location.path(true).indexof("access_token") === -1;   } } 

register guard home route:

const approutes: routes = [   { path: '', component: homecomponent, canactivate: [authenticationcallbackactivateguard] },   { path: '**', redirectto: '' } ];  export const approutingproviders: any[] = [   authenticationcallbackactivateguard ]; 

and finally, navigate route after authentication:

this.lock.on('authenticated', (authresult) => {   localstorage.setitem('id_token', authresult.idtoken);   this.router.navigate([''], {}); }); 

workaround #2 - (angular/core@2.4.1, angular/router@3.4.1, lock@10.7)

similar done before, imperative navigation done on guard itself authentication callback data provided fragment lock able see information when processing events. since navigation moved guard, no longer need navigation on lock authenticated event.

create following class:

import { injectable } '@angular/core'; import { canactivate } '@angular/router'; import { location } '@angular/common'; import { router } '@angular/router';  @injectable() export class authenticationcallbackactivateguard implements canactivate {    constructor(private router: router, private location: location) { }    canactivate() {     var path = this.location.path(true);      // may want make more robust check here     var isauthenticationcallback = path.indexof("access_token") !== -1;      if (isauthenticationcallback) {       this.router.navigate([''], { fragment: path });        return false;     }      return true;   } } 

register guard home route:

const approutes: routes = [   { path: '', component: homecomponent, canactivate: [authenticationcallbackactivateguard] },   { path: '**', redirectto: '' } ];  export const approutingproviders: any[] = [   authenticationcallbackactivateguard ]; 

and finally, handle authentication event:

this.lock.on('authenticated', (authresult) => {   localstorage.setitem('id_token', authresult.idtoken); }); 

Comments

Popular posts from this blog

unity3d - Rotate an object to face an opposite direction -

angular - Is it possible to get native element for formControl? -

javascript - Why jQuery Select box change event is now working? -