2016-07-25 5 views
2

Ich beginne mit der Entwicklung von Web-Anwendungen und wählte Angular 2 als Front-End-Framework. Ich probiere gerade Aut0 für Benutzerautorisierung aus. Das Problem ist wie folgt: Ich versuche, eine Zielseite Login -> Redirect-Funktionalität zu implementieren. Unmittelbar nach dem Öffnen der Website sollte überprüft werden, ob sich ein Benutzer-Token in der localStorage befindet und dann entweder das Login-Widget angezeigt wird oder auf die Homepage umgeleitet wird. Aber ich bin in diesen sehr bösen Fehler gelaufen:Auth0 und Angular 2: Login und Routing fehlgeschlagen mit dem Login-Widget

Wenn ich mich anmelde, wird die Seite aktualisiert und das Widget erscheint wieder: tokenNotExpired() gibt aus irgendeinem Grund false zurück. Ich drücke, um mich erneut mit den gleichen Anmeldeinformationen anzumelden - Seite aktualisiert, Login-Widget verschwindet, Protokollierung zeigt, dass tokenNotExpired()true jetzt zurückgibt, aber meine Weiterleitung funktioniert immer noch nicht. Wenn ich jetzt nur meine Basisadresse, http://localhost:4200, eingeben, leitet es mich erfolgreich zu home und tokenNotExpired() zurück true.

Ich habe versucht, es zu debuggen, aber ohne Glück - ich kann nicht finden, wo es versagt.

Im Wesentlichen bin ich mir sehr sicher, dass es Probleme in der Art und Weise gibt, wie ich die Redirect-Funktion anspreche, da ich keine Erfahrung habe. Ich würde sehr dankbar für jede Hilfe sein, habe eine Weile darauf gesessen.

Ich habe Auszüge aus meinem Code enthalten die überflüssigen Teile weglassen. Ich injiziere den Auth-Dienst global, indem ich ihn in main.ts bootstrappte.

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) 
]; 

Login-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

In 'auth.login()' sollte Ihr Attribut 'callbackURL' sein. Ich glaube, dass dies für OAuth case sensitive ist. – ghg565

+0

@ ghg565 Ja, ich habe es geändert, aber es hat keine Auswirkungen darauf.Ich erkannte auch, dass es CallbackURL nicht verwendet, um irgendwohin umzuleiten, stattdessen geht es zurück auf die Anmeldeseite und speichert die Anmeldeinformationen nicht beim ersten Mal. – praktikantas

Antwort

4

Sie redirect: false in der Konfiguration festgelegt muss, da es sich um eine einzelne Seite app ist. Auth0 wird sonst einen GET-Aufruf an die redirectUrl vornehmen. Dieser Anruf verhindert, dass Ihr authenticated-Ereignis ausgelöst wird. So in Ihrer auth.service.ts Datei:

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

Dies wird die ‚authentifiziert‘ Veranstaltung im Dienst bei der Anmeldung aufrufen. Wahrscheinlich möchten Sie den Benutzer nach der Anmeldung auch umleiten. Rufen Sie daher im Rückruf this._router.navigate(['path']) auf. Vergessen Sie nicht import { Router } from 'angular/router' und erstellen Sie eine Instanz im Konstruktor: constructor(private _router: Router) {}.

+0

Wenn Sie redirect auf false setzen, wird der Popup-Modus aktiviert, der in der Dokumentation folgende Warnung enthält: Es gibt einen bekannten Fehler, der verhindert, dass der Popup-Modus in Android oder Firefox unter iOS und im Internet Explorer unter bestimmten Umständen ordnungsgemäß funktioniert. Daher empfehlen wir, entweder nur den Umleitungsmodus zu verwenden oder diese Sonderfälle zu erkennen und den Weiterleitungsmodus selektiv zu aktivieren. –