您遇到此问题的原因是Angular 2 路由器将在路由导航时自动清理 URL,导致 Auth0 Lock 永远看不到验证用户身份所需的数据。从 GitHub 来看,这种行为并不总是这样,但现在就是这样。看RC2 路由器在匹配路由后从路径中去除额外的参数 https://github.com/angular/angular/issues/11233 and 导航不应保留查询参数和片段 https://github.com/angular/angular/commit/23ee29b6a2ae396f6ec13f71c9552e3e0a983c3c一些背景。
执行登录后,Auth0 将请求您的浏览器导航到类似于以下内容的 URL:
http://example.com/#access_token=RENH3twuqx&id_token=eyJ0.epcOidRwc.Qdx3ac&token_type=Bearer
此 URL 包含 Lock 识别用户已通过身份验证所需的所有信息,但是,前面提到的 Angular 路由器行为意味着在 Lock 之前当有机会处理此信息时,URL 片段中包含的身份验证数据将被剥离,将 URL 保留为 (http://example.com/#/
)。发生这种情况是因为您很可能配置了与任何 URL 匹配的包罗万象的路由。
假设您配置了以下路由:
const appRoutes: Routes = [
{ path: '', component: HomeComponent },
{ path: '**', redirectTo: '' }
];
免责声明:下面显示的第一个解决方案是作为解决方法提供的,经证明对 Angular 有效2.0.0, 角路由器3.0.0与锁一起使用10.2。从那时起,路由器和/或锁似乎发生了变化,导致最初的解决方法失败了。我提供了第二种解决方法,它似乎适用于 Angular2.4.1, 角路由器3.4.1和锁定10.7.
解决方法#1 - (角度/[电子邮件受保护] /cdn-cgi/l/email-protection, 角度/[电子邮件受保护] /cdn-cgi/l/email-protection, [电子邮件受保护] /cdn-cgi/l/email-protection)
尝试规避此默认行为的一种可能方法是执行以下步骤:
- 将激活防护添加到处理身份验证回调请求的路由中,以便在当前 URL 看起来像是登录的结果(例如,包含
access_token
其片段中的关键字。
- 触发经过身份验证的事件后,强制导航到您所需的路线,以便应用程序识别登录。
您可以创建以下类:
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;
}
}
将其注册为您家乡路线的守卫:
const appRoutes: Routes = [
{ path: '', component: HomeComponent, canActivate: [AuthenticationCallbackActivateGuard] },
{ path: '**', redirectTo: '' }
];
export const appRoutingProviders: any[] = [
AuthenticationCallbackActivateGuard
];
最后,在身份验证后导航到您的路线:
this.lock.on('authenticated', (authResult) => {
localStorage.setItem('id_token', authResult.idToken);
this.router.navigate([''], {});
});
解决方法 #2 - (角度/[电子邮件受保护] /cdn-cgi/l/email-protection, 角度/[电子邮件受保护] /cdn-cgi/l/email-protection, [电子邮件受保护] /cdn-cgi/l/email-protection)
与之前所做的类似,但是命令式导航是在守卫本身上完成的以片段形式提供身份验证回调数据,以便 Lock 在处理事件时能够看到此信息。由于导航转移到了守卫,您不再需要在锁定验证事件上进行导航。
创建以下类:
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;
}
}
将其注册为您家乡路线的守卫:
const appRoutes: Routes = [
{ path: '', component: HomeComponent, canActivate: [AuthenticationCallbackActivateGuard] },
{ path: '**', redirectTo: '' }
];
export const appRoutingProviders: any[] = [
AuthenticationCallbackActivateGuard
];
最后,处理身份验证事件:
this.lock.on('authenticated', (authResult) => {
localStorage.setItem('id_token', authResult.idToken);
});