使用Auth0和Auth0锁在Angular中进行身份验证
身份验证可能很困难,并且每次在应用程序中需要它时重新发明轮子肯定没有乐趣。 值得庆幸的是,不同的服务和工具可以为我们完成繁重的工作。 我们已经讨论过使用 Firebase 实现 身份验证,所以现在让我们探索一个替代方案:Auth0。 Auth0 是一个非常强大的解决方案,它提供了您期望从身份验证提供商那里获得的所有功能(社交登录、电子邮件/密码登录、授权规则……)
在这篇文章中,我们将使用 Auth0 Lock 小部件 ,它允许在您的应用程序中嵌入一个弹出窗口以进行身份验证。 您还可以在 Auth0 的托管登录页面上实现身份验证,在这种情况下,您可能需要 参考本指南 。
这篇文章涵盖了 Angular 2+ 应用程序的身份验证。
设置
首先,您需要创建一个 Auth0 帐户,然后创建一个新的 单页 Web 应用程序 客户端。
创建客户端后,您将能够根据自己的喜好配置设置。 重要的一件事是添加一个回调 URL,该 URL 反映了 Angular 应用程序中的实际登录回调路由。 在这里,我们将创建一个 login 路由,因此我们将添加 http://localhost:4200/login 作为我们唯一允许的回调 URL。 Auth0 将在身份验证后重定向到它。
在您的客户端设置中,您还可以访问 域 和 客户端 ID 信息。 在应用的 environment.ts 文件中添加该信息:
环境.ts
export const environment = {
production: false,
auth0: {
domain: 'your-awesome-domain.auth0.com',
clientId: 'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
callbackURL: 'http://localhost:4200/login'
}
};
您的项目中还需要三个额外的包:auth0-js、auth0-lock 和 angular2-jwt。 让我们使用 npm 或 Yarn 将它们安装到我们的项目中:
$ yarn add auth0-js auth0-lock angular2-jwt # or, using npm: $ npm install auth0-js auth0-lock angular2-jwt
现在将 auth0.min.js 添加到应用程序构建中包含的脚本列表中:
.angular-cli.json
..., "scripts": [ "../node_modules/auth0-js/build/auth0.min.js" ], ...
租户
使用 Auth0,您可以创建多个租户以适应不同的部署环境(development、production、staging,...)每个租户都有自己的域名(例如:my-app-dev.auth0.com 和 my-app.auth0.com)。 这样,您可以为生产创建一个不同的客户端,您只需使用不同的域名、客户端 ID 和回调 URL 填充您的生产环境文件。
组件和路由设置
我们将向我们的应用程序添加两个组件:一个 home 组件和一个 login 回调组件。 我们可以使用 Angular CLI 轻松生成新组件:
$ ng g c home $ ng g c login
接下来,让我们设置一个简单的路由模块:
app.routing.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'login', component: LoginComponent }
];
认证服务
让我们也使用 Angular CLI 创建一个 Auth 服务:
$ ng g s auth
此时,您需要确保您的路由模块已导入到您的应用程序模块中,并且验证服务也由应用程序模块提供。
让我们开始设置身份验证服务:
auth.service.ts
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { environment } from '../environments/environment';
import { tokenNotExpired } from 'angular2-jwt';
import Auth0Lock from 'auth0-lock';
@Injectable()
export class AuthService {
auth0Options = {
theme: {
logo: '/assets/alligator-logo.svg',
primaryColor: '#DFA612'
},
auth: {
redirectUrl: environment.auth0.callbackURL,
responseType: 'token id_token',
audience: https://${environment.auth0.domain}/userinfo,
params: {
scope: 'openid profile'
}
},
autoclose: true,
oidcConformant: true,
};
lock = new Auth0Lock(
environment.auth0.clientId,
environment.auth0.domain,
this.auth0Options
);
constructor(private router: Router) {
this.lock.on('authenticated', (authResult: any) => {
console.log('Nice, it worked!');
this.router.navigate(['/']); // go to the home route
// ...finish implementing authenticated
});
this.lock.on('authorization_error', error => {
console.log('something went wrong', error);
}); }
login() {
this.lock.show();
}
logout() {
// ...implement logout
}
这里有几点需要注意:
- 我们首先定义一个 Auth0Lock 的新实例,它接受客户端 ID、域和一个配置对象。 有很多 配置选项 可用,在所需选项之上,我们还添加了一些主题选项来设置锁定小部件的样式。
- 在选项中,我们还使用 scopes 键指定我们想要返回的数据类型。 在这里,除了默认的 openid 之外,我们还对获取 profile 信息感兴趣。
- 在服务的构造函数中,我们侦听锁实例上的 authenticated 或 authorization_error 事件。 authenticated 事件的回调将包含我们何时验证成功的逻辑。
- 登录方法与在我们的锁实例上调用 show 方法一样容易实现。
- 我们必须回来完成 logout 和 isAuthenticated 方法的实现。
我们现在可以在我们的 home 组件中注入 auth 服务:
home.component.ts
import { Component } from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html'
})
export class HomeComponent {
让我们在模板中添加登录和注销按钮:
home.component.html
<button *ngIf="!auth.isAuthenticated()" (click)="auth.login()"> Sign Up or Login </button> <button *ngIf="auth.isAuthenticated()" (click)="auth.logout()"> Logout </button>
有了我们的基本身份验证服务,Auth0 嵌入已经开始工作,我们可以注册或登录:
配置文件,IsAuthenticated,注销
让我们完成我们的认证服务实现。 对于我们的示例,我们将 Auth0 返回的 JSON Web 令牌保存到本地存储。 然后可以使用对后端 API 的 HTTP 请求的 Bearer 前缀将该令牌添加到 Authorization 标头。 然后,后端将负责确保令牌有效。 我们还将获取我们使用 scopes 请求的帐户配置文件信息并将其保存到本地存储。
一、authenticated事件成功的逻辑:
auth.service.ts(部分)
this.lock.on('authenticated', (authResult: any) => {
this.lock.getUserInfo(authResult.accessToken, (error, profile) => {
if (error) {
throw new Error(error);
}
localStorage.setItem('token', authResult.idToken);
localStorage.setItem('profile', JSON.stringify(profile));
this.router.navigate(['/']);
在这里,我们在锁实例上调用 getUserInfo 并传入从成功认证返回的访问令牌。 getUserInfo 让我们可以访问用户的配置文件信息。
已认证
我们的 isAuthenticated 方法对我们的应用程序了解是否有经过身份验证的用户很有用,并因此调整 UI。
为了实现它,我们将使用 angular2-jwt 的 tokenNotExpired 方法。 如果没有令牌或令牌已过期,它将返回 false:
isAuthenticated() {
return tokenNotExpired();
}
登出
由于使用 JWT 进行身份验证是无状态的,因此我们只需从本地存储中删除令牌和配置文件即可注销:
auth.service.ts
logout() {
localStorage.removeItem('profile');
localStorage.removeItem('token');
}
🔑 你有它! 为您的应用程序提供简单的身份验证。