繁体   English   中英

如何使用Angular 2 useHash设置Auth0:是吗?

[英]How do I set up Auth0 with Angular 2 useHash: true?

有关使用散列路由(例如http://somdomain.com/#/someroute )将auth0与angular 2一起使用的文档和示例非常稀少且已过时。

有多个问题要解决:

  1. auth0侦听URL片段的更改。 不幸的是, angular吞下了URL片段更改,因为它认为它正在处理路由。

  2. 网址片段以#access_token=...开头,并且角度错误引发错误,因为access_token未注册为路由。

  3. 即使您注册了路线access_token您也不想以任何方式将其显示为路线,因此您需要取消导航。

实际进行设置需要做什么?

首先,您需要auth0-lock

 npm install --save auth0-lock

接下来,您将需要身份验证服务。 以下身份验证服务实现了login()logout()

在调用这些方法之前,请确保使用registerAuthenticationWithHashHandler配置服务。 这可以在App.Component.ts完成

// AuthService.ts
import { environment } from './../environments/environment';
import { Injectable } from '@angular/core';
import { Router, RouterEvent } from '@angular/router';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/take';
import { AuthCallbackComponent } from './../app/auth-callback/auth-callback.component';
import { AuthenticationCallbackActivateGuard } from '../app/auth-callback/auth-callback-activate-guard';
import Auth0Lock from 'auth0-lock';

@Injectable()
export class AuthService {

  private lock: Auth0Lock;

  constructor(public router: Router) {

    this.lock = new Auth0Lock(
      environment.auth0.clientID,
      environment.auth0.domain,
      {
        oidcConformant: true,
        autoclose: true,
        auth: {
          autoParseHash: false,
          redirectUrl: environment.auth0.redirectUri,
          responseType: 'token id_token',
          audience: environment.auth0.audience,
          params: {
            scope: 'openid'
          }
        }
      }
    );

  }

  public login(): void {
    this.lock.show();
  }

  // Call this method in app.component.ts
  // if using path-based routing
  public registerAuthenticationHandler(): void {
    this.lock.on('authenticated', (authResult) => {
      if (authResult && authResult.accessToken && authResult.idToken) {
        this.setSession(authResult);
        this.router.navigate(['/']);
      }
    });
    this.lock.on('authorization_error', (err) => {
      this.router.navigate(['/']);
      console.log(err);
      alert(`Error: ${err.error}. Check the console for further details.`);
    });
  }

  // Call this method in app.component.ts
  // if using hash-based routing
  public registerAuthenticationWithHashHandler(): void {

    this.registerAuthenticationHandler();
    this.workaroundHashAccessTokenRoute();

    this.router.events.take(1).subscribe(event => {

      if (!(event instanceof RouterEvent)) {
        return;
      }

      this.lock.resumeAuth(window.location.hash, (err, authResult) => {
        if (authResult && authResult.idToken) {
          this.lock.emit('authenticated', authResult);
        }

        if (authResult && authResult.error) {
          this.lock.emit('authorization_error', authResult);
        }
      });

    });
  }

  private workaroundHashAccessTokenRoute() {

    /* workaround useHash:true with angular2 router
    ** Angular mistakenly thinks "#access_token" is a route
    ** and we oblige by creating a fake route that can never be activated
    */
    const routes = this.router.config;
    routes.splice(0, 0, {
      path: 'access_token',
      component: AuthCallbackComponent,
      canActivate: [AuthenticationCallbackActivateGuard]
    });
    this.router.resetConfig(routes);
  }

  private setSession(authResult): void {
    // Set the time that the access token will expire at
    const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
    localStorage.setItem('access_token', authResult.accessToken);
    localStorage.setItem('id_token', authResult.idToken);
    localStorage.setItem('expires_at', expiresAt);
  }

  public logout(): void {
    // Remove tokens and expiry time from localStorage
    localStorage.removeItem('access_token');
    localStorage.removeItem('id_token');
    localStorage.removeItem('expires_at');
    // Go back to the home route
    this.router.navigate(['/']);
  }

  public isAuthenticated(): boolean {
    // Check whether the current time is past the
    // access token's expiry time
    const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
    return new Date().getTime() < expiresAt;
  }
}

registerAuthenticationWithHashHandler创建一个名为“ access_token”的伪路由,并受到名为AuthenticationCallbackActivateGuard的规则的保护,该规则始终返回false。

// auth-callback-activate-guard.ts
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() {
    return false;
  }
}

这是虚拟路线所需的部分:

// auth-callback/auth-callback.components.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-auth-callback',
  templateUrl: './auth-callback.component.html',
  styleUrls: ['./auth-callback.component.scss']
})
export class AuthCallbackComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

在App.Component.ts中注册身份验证服务

// app/app.component.ts
import { Component } from '@angular/core';
import { AuthService } from '../services/auth.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';

  constructor(private auth: AuthService) {
    auth.registerAuthenticationWithHashHandler();
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM