如何使用带有Auth0 Lock小部件的HashLocationStrategy进行用户登录 [英] How to use the HashLocationStrategy with the Auth0 Lock widget for user login

查看:41
本文介绍了如何使用带有Auth0 Lock小部件的HashLocationStrategy进行用户登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在更新 Auth0登录示例在app.module.ts中使用HashLocationStrategy:

import { LocationStrategy, HashLocationStrategy } from '@angular/common';
// (...)
@NgModule({
  providers: [
    {provide: LocationStrategy, useClass: HashLocationStrategy},
    appRoutingProviders,
    AUTH_PROVIDERS
  ],  
//(...)

不再引发Auth0 Lock authenticated事件:

The Auth0 Lock authenticated event is not raised anymore:

import { Injectable } from '@angular/core';
import { tokenNotExpired } from '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 for lock `authenticated` event
    this.lock.on("authenticated", (authResult) => {
      // Use the token in authResult to getProfile() and save it to 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));
      });
    });    
  }
// (...)

推荐答案

遇到此问题的原因是, Angular 2路由器将在路由导航时自动清除URL,从而导致Auth0 Lock永远看不到数据验证用户身份所需的.从GitHub来看,这种行为并不总是这样,但这是当前的行为.请参见 RC2路由器在匹配路由后从路径中剥离多余的参数

The reason you're experiencing this issue is because the Angular 2 router will automatically cleanup the URL upon route navigation causing Auth0 Lock to never see the data required to authenticate the user. Judging from GitHub, this behavior was not always like this, but it's the current one. See RC2 Router strips extra arguments from the path after matching a route and navigation should not preserve query params and fragment for some background.

执行登录Auth0后,将要求您的浏览器导航到类似于以下网址:

Upon performing the login Auth0 will request your browser to navigate into an URL similar to this:

http://example.com/#access_token=RENH3twuqx&id_token=eyJ0.epcOidRwc.Qdx3ac&token_type=Bearer

此URL包含用于Lock识别用户已通过身份验证的所有必要信息,但是,前面提到的Angular路由器行为意味着,在Lock之前有机会处理此信息,即身份验证数据URL片段中包含的内容将被删除,而将URL保留为(http://example.com/#/).发生这种情况是因为您很可能已配置了与任何URL匹配的全部路由.

This URL contains all the necessary information for Lock to recognize that the user is authenticated, however, the previously mentioned Angular router behavior means that before Lock having a chance to process this information, the authentication data contained in the URL fragment is stripped, leaving the URL as (http://example.com/#/). This happens because you most likely have configured a catch-all route that matches any URL.

假设您配置了以下路由:

Assuming you have the following routes configured:

const appRoutes: Routes = [
  { path: '', component: HomeComponent },
  { path: '**', redirectTo: '' }
];


免责声明:下面提供的第一个解决方案是一种变通方法,被证明可用于Angular 2.0.0 ,Angular路由器 3.0.0 与锁 10.2 一起使用.从那时起,路由器和/或Lock似乎遭受了更改,从而使初始解决方法失败.我提供了第二种解决方法,它似乎可以与Angular 2.4.1 ,Angular路由器 3.4.1 和Lock 10.7 一起使用.

DISCLAIMER: The first solution that will be shown below was provided as a workaround that proved functional for Angular 2.0.0, Angular router 3.0.0 used with Lock 10.2. Since then, it seems the router and/or Lock suffered changes that made the initial workaround fail. I'm providing a second workaround that seems to be functional with Angular 2.4.1, Angular router 3.4.1 and Lock 10.7.


解决方法#1-(角度/核心@ 2.0.0,角度/路由器@ 3.0.0,锁定@ 10.2)

尝试规避此默认行为的一种可能方法是执行以下步骤:


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

One possible way to try to circumvent this default behavior is to perform the following steps:

  1. 向正在处理身份验证回调请求的路由添加激活保护,以使如果当前URL似乎是登录的结果(例如,包含access_token关键字),则不允许该路由激活在其片段中.
  2. 在触发经过身份验证的事件后,将强制导航到所需的路线,以便应用程序识别登录名.
  1. Add an activation guard to the route that is handling the authentication callback request in such way as to not allow the route to activate if the current URL seems like to be the result of login (for example, contains the access_token keyword in its fragment.
  2. Upon the authenticated event being triggered force the navigation to your desired route so that the application recognizes the login.

您可以创建以下类:

import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { Location } from '@angular/common';

@Injectable()
export class AuthenticationCallbackActivateGuard implements CanActivate {

  constructor(private location: Location) { }

  canActivate() {
    // You may want to make a more robust check here
    return this.location.path(true).indexOf("access_token") === -1;
  }
}

将其注册为本地路线的警卫:

Register it as a guard for your home route:

const appRoutes: Routes = [
  { path: '', component: HomeComponent, canActivate: [AuthenticationCallbackActivateGuard] },
  { path: '**', redirectTo: '' }
];

export const appRoutingProviders: any[] = [
  AuthenticationCallbackActivateGuard
];

最后,在身份验证后导航到您的路由:

And finally, navigate to your route after authentication:

this.lock.on('authenticated', (authResult) => {
  localStorage.setItem('id_token', authResult.idToken);
  this.router.navigate([''], {});
});

解决方法#2-(angular/core@2.4.1,angular/router@3.4.1,lock@10.7)

与之前的操作类似,但是强制性导航是在警卫本身上完成的,其中身份验证回调数据作为片段提供,以便Lock在处理事件时能够看到此信息.由于导航移到了后卫,因此您不再需要对经过身份验证的锁定事件进行导航.

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

Similar to what was done before, but the imperative navigation is done on the guard itself with the authentication callback data provided as fragment so that Lock is able to see this information when processing events. Since navigation moved to the guard, you no longer need to do the navigation on the lock authenticated event.

创建以下类:

import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { Location } from '@angular/common';
import { Router } from '@angular/router';

@Injectable()
export class AuthenticationCallbackActivateGuard implements CanActivate {

  constructor(private router: Router, private location: Location) { }

  canActivate() {
    var path = this.location.path(true);

    // You may want to make a more robust check here
    var isAuthenticationCallback = path.indexOf("access_token") !== -1;

    if (isAuthenticationCallback) {
      this.router.navigate([''], { fragment: path });

      return false;
    }

    return true;
  }
}

将其注册为本地路线的警卫:

Register it as a guard for your home route:

const appRoutes: Routes = [
  { path: '', component: HomeComponent, canActivate: [AuthenticationCallbackActivateGuard] },
  { path: '**', redirectTo: '' }
];

export const appRoutingProviders: any[] = [
  AuthenticationCallbackActivateGuard
];

最后,处理身份验证事件:

And finally, handle the authentication event:

this.lock.on('authenticated', (authResult) => {
  localStorage.setItem('id_token', authResult.idToken);
});

这篇关于如何使用带有Auth0 Lock小部件的HashLocationStrategy进行用户登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆