Authentification et enregistrement avec Firebase
1. Motivation
On va voir comment authentifier et enregistrer des utilisateurs d’une app angular.
Nous allons étendre l’application déjà développée dans le cours et le tp précédent.(gestion de produits).
L’objectif est chaque utilisateur doit s’authentifier avant d’utiliser l’application et s’il n’est pas enregistrer alors il peut faire un enregistrement.
Si l’utilisateur demande la page ajouter (add) et il n’est pas authentifie alors on lui redirige vers la page login.
Etapes
2. Configurer un projet firebase pour permettre l’authentification en utilisant les emails et les mots de passes.
Cliquer sur authentication > Sign-in

Puis cliquer sur Email/Password row et puis sur Enable
en fin cliquer sur save.
Aller authentication > Users tab et cliquer sur le bouton Add user pour ajouter un utilisateur afin de tester votre code.

3. Créer un projet gestionproduits
4. Créer un composant add( ajouter)
5. Créer un composant enregistrer
6. Ouvrir le fichier src/app/admin/admin-routing.module.ts file et ajouter les Chemins de ces composants afin de permettre la navigation entre eux.
Voici les résultats
|
import { Component } from '@angular/core'; import { AngularFireAuth } from '@angular/fire/auth'; import { auth } from 'firebase/app'; import { AuthService } from './auth.service'; import { Router } from "@angular/router";
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(private router: Router) { } ngOninit(){
var user=localStorage.getItem('user');
if (user) this.router.navigate(['add']) else this.router.navigate(['login']) ;
}
} Html <router-outlet> </router-outlet>
|
import { Component, OnInit } from '@angular/core'; import { AngularFireAuth } from '@angular/fire/auth'; import { auth } from 'firebase/app'; import { AuthService } from '../auth.service';
@Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit {
u:string; p:string; constructor(private aut: AuthService) { }
changeu(u){ this.u=u; }
changep(p){ this.p=p; }
login() { this. aut.login(this.u,this.p); } enrigistrer() { this. aut.login(this.u,this.p); }
ngOnInit(): void { }
}
///html <p>login!</p> <input #u type="text" (keyup)="changeu(u.value) " > <input #p type="text" (keyup)="changep(p.value)" > <button (click)="login()" >Login</button> <a routerLink="/enrigister" routerLinkActive="active">s'inscrire</a>
|
|
|
|
import { Component, OnInit } from '@angular/core'; import { FormControl,Validators } from '@angular/forms'; import { AngularFireDatabase} from '@angular/fire/database'; import { AngularFireList , AngularFireObject } from 'angularfire2/database'; import { AngularFirestore } from '@angular/fire/firestore'; import { produit } from 'tp2/src/app/produit'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { AuthService } from '../auth.service'; import { Router } from "@angular/router"; @Component({ selector: 'app-add', templateUrl: './add.component.html', styleUrls: ['./add.component.css'] }) export class AddComponent { e=false; p:[]; designation = new FormControl(''); id = new FormControl(''); prix = new FormControl(); private basePath: string = '/produits'; //list of objects produits: AngularFireList<any>; items: Observable<any[]>; produitt: AngularFireObject<any[]> = null produitss:AngularFireList<any[]> ;
constructor(private db: AngularFireDatabase,private Auth:AuthService,private router:Router) {var user=localStorage.getItem('login'); console.log("hhhhhh"+user);
this.produits= db.list('/produits');//AngularFireList<product[]> ; this.items = this.produits.snapshotChanges().pipe( map(changes => changes.map(c => ({ key: c.payload.key, ...c.payload.val() })) ) );
}
private handleError(error) { console.log(error) }
adddata(): void { var item=new product(); item.d=this.designation.value; item.id=this.id.value; item.prix=this.prix.value; this.produits = this.db.list('/produits');
this.produits.push([item]);
}
affiche(): void {
this.db .object('/produits') .valueChanges() .subscribe(data => { console.log('our book', data);
}); this.e=true;
//listObservable.subscribe(); }
// Return a single observable item
ngOnInit(): void {
}
addItem() { var item=new product(); item.d=this.designation.value; item.id=this.id.value; item.prix=this.prix.value; this.produits.push(item); } updateItem(key: string,des:string,pr:string) {
var item=new product(); item.d=des;
item.prix=pr; this.produits.update(key, item); } deleteItem(key: string) { this.produits.remove(key); } deleteEverything() { this.produits.remove(); } logout(){ console.log(localStorage.getItem('isconnected')); localStorage.setItem('isconnected','false'); this.Auth.logout(); this.router.navigate(['login']); }
} class product { $key: string; d:string; id:string; prix:string;
} Html
<h3>Using FormControl </h3> <div> <div> id: <input [formControl]="id"> </div> <div> designation: <input [formControl]="designation">
</div>
<div> prix: <input [formControl]="prix"> </div>
<p>id: {{ id.value }}</p> <p>designation: {{ designation.value }}</p> <p>prix {{ prix.value }} </p>
<ul> <li *ngFor="let item of items | async"> <input type="text" #updatedes [value]="item.designation" /> <input type="text" #updatepr [value]="item.prix" />
<button (click)="updateItem(item.key, updatedes.value,updatepr.value)">Update</button> <button (click)="deleteItem(item.key)">Delete</button> </li> </ul> <input type="text" #newitem /> <button (click)="addItem()">Add</button> <button (click)="deleteEverything()">Delete All</button> <button (click)="logout();"> logout</button>
|
import { Component, OnInit } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-enrigister', templateUrl: './enrigister.component.html', styleUrls: ['./enrigister.component.css'] }) export class EnrigisterComponent implements OnInit {
constructor(private aut: AuthService) { }
ngOnInit(): void { } enrigistrer(){
this.aut.
} }
À vous de completer le comoposnat |
|
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { AddComponent } from './add/add.component'; import { ListpComponent } from './listp/listp.component'; import { EnrigisterComponent } from './enrigister/enrigister.component'; import { LoginComponent } from './login/login.component'; import { AdminGuard } from './admin.guard';
const routes: Routes = [{path: '', redirectTo: 'login', pathMatch: 'full'}, { path: 'logout', component: LoginComponent}, { path: 'enrigister', component: EnrigisterComponent}, { path: 'login', component: LoginComponent},{ path: 'add', component: AddComponent,canActivate: [AdminGuard]}];
@NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
|
|
7. Créer un service d’authentification. Le service permet d’authentifier les utilisateurs en utilisant les emails et les mots de passes.
|
import { Injectable } from '@angular/core'; import { Router } from "@angular/router"; import { auth } from 'firebase/app'; import { AngularFireAuth } from "@angular/fire/auth"; import { User } from 'firebase'; import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root' }) export class AuthService {
private user: Observable<firebase.User>=null; private userDetails: firebase.User = null;
constructor(public afAuth: AngularFireAuth, public router: Router) { this.afAuth.authState.subscribe(user => { if (user){
localStorage.setItem('isconnected', 'true'); } else { localStorage.setItem('isconnected', 'false'); } }) } login(email: string, password: string) { var result = this.afAuth.signInWithEmailAndPassword(email, password).then(()=>{console.log("logged");
this.router.navigate(['/add']); }).catch((error)=>{console.log("erreour"+error);});
}
async register(email: string, password: string) { var result = await this.afAuth.createUserWithEmailAndPassword(email, password); this.sendEmailVerification(); } async sendEmailVerification() { //await await this.afAuth.currentUser.sendEmailVerification(); this.router.navigate(['admin/verify-email']); } async sendPasswordResetEmail(passwordResetEmail: string) { // return await this.afAuth.sendPasswordResetEmail(passwordResetEmail); } isLoggedIn(): boolean { console.log("inside login service"+localStorage.getItem('isconnected')) if ((localStorage.getItem('isconnected')=='true' )) { return true; } else { return false; }
}
logout(){
this.afAuth.signOut().then(function() {
console.log("Logout successful"); localStorage.setItem('isconnected','false');
}, function(error) {
console.log(error);
}); };
}
|
8. Protéger les routes avec Guard
On veut pas que les utilisateurs accèdent à la page add sans qu’ils sont authentifiés. Alors toute tentative donnera lieu à une redirection vers la page login.
Pour mettre en place ce mécanisme angular nous fournit un outil : Guard
Une guard est :
Un service Angular (donc decoré par @Injectable) qui
implemente une des interfaces suivantes
CanActivate : vérifie si un utilisateur peut visiter une route.
CanDeactivate : vérifie si un utilisateur peut quitter une route.
CanActivateChild : vérifie si un utilisateur peut visiter les routes enfants.
CanLoad : verifie si un utilisateur peut aller sur une route d’un module défini avec un lazy loading
9. Dans notre cas
On veut que l’accès a la route /add est autorisé seulement aux utilisateurs authentifies
On va créer une guard admin et l’associer a la route adresse
Pour créer une guard on exécute la commande
ng g guard admin
voici le contenu de la guard
|
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot,Router, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root' }) export class AdminGuard implements CanActivate { constructor(private authe: AuthService,private router: Router){} canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean | UrlTree { console.log("herer guard"+this.authe.isLoggedIn()) if(this.authe.isLoggedIn()){ return true; } else {
this.router.navigateByUrl('/login'); }
}
}
|
Dans cette guard on vérifie si l’user est authentifie si oui alors on navigue vers la route si non on le redirige vers login.
Noter qu’on a modifie la route ‘add’ en joutant canactivate
const routes: Routes = [{path: '', redirectTo: 'login', pathMatch: 'full'},
{ path: 'logout', component: LoginComponent},
{ path: 'enrigister', component: EnrigisterComponent},
{ path: 'login', component: LoginComponent},{ path: 'add', component: AddComponent,canActivate: [AdminGuard]}];