2016-07-25 79 views
2

我開始開發Web應用程序並選擇Angular 2作爲前端框架。我目前正在嘗試使用Auth0進行用戶授權。 問題如下: 我正在嘗試實現登錄頁面登錄 - >重定向功能。打開網站後立即檢查localStorage中是否有用戶令牌,然後顯示登錄小部件或重定向到主頁。但我遇到了這個非常討厭的bug:Auth0和Angular 2:使用登錄小部件登錄和路由失敗

當我登錄時,頁面刷新並且窗口小部件再次出現: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; 
    } 
    } 
} 
+0

在'auth.login()'你的屬性應該是'callbackURL'。我相信這對OAuth是大小寫敏感的。 – ghg565

+0

@ ghg565是的,我改變了它,但它沒有任何影響。我也意識到它不使用callbackURL在任何地方重定向,而是返回到登錄頁面,並且不會在第一次存儲憑據。 – praktikantas

回答

4

您必須在配置中設置redirect: false,因爲它是一個單頁的應用程序。否則Auth0將對redirectUrl進行GET調用。此通話阻止您的authenticated事件啓動。因此,在你的auth.service.ts文件:

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

這將調用在登錄該服務的「認證」事件。登錄完成後,您可能還希望重定向用戶。因此,在回調中調用this._router.navigate(['path'])。不要忘記import { Router } from 'angular/router'並在構造函數中創建一個實例:constructor(private _router: Router) {}

+0

將重定向設置爲false將啓用「彈出式模式」,該模式在文檔中有以下警告:在某些情況下,存在一個已知的問題,它阻止彈出模式在Android或Firefox的iOS和Internet Explorer中正常運行。因此,我們建議要麼只使用重定向模式,要麼檢測這些特殊情況,並選擇性地啓用重定向模式。 –