Menggunakan Authentication Pada Project Buku Resep – 11

Auto Login

Sampai sejauh ini, informasi user masih disimpan dalam memory. Jika aplikasi di reload, maka data user dan authentication akan hilang.

Untuk itu kita perlu menyimpan data kedalam local storage.

Buka file auth.service.ts, lalu tambahkan code pada method handleAuth dan autoLogin.(lihat code dengan bagian komentar).

Selain itu kita perlu mengganti tipe subject menjadi ReplaySubject.

import {Injectable} from '@angular/core';
import {HttpClient, HttpErrorResponse} from '@angular/common/http';
import { Router } from '@angular/router';

import { catchError, tap } from 'rxjs/operators';
//import ReplaySUbject
import { ReplaySubject, throwError } from 'rxjs';

import { User } from './user.model';

export interface AuthResponse {
    idToken: string;
    email: string;
    refreshToken: string;
    expiresIn: string;
    localId: string;
    registered?: boolean; 
}

@Injectable({providedIn: 'root'})
export class AuthService {
    //ubah user subject menjadi ReplaySubject
    user = new ReplaySubject<User>();
    token = "";

    //inject router
    constructor(private http: HttpClient, private router : Router){}

    signUp(email: string, pswrd: string){
        return this.http
        .post<AuthResponse>('https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyAHq81IV8SqS_n6KL9wEmuB_qs3_8J4szU',
            {
                email: email, 
                password: pswrd, 
                returnSecureToken: true
            }
        )
        .pipe(catchError(this.errHandling), tap(respData=>{
            this.handleAuth(respData.email, respData.localId, respData.idToken, +respData.expiresIn);
        }));
    }

    login(email: string, pswrd: string){
        return this.http
        .post<AuthResponse>('https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyAHq81IV8SqS_n6KL9wEmuB_qs3_8J4szU',
            {
                email: email, 
                password: pswrd, 
                returnSecureToken: true                
            }
        ).pipe(catchError(this.errHandling), tap(respData=>{
            this.handleAuth(respData.email, respData.localId, respData.idToken, +respData.expiresIn);
        }));   
    }

    //method untuk autologin berdasarkan data localstorage
    autoLogin(){
        const userData :{
            email: string;
            id: string;
            _token: string;
            _tokenExpDt: string;
        } = JSON.parse(localStorage.getItem("userData") || '{}') ;

        if(!userData){
            return;
        }else{
            const loadUser = new User(userData.email, userData.id, userData._token, new Date(userData._tokenExpDt));
            if(loadUser.token){
                this.user.next(loadUser);
                this.token = userData._token; 
            }
        }
    }

    logout(){
        this.user.next(undefined);
        this.token = "";
        this.router.navigate(['/auth']);
    }

    private handleAuth(email: string, userId: string, token: string, expiresIn: number){
        const expDate = new Date(new Date().getTime()+ (expiresIn*1000));
        const user = new User(email, userId, token, expDate);
        this.user.next(user);
        this.token = token;
        //menyimpan data ke localstorage
        localStorage.setItem('userData', JSON.stringify(user));
    }

    private errHandling(errResp: HttpErrorResponse){
        let errMsg = 'Unknown Error...';

        if (!errResp.error || !errResp.error.error){
            return throwError(errMsg);
        }
        switch(errResp.error.error.message){
            case 'EMAIL_EXISTS':      
                errMsg = 'Email sudah terdaftar';
                break;
            case 'EMAIL_NOT_FOUND':
                errMsg = 'User belum terdaftar';
                break;
            case 'INVALID_PASSWORD':
                errMsg = 'User atau Password salah';
                break;                
        }
        return throwError(errMsg);
    }
}

Kemudian buka app.component.ts, implementasikan method ngOnInit untuk melakukan proses autoLogin.

import { Component, OnInit } from '@angular/core';
import { AuthService } from './auth/auth.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  constructor(private authSrv : AuthService){}
  
  ngOnInit(): void {
    this.authSrv.autoLogin();
  }
}

JIka Anda coba reload, aplikasi tetap dalam status authenticated.

Auto Logout

Berikutnya kita akan implementasikan autoLogout, karena token terdapat masa expires.

Buka file auth.service.ts, lalu ubah menjadi code seperti dibawah

import {Injectable} from '@angular/core';
import {HttpClient, HttpErrorResponse} from '@angular/common/http';
import { Router } from '@angular/router';

import { catchError, tap } from 'rxjs/operators';
import { ReplaySubject, throwError } from 'rxjs';

import { User } from './user.model';

export interface AuthResponse {
    idToken: string;
    email: string;
    refreshToken: string;
    expiresIn: string;
    localId: string;
    registered?: boolean; 
}

@Injectable({providedIn: 'root'})
export class AuthService {
    user = new ReplaySubject<User>();
    token = "";
    private tokenExpTimer : any;

    constructor(private http: HttpClient, private router : Router){}

    signUp(email: string, pswrd: string){
        return this.http
        .post<AuthResponse>('https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyAHq81IV8SqS_n6KL9wEmuB_qs3_8J4szU',
            {
                email: email, 
                password: pswrd, 
                returnSecureToken: true
            }
        )
        .pipe(catchError(this.errHandling), tap(respData=>{
            this.handleAuth(respData.email, respData.localId, respData.idToken, +respData.expiresIn);
        }));
    }

    login(email: string, pswrd: string){
        return this.http
        .post<AuthResponse>('https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyAHq81IV8SqS_n6KL9wEmuB_qs3_8J4szU',
            {
                email: email, 
                password: pswrd, 
                returnSecureToken: true                
            }
        ).pipe(catchError(this.errHandling), tap(respData=>{
            this.handleAuth(respData.email, respData.localId, respData.idToken, +respData.expiresIn);
        }));   
    }

    autoLogin(){
        const userData :{
            email: string;
            id: string;
            _token: string;
            _tokenExpDt: string;
        } = JSON.parse(localStorage.getItem("userData") || '{}') ;

        if(!userData){
            return;
        }else{
            const loadUser = new User(userData.email, userData.id, userData._token, new Date(userData._tokenExpDt));
            if(loadUser.token){
                this.user.next(loadUser);
                this.token = userData._token; 
                //lakukan perhitungan delta dari expired date dengan current date dalam ms.
                const expDur = new Date(userData._tokenExpDt).getTime() - new Date().getTime();
                this.autoLogout(expDur);
            }
        }
    }

    //method untuk autologout ketika token expired
    autoLogout(expDuration : number){
       this.tokenExpTimer =  setTimeout(()=>{
            this.logout();
        }, expDuration);
    }

    logout(){
        this.user.next(undefined);
        this.token = "";
        this.router.navigate(['/auth']);
        //hapus data local storage dan setup autologout
        localStorage.removeItem('userData');
        if(this.tokenExpTimer){
            clearTimeout(this.tokenExpTimer);
        }
        this.tokenExpTimer = null;
    }

    private handleAuth(email: string, userId: string, token: string, expiresIn: number){
        const expDate = new Date(new Date().getTime()+ (expiresIn*1000));
        const user = new User(email, userId, token, expDate);
        this.user.next(user);
        //tambahkan autologout
        this.autoLogout(expiresIn * 1000);
        this.token = token;
        localStorage.setItem('userData', JSON.stringify(user));
    }

    private errHandling(errResp: HttpErrorResponse){
        let errMsg = 'Unknown Error...';

        if (!errResp.error || !errResp.error.error){
            return throwError(errMsg);
        }
        switch(errResp.error.error.message){
            case 'EMAIL_EXISTS':      
                errMsg = 'Email sudah terdaftar';
                break;
            case 'EMAIL_NOT_FOUND':
                errMsg = 'User belum terdaftar';
                break;
            case 'INVALID_PASSWORD':
                errMsg = 'User atau Password salah';
                break;                
        }
        return throwError(errMsg);
    }
}
Sharing is caring:

Leave a Comment