【问题标题】:Why my auth0 token expires when refreshing page or clicking link in my Angular app?为什么在我的 Angular 应用程序中刷新页面或单击链接时,我的 auth0 令牌会过期?
【发布时间】:2019-08-14 22:03:24
【问题描述】:

我正在我的 Angular SPA 中设置身份验证。

我正在使用 auth0,我正在阅读他们页面上的教程:https://auth0.com/docs/quickstart/spa/angular2

我做了登录教程。

import { Injectable } from '@angular/core';
import * as auth0 from 'auth0-js';
import { Router } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  userProfile: any;

  private _idToken: string;
  private _accessToken: string;
  private _expiresAt: number;

    auth0 = new auth0.WebAuth({
    clientID: '*****',
    domain: '****',
    responseType: 'token id_token',
    redirectUri: 'http://localhost:4200/callback',
    scope: 'openid profile'
  });

  constructor(public router: Router) {
    this._idToken = '';
    this._accessToken = '';
    this._expiresAt = 0;
  }

  public login(): void {
    this.auth0.authorize();
  }

  public handleAuthentication(): void {
    this.auth0.parseHash((err, authResult) => {
      if (authResult && authResult.accessToken && authResult.idToken) {
        window.location.hash = '';
        this.localLogin(authResult);
        this.router.navigate(['/']);
      } else if (err) {
        this.router.navigate(['/']);
        console.log(err);
      }
    });
  }

  public getProfile(cb): void {
    if (!this._accessToken) {
      throw new Error('Access Token must exist to fetch profile');
    }

    const self = this;
    this.auth0.client.userInfo(this._accessToken, (err, profile) => {
      if (profile) {
        self.userProfile = profile;
      }
      cb(err, profile);
    });
  }

  private localLogin(authResult): void {

    localStorage.setItem('isLoggedIn', 'true');

    const expiresAt = (authResult.expiresIn * 1000) + new Date().getTime();
    this._accessToken = authResult.accessToken;
    this._idToken = authResult.idToken;
    this._expiresAt = expiresAt;
  }

  public renewTokens(): void {
    this.auth0.checkSession({}, (err, authResult) => {
      if (authResult && authResult.accessToken && authResult.idToken) {
        this.localLogin(authResult);
      } else if (err) {
        alert(`Could not get a new token (${err.error}: ${err.error_description}).`);
        this.logout();
      }
    });
  }

  public logout(): void {
    this._accessToken = '';
    this._idToken = '';
    this._expiresAt = 0;

    localStorage.removeItem('isLoggedIn');
    this.router.navigate(['/']);
  }

  public isAuthenticated(): boolean {
    return new Date().getTime() < this._expiresAt;
  }

  get accessToken(): string {
    return this._accessToken;
  }

  get idToken(): string {
    return this._idToken;
  }


}

我在我的页面上单击登录,我成功了,我得到了令牌,一切都很好。但是,当我刷新页面或单击链接时,就会被注销。我应该怎么做才能保持在页面的登录状态?

【问题讨论】:

    标签: angular authentication token auth0


    【解决方案1】:

    目前,您将数据保存在内存变量中。因此,当您重新加载应用程序时,内存中的变量 (_expiresAt) 会丢失该值。因此,isAuthenticated() 方法返回false。您可以将数据保存在浏览器 localStorage 中。

     private localLogin(authResult): void {
          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);
      }
    

    然后,在 isAuthenticated() 方法中,您可以从 localStorage 加载 expiresAt。

      public isAuthenticated(): boolean {
        const expiresAt = JSON.parse(localStorage.getItem("expires_at") || "{}");
        return new Date().getTime() < expiresAt;
      }
    

    注销过程中,需要清除localStorage中的数据。

    public logout(): void {
        // Remove tokens and expiry time from localStorage
        localStorage.removeItem("access_token");
        localStorage.removeItem("id_token");
        localStorage.removeItem("expires_at");
        // Remove server SSO session
        this.auth0.logout({ returnTo: "http://localhost:4200" });
    
      }
    

    最佳实践:

    对于 SPA,请遵循 auth0 最佳实践:https://auth0.com/docs/security/store-tokens#single-page-apps

    【讨论】:

    • 谢谢,我一直在寻找。但是将这些令牌保存在本地存储中是否安全?
    • 围绕它有一些争论。 Auth0 不建议将令牌存储在 SPA 的 localStorage 或 sessionStorage 中。因为存储的任何数据都可以通过 javascript 访问并且容易受到跨站点脚本的攻击。 @K4mczi
    • 好的,你真的很有帮助,我认为更好的解决方案是在 java 后端做 auth0
    • @TanverHasan 他们建议不要存储它。建议使用常规 webapp,但显然不清楚如何将它与 angular 一起使用。你有样品吗?
    • @MathKimRobin 新的 SDK auth0-spa-js 提供了更好的令牌存储机制,如果令牌丢失,您可以使用静默身份验证获取新令牌。 github.com/auth0/auth0-spa-js
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    • 2020-06-22
    • 2021-02-04
    • 1970-01-01
    • 2020-01-16
    • 2013-03-11
    • 2013-08-12
    相关资源
    最近更新 更多