2017-10-17 4 views
2

Je rencontre un problème avec mon application Angular 4 et la protection canActivate lors de l'utilisation de Firebase.Angular4 canActivate et google firebase

J'ai ce service AuthService qui lie à firebase.

@Injectable() 
export class AuthService { 

    authState: any = null; 

    constructor(private afAuth: AngularFireAuth,private db: AngularFireDatabase,private router:Router) { 
    this.afAuth.authState.subscribe((auth) => { 
     this.authState = auth 
    }); 

    this.afAuth.auth.onAuthStateChanged(user => { 
     if(user){ 
     console.log('user signed in'); 
     } 
     else{ 
     this.anonymousLogin(); 
     } 
    }) 
    } 

    get authenticated(): boolean { 
    return this.authState !== null; 
    } 

    get currentUser(): any { 
    return this.authenticated ? this.authState : null; 
    } 

    get currentUserAnonymous(): boolean { 
    return this.authenticated ? this.authState.isAnonymous : false; 
    } 

    //// Google Auth //// 
    googleLogin() { 
    const provider = new firebase.auth.GoogleAuthProvider() 
    return this.socialSignIn(provider); 
    } 
    private socialSignIn(provider) { 
    return this.afAuth.auth.signInWithPopup(provider) 
     .then((credential) => { 
      this.authState = credential.user 
     }) 
     .catch(error => console.log(error)); 
    } 

    //// Anonymous Auth //// 
    anonymousLogin() { 
    return this.afAuth.auth.signInAnonymously() 
    .then((user) => { 
     this.authState = user 
    }) 
    .catch(error => console.log(error)); 
    } 

    //// Email/Password Auth //// 
    emailLogin(email:string, password:string) { 
    return this.afAuth.auth.signInWithEmailAndPassword(email, password) 
     .then((user) => { 
     this.authState = user 
     }) 
     .catch(error => console.log(error)); 
    } 

    //// Sign Out //// 
    signOut(): void { 
    this.afAuth.auth.signOut(); 
    this.router.navigate(['/']) 
    } 
} 

et ceci est mon garde

@Injectable() 
export class AuthGuard implements CanActivate { 

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

    canActivate(
    next: ActivatedRouteSnapshot, 
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean { 
     if(this.auth.authState && !this.auth.currentUserAnonymous){ 
     console.log('User is staff'); 
     return true; 
     } 
     else{ 
     console.log(this.auth.authState); 
     console.log(this.auth.currentUserAnonymous); 
     console.log('User is not staff') 
     this.router.navigate(['/']); 
     return false; 
     } 
    } 
} 

Le gardien fonctionne très bien lorsque vous naviguez sur le composant surveillé en utilisant un lien d'un autre composant lorsque l'utilisateur est connecté, mais lorsque vous essayez d'aller directement à la composant surveillé en utilisant la barre d'adresse il enregistre les éléments suivants

auth.guard.ts:20 null <-- this.auth.authState 
auth.guard.ts:21 false <-- this.auth.currentUserAnonymously 
auth.guard.ts:22 User is not staff 
auth.service.ts:19 user signed in 

car il se connecte l'utilisateur connecté "du service auth après la garde, il semble que cela signifie la auth.service est c vérification de l'état connecté après la garde. Comment puis-je changer cela pour faire le service en premier? Ou dois-je faire appel au service de la garde? Merci

+1

Je ne suis pas familier avec AngularFireAuth mais vous devez avoir le canActivate retourner la promesse this.afAuth.auth.onAuthStateChanged – Carsten

+0

Lisez la définition de la méthode - vous pouvez retourner une promesse ou observable, qu'Angular va alors résoudre pour vous avant de continuer. – jonrsharpe

+0

Je suis conscient de cela mais j'ai besoin de 2 conditions car l'utilisateur peut être authentifié anonymement –

Répondre

1

Je pense que vous voulez utiliser l'observable dans votre canActivate. Vous aurez besoin de quelque chose comme ceci:

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean { 
    return this.afAuth.authState.map(auth => { 
     if (isNullOrUndefined(auth)) { 
      this.router.navigate(['/']); 
      return false; 
     } else { 
      return true; 
     } 
    }); 
}