Auth0和Angular 2:使用登录窗口小部件

时间:2016-07-25 17:28:28

标签: angular jwt angular2-routing auth0

我开始开发Web应用程序并选择Angular 2作为前端框架。我目前正在尝试使用Auth0进行用户授权。 问题如下: 我正在尝试实施登录页面登录 - >重定向功能。打开网站后,应立即检查localStorage中是否有用户的令牌,然后显示登录窗口小部件或重定向到主页。但我遇到了这个非常讨厌的错误:

当我登录时,页面会刷新并再次显示小部件:tokenNotExpired()由于某种原因返回false。我再次使用相同的凭据登录 - 页面刷新,登录窗口小部件消失,日志显示tokenNotExpired()现在正在返回true,但我的重定向仍然无法正常工作。如果我现在只输入我的基地http://localhost:4200,则会成功将我重定向到hometokenNotExpired()会返回true

我试过调试但没有运气 - 我无法找到失败的地方。

基本上,我非常确定我在编写重定向功能时遇到问题,因为我缺乏经验。我非常感谢任何帮助,一直坐在这上面。

我包括省略冗余部分的代码摘录。我通过在main.ts中引导它来全局注入Auth服务。

app.routes.ts:

import {provideRouter, RouterConfig} from "@angular/router";
import {AuthGuard} from './secure/auth.guard';
import {AdminGuard} from "./secure/admin.guard";

import {UserHomeComponent} from "./main/user-cpl/user-home.component";
import {AdminHomeComponent} from "./main/admin-cpl/admin-home.component";
import {LoginPageComponent} from "./login/login-page.component";

const APP_ROUTES: RouterConfig = [

  { path: 'home', canActivate: [AuthGuard],
    children: [
      { path: '', component: UserHomeComponent },
      { path: 'admin', component: AdminHomeComponent, canActivate: [AdminGuard] },
      ] },
  { path: 'login', component: LoginPageComponent },
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: '**', redirectTo: 'home', pathMatch: 'full' }
];

export const APP_ROUTES_PROVIDER = [
  provideRouter(APP_ROUTES)
];

登录-page.component.ts:

import {Component, OnInit} from '@angular/core';
import {ROUTER_DIRECTIVES, Router} from '@angular/router';
import {Auth} from '../secure/auth.service';

@Component({
  moduleId: module.id,
  selector: 'login-page-component',
  template: `
    <router-outlet></router-outlet>  
  `,
  directives: [ROUTER_DIRECTIVES]
})
export class LoginPageComponent implements OnInit {

  constructor(private auth: Auth, private router: Router) {
  }

  ngOnInit():any {
    console.log('LOGGED IN - ' + this.auth.loggedIn());
    if (this.auth.loggedIn()) {
      if (this.auth.isAdmin()) {
        this.router.navigate(['/home/admin']);
      } else if (!this.auth.isAdmin()) {
        this.router.navigate(['/home']);
      }

    } else {
      this.auth.login();
    }
  }
}

auth.service.ts:

import {Injectable} from '@angular/core';
import {tokenNotExpired} from 'angular2-jwt';

declare var Auth0Lock: any;

@Injectable()
export class Auth {
  // Configure Auth0
  lock = new Auth0Lock('omitted', 'omitted', {
    closable: false
  });

  //Store profile object in auth class
  userProfile: any;

  constructor() {
    // Set userProfile attribute if already saved profile
    this.userProfile = JSON.parse(localStorage.getItem('profile'));

    // Add callback for lock `authenticated` event
    this.lock.on("authenticated", (authResult) => {
      localStorage.setItem('id_token', authResult.idToken);

      // Fetch profile information
      this.lock.getProfile(authResult.idToken, (error, profile) => {
        if (error) {
          // Handle error
          alert(error);
          return;
        }

        localStorage.setItem('profile', JSON.stringify(profile));
        this.userProfile = profile;
      });
    });
  }

  login() {
    this.lock.show({
      callbackUrl: 'http://localhost:4200/home'
    });
  }

  logout() {
    localStorage.removeItem('profile');
    localStorage.removeItem('id_token');
    this.userProfile = undefined;
  }

  loggedIn() {
    return tokenNotExpired();
  }

  isAdmin() {
    return this.userProfile && this.userProfile.app_metadata
      && this.userProfile.app_metadata.roles
      && this.userProfile.app_metadata.roles.indexOf('admin') > -1;
  }
}

auth.guard.ts:

import {Injectable} from '@angular/core';
import {Router, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {CanActivate} from '@angular/router';
import {Auth} from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private auth: Auth, private router: Router) {
  }

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (this.auth.loggedIn()) {
      console.log('AUTH GUARD PASSED');
      return true;
    } else {
      console.log('BLOCKED BY AUTH GUARD');
      this.router.navigate(['/login']);
      return false;
    }
  }
}

admin.guard.ts:

import {Injectable} from '@angular/core';
import {Router, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {CanActivate} from '@angular/router';
import {Auth} from './auth.service';

@Injectable()
export class AdminGuard implements CanActivate {

  constructor(private auth: Auth, private router: Router) {}

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (this.auth.isAdmin()) {
      return true;
    } else {
      return false;
    }
  }
}

1 个答案:

答案 0 :(得分:5)

您必须在配置中设置redirect: false,因为它是单页应用。否则,Auth0将对redirectUrl进行GET调用。此调用阻止您的authenticated事件触发。因此,在 auth.service.ts 文件中:

lock = new Auth0Lock('omitted', 'omitted', {
  closable: false,
  auth: { // <--- mind this nesting
    redirect: false
  }
});

这将在登录时调用服务中的“authenticated”事件。登录完成后,您可能还希望重定向用户。因此,在回调调用this._router.navigate(['path'])中。不要忘记import { Router } from 'angular/router'并在构造函数中创建实例:constructor(private _router: Router) {}

相关问题