handle Refresh token - Angular interceptor
Mon Feb 27 2023 11:37:37 GMT+0000 (Coordinated Universal Time)
Saved by @mtommasi
import { catchError, EMPTY, Observable, switchMap, throwError } from 'rxjs'; import { AuthenticationService } from '../authentication.service'; import { UserService } from '../user.service'; @Injectable({ providedIn: 'root', }) export class AuthInterceptorService implements HttpInterceptor { constructor(private injector: Injector) {} intercept( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { //this request should handle request if token is expired: //use a flag like "retry" if i should retry const reqClone = req.clone({ headers: req.headers.delete('skip', 'true') }); return next.handle(reqClone).pipe( catchError((err) => { if (err.status === 401) { return this.handleRefreshToken(req, next); } return EMPTY; }) ); } handleRefreshToken( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { const authService = this.injector.get(AuthenticationService); // approfondisci sta cosa return authService.refresh().pipe( switchMap((resp) => { return next.handle(req); // ripeto la richiesta con il sessiontoken fresco }) ); } } import { Injectable } from '@angular/core'; import { BehaviorSubject, catchError, EMPTY, filter, map, shareReplay, tap, } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { IUser, IUserSignup } from '../models/user/user'; import { environment } from 'src/environments/environment'; import { LoginRequest } from '../models/login/login.request'; import { LoginResponse } from '../models/login/login.response'; const anonimous_USER: IUser = { email: '', username: '', id: '', roles: [], }; @Injectable({ providedIn: 'root', }) export class AuthenticationService { private BASE = environment.base; private SIGNUP_URL = `${this.BASE}${environment.signupURL}`; private LOGOUT_URL = `${this.BASE}${environment.logout}`; private LOGIN_URL = `${this.BASE}${environment.login}`; private USER_URL = `${this.BASE}${environment.user}`; private REFRESH_URL = `${this.BASE}${environment.refresh}`; private ADMIN_AS_USER_URL = `${this.BASE}${environment.admin}${environment.loginAsUser}`; private subject = new BehaviorSubject<IUser | undefined>(anonimous_USER); public user$ = this.subject.pipe(filter((user) => Boolean(user))); public isLoggedIn$ = this.user$.pipe(map((user) => Boolean(user?.id))); public isLoggedOut$ = this.isLoggedIn$.pipe(map((loggedIn) => !loggedIn)); constructor(private http: HttpClient) { this.getUserSession().subscribe((user) => this.subject.next(user)); } signup(user: IUserSignup) { return this.http .post<IUser>(this.SIGNUP_URL, user, { headers: { skip: 'true' }, }) .pipe( shareReplay(), tap((user) => { console.log(user); this.subject.next(user); }) ); } getUserSession() { return this.http .get<IUser | undefined>(this.USER_URL, { headers: { skip: 'true' }, }) .pipe(shareReplay()); } logout() { return this.http .post(this.LOGOUT_URL, null, { headers: { skip: 'true' } }) .pipe( shareReplay(), tap(() => { this.subject.next(anonimous_USER); // emetto un utente nullo }) ); } login(loginRequest: LoginRequest) { return this.http .post<LoginResponse>(this.LOGIN_URL, loginRequest, { headers: { skip: 'true' }, }) .pipe( shareReplay(), tap((user) => { this.subject.next(user); }) ); } loginAsUser(userEmail: string) { return this.http .post<LoginResponse>( this.ADMIN_AS_USER_URL, { email: userEmail }, { headers: { skip: 'true' }, } ) .pipe( shareReplay(), tap((user) => { this.subject.next(user); }) ); } refresh() { const email = this.subject.value?.email; return this.http.post(this.REFRESH_URL, { email: email || '' }).pipe( tap({ error: (err) => { console.log(err); }, }), shareReplay(), catchError(() => { return EMPTY; // non voglio che fa nulla se c'è un errore }) ); } }
Comments