使用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-jsauth0-lockangular2-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,您可以创建多个租户以适应不同的部署环境(developmentproductionstaging,...)每个租户都有自己的域名(例如:my-app-dev.auth0.commy-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 信息感兴趣。
  • 在服务的构造函数中,我们侦听锁实例上的 authenticatedauthorization_error 事件。 authenticated 事件的回调将包含我们何时验证成功的逻辑。
  • 登录方法与在我们的锁实例上调用 show 方法一样容易实现。
  • 我们必须回来完成 logoutisAuthenticated 方法的实现。



我们现在可以在我们的 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-jwttokenNotExpired 方法。 如果没有令牌或令牌已过期,它将返回 false:

isAuthenticated() {
  return tokenNotExpired();
}

登出

由于使用 JWT 进行身份验证是无状态的,因此我们只需从本地存储中删除令牌和配置文件即可注销:

auth.service.ts

logout() {
  localStorage.removeItem('profile');
  localStorage.removeItem('token');
}

🔑 你有它! 为您的应用程序提供简单的身份验证。