身份验证可能很难,每次在应用程序中需要它时都要重新发明轮子,这肯定不是一件有趣的事情。谢天谢地,不同的服务和工具可以为我们处理繁重的任务。我们已经讨论了使用Firebase](https://andsky.com/tech/tutorials/angular-firebase-authentication-angularfire2),实现[身份验证],所以现在让我们探索一种替代方案:Auth0。Auth0是一款功能非常强大的解决方案,它提供了身份验证提供商提供的所有功能(社交登录、电子邮件/密码登录、授权规则等)
在这篇文章中,我们将使用Auth0 Lock Widget,,它允许在您的应用程序中嵌入弹出窗口进行身份验证。您也可以在AUTHO的S托管登录页面上进行身份验证,在这种情况下,您可能需要参考此guide.
<$>[note]这篇文章涵盖了Angular 2+应用程序的身份验证。<$>
设置
首先,您需要创建一个Auth0帐户,然后创建一个新的单页Web应用程序 客户端。
一旦创建了您的客户端,您将能够根据您的首选项配置设置。有一件事很重要,那就是在您的ANGLE应用程序中添加一个反映实际登录回调路线的回调URL。这里我们将创建一条登录路径,因此我们将添加http://localhost:4200/login
作为我们唯一允许的回调URL。经过身份验证后,Auth0将重定向到它。
在您的客户端设置中,您还可以访问域和客户端ID信息。将该信息添加到应用程序的环境.ts文件中:
1[label environment.ts]
2export const environment = {
3 production: false,
4 auth0: {
5 domain: 'your-awesome-domain.auth0.com',
6 clientId: 'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
7 callbackURL: 'http://localhost:4200/login'
8 }
9};
您的项目中还需要另外三个包:auth0-js、auth0-lock和angular2-jwt。让我们使用NPM或Yarn将它们安装到我们的项目中:
1$ yarn add auth0-js auth0-lock angular2-jwt
2
3# or, using npm:
4$ npm install auth0-js auth0-lock angular2-jwt
现在,将auth0.min.js添加到应用程序版本中包含的脚本列表中:
1[label .angular-cli.json]
2...,
3"scripts": [
4 "../node_modules/auth0-js/build/auth0.min.js"
5],
6...
租客
有了Auth0,您可以创建多个租户,以适应不同的部署环境(开发 、** 生产** 、** 暂存** ,...)每个租户都有自己的域名(例如:my-app-dev.auth0.com
和my-app.auth0.com
)。这样,您就可以为生产创建不同的客户端,您所需要的就是用不同的域名、客户端ID和回调URL填充您的生产环境文件。
组件布线设置
我们将向应用程序添加两个组件:一个home组件和一个login回调组件。我们可以使用Angular CLI轻松生成新组件:
1$ ng g c home
2$ ng g c login
接下来,让我们设置一个简单的路由模块:
1[label app.routing.ts]
2import { NgModule } from '@angular/core';
3import { RouterModule, Routes } from '@angular/router';
4
5import { LoginComponent } from './login/login.component';
6import { HomeComponent } from './home/home.component';
7const routes: Routes = [
8 { path: '', component: HomeComponent },
9 { path: 'login', component: LoginComponent }
10];
身份验证服务
让我们还使用角度CLI来创建一个Auth服务:
1$ ng g s auth
<$>[注意]此时,您需要确保路由模块已导入到app模块中,并且auth服务也由app模块提供。<$>
让我们开始设置auth服务:
1[label auth.service.ts]
2import { Injectable } from '@angular/core';
3import { Router } from '@angular/router';
4import { environment } from '../environments/environment';
5
6import { tokenNotExpired } from 'angular2-jwt';
7import Auth0Lock from 'auth0-lock';
8@Injectable()
9export class AuthService {
10 auth0Options = {
11 theme: {
12 logo: '/assets/alligator-logo.svg',
13 primaryColor: '#DFA612'
14 },
15 auth: {
16 redirectUrl: environment.auth0.callbackURL,
17 responseType: 'token id_token',
18 audience: https://${environment.auth0.domain}/userinfo,
19 params: {
20 scope: 'openid profile'
21 }
22 },
23 autoclose: true,
24 oidcConformant: true,
25 };
26 lock = new Auth0Lock(
27 environment.auth0.clientId,
28 environment.auth0.domain,
29 this.auth0Options
30 );
31 constructor(private router: Router) {
32 this.lock.on('authenticated', (authResult: any) => {
33 console.log('Nice, it worked!');
34 this.router.navigate(['/']); // go to the home route
35 // ...finish implementing authenticated
36 });
37this.lock.on('authorization_error', error => {
38 console.log('something went wrong', error);
39}); }
40 login() {
41 this.lock.show();
42 }
43 logout() {
44 // ...implement logout
45 }
以下是需要注意的几点:
- 我们首先定义一个新的Auth0Lock实例,它接受客户端ID、域和一个配置对象。有大量的Configuration options]可用,在这里,除了所需的选项之外,我们还添加了一些主题选项来设置锁小部件的样式。
- 在选项中,我们还使用作用域键指定要返回的数据类型。在这里,除了默认的OpenID之外,我们还对取回配置文件信息感兴趣。
- 在服务的构造函数中,我们监听锁实例上的AUTHENTICATED或AUTHORIZATION_ERROR事件。经过身份验证的事件的回调将具有身份验证成功时间的逻辑。
- 登录方法的实现就像在锁实例上调用show方法一样简单。
- 我们将不得不回来并完成Logout和和isAuthenticated方法的实现。
我们现在可以在主组件中注入身份验证服务:
1[label home.component.ts]
2import { Component } from '@angular/core';
3
4import { AuthService } from '../auth.service';
5@Component({
6 selector: 'app-home',
7 templateUrl: './home.component.html'
8})
9export class HomeComponent {
让我们在模板中添加登录和注销按钮:
1[label home.component.html]
2<button
3 *ngIf="!auth.isAuthenticated()"
4 (click)="auth.login()">
5 Sign Up or Login
6</button>
7
8<button
9 *ngIf="auth.isAuthenticated()"
10 (click)="auth.logout()">
11 Logout
12</button>
在我们的基本身份验证服务就位后,Auth0嵌入已经在工作,我们可以注册或登录:
Profile,IsAuthenticated,注销
让我们完成身份验证服务实现。对于我们的示例,我们将把Auth0返回的JSON Web令牌保存到本地存储。然后,可以在对后端API的HTTP请求上使用持有者前缀将该令牌添加到授权标头中。然后,后端将负责确保令牌有效。我们还将获得使用作用域请求的帐户配置文件信息,并将其保存到本地存储。
首先,关于成功的身份验证事件的逻辑:
1[label auth.service.ts (partial)]
2this.lock.on('authenticated', (authResult: any) => {
3 this.lock.getUserInfo(authResult.accessToken, (error, profile) => {
4 if (error) {
5 throw new Error(error);
6 }
7
8localStorage.setItem('token', authResult.idToken);
9localStorage.setItem('profile', JSON.stringify(profile));
10this.router.navigate(['/']);
在这里,我们在锁实例上调用getUserInfo,并传入从成功的身份验证返回的访问令牌。getUserInfo 让我们可以访问该用户的档案信息。
已通过身份验证
我们的isAuthenticated方法对于我们的应用程序很有用,可以知道是否使用了经过身份验证的用户界面,并因此调整了用户界面。
为了实现它,我们将使用angular2-jwt的tokenNotExpired
方法。如果没有令牌或令牌已过期,则返回FALSE:
1isAuthenticated() {
2 return tokenNotExpired();
3}
注销
由于使用JWT进行身份验证是无状态的,因此要注销,我们只需从本地存储中删除令牌和配置文件:
1[label auth.service.ts]
2logout() {
3 localStorage.removeItem('profile');
4 localStorage.removeItem('token');
5}
你有它!为您的应用程序提供简单的身份验证。