首页 > 解决方案 > auth0 身份验证后需要刷新页面才能在 Angular 中获取令牌和用户配置文件

问题描述

所以我的 SPA 应用程序是用 Angular 编写的。我正在使用 auth0 进行身份验证。当我单击“登录”时,我重定向到我使用谷歌帐户登录的 auth0 页面,然后我重定向到我的 Angular 应用程序。问题是我需要刷新页面以获取用户个人资料信息或访问令牌。我在导航栏“昵称和头像”中有一个用户信息,所以我需要在返回页面后直接获取这些信息。

我尝试将 handleauthentication() 方法放在很多地方,与 getUserProfile() 方法相同。

所以这是我的身份验证服务

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

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

  userProfile: any;

  public  auth0 = new auth0.WebAuth({
    clientID: environment.clientID,
    domain: environment.domain,
    responseType: environment.responseType,
    audience: environment.audience,
    redirectUri: environment.redirectUri,
    scope: environment.requestedScopes
  });


  constructor(private router: Router) {
  }

  public getProfile(cb): void {
    const accessToken = localStorage.getItem('access_token');
    if (!accessToken) {
      throw new Error('Access Token must exist to fetch profile');
    }
    const self = this;
    this.auth0.client.userInfo(accessToken, (err, profile) => {
      if (profile) {
        self.userProfile = profile;
        console.log(self.userProfile);
      }
      cb(err, profile);
    });
  }

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

  public handleAuthentication(): void {
    this.auth0.parseHash((err, authResult) => {
      if (authResult && authResult.accessToken && authResult.idToken) {
        window.location.hash = '';
        this.setSession(authResult);
        this.router.navigate(['/home']);
      } else if (err) {
        this.router.navigate(['/error']);
        console.log(err);
        alert('Error: ${err.error}. Check the console for further details.');
      }
    });
  }

  private setSession(authResult): void {
    const expiresAt = JSON.stringify(authResult.expiresIn * 1000 + new Date().getTime());
    const scopes = authResult.scope || environment.requestedScopes || '';

    localStorage.setItem('access_token', authResult.accessToken);
    localStorage.setItem('id_token', authResult.idToken);
    localStorage.setItem('expires_at', expiresAt);
    localStorage.setItem('scopes', JSON.stringify(scopes));
    console.log(localStorage.getItem('access_token'));
  }




  public logout(): void {
    localStorage.removeItem('access_token');
    localStorage.removeItem('id_token');
    localStorage.removeItem('expires_at');
    localStorage.removeItem('scopes');
    this.router.navigate(['/']);
  }

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

  public userHasScopes(scopes: Array<string>): boolean {
    const grantedScopes = JSON.parse(localStorage.getItem('scopes')).split(',');
    return scopes.every(scope => grantedScopes.includes(scope));
  }

  public renewToken() {
    this.auth0.checkSession((err,result) => {
      if(!err){
        this.setSession(result);
      }
    })
  }
}

我的应用组件

import { PostService } from './services/post.service';
import { ProfileService } from './services/profile.service';
import { Component, OnInit } from '@angular/core';
import { AuthService } from './services/auth.service';

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

  constructor(public auth: AuthService, private postService: PostService) {
    auth.handleAuthentication();
  }

  ngOnInit() {
    this.postService.getMessage();
  }
}

和我的导航栏 ts

import { ProfileService } from './../../services/profile.service';
import { AuthService } from './../../services/auth.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
  profile: any;

  constructor(private auth: AuthService) { }

  ngOnInit() {
    if (this.auth.userProfile) {
      this.profile = this.auth.userProfile;
    } else {
      this.auth.getProfile((err, profile) => {
        this.profile = profile;
      });
    }
  }

  login(): void {
    this.auth.login();

  }

  logout(): void {
    this.auth.logout();
  }

  isAuthenticated(): boolean {
    return this.auth.isAuthenticated();
  }
}

我的回调组件是空的

我需要在重定向到 Angular 应用程序后而不是在单击刷新后获取用户配置文件。

标签: angularapiasynchronousauth0

解决方案


Hy 使用 BehaviourSubject 将直接数据提取到导航栏中,例如

 public handleAuthentication(): void {
    this.auth0.parseHash((err, authResult) => {
      if (authResult && authResult.accessToken && authResult.idToken) {
        this.setSession(authResult);
        this.getUserManagmentProfile();
        const returnURL = localStorage.getItem('PM_ReturnUrl');
        if (returnURL) {
          this.router.navigate([returnURL]);
        } else { this.router.navigate(['/dashboard']); }
      } else if (err) {
        this.router.navigate(['/login']);
      }
      this.getProfile(null);
    });
  }

  getUserManagmentProfile() {
    if (this.isAuthenticated()) {
      this.userService.getUserProfile.subscribe(result => {
        const profile = result as any;
        this.languageService.setLanguage(profile.locale);
      });
    }
  }


推荐阅读