| import { Injectable } from '@angular/core'; |
| import { BehaviorSubject } from 'rxjs'; |
| import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; |
| import { Observable } from 'rxjs/internal/Observable'; |
| import { tap } from 'rxjs/operators'; |
| import { catchError } from 'rxjs/operators'; |
| import { throwError } from 'rxjs'; |
| @Injectable({ |
| providedIn: 'root' |
| }) |
| export class AuthenticationService { |
| private apiUrl = 'http://127.0.0.1:5000'; |
| private loggedInSubject = new BehaviorSubject<boolean>(this.isLoggedIn()); |
|
|
| constructor(private http: HttpClient) { |
| |
| setInterval(() => this.checkAndRefreshToken(), 30 * 1000); |
|
|
| |
| |
| } |
| |
|
|
|
|
|
|
| |
| |
| login(username: string, password: string): Observable<any> { |
| const loginData = { username, password }; |
| return this.http.post(`${this.apiUrl}/login`, loginData).pipe( |
| tap((response: any) => { |
| |
| |
| localStorage.setItem('access_token', response.access_token); |
| localStorage.setItem('refresh_token', response.refresh_token); |
|
|
| |
| |
| const accessTokenExpiry = Date.now() + 2 * 60 * 1000; |
| localStorage.setItem('access_token_expiry', accessTokenExpiry.toString()); |
|
|
| |
| const refreshTokenExpiry = Date.now() + 10 * 60 * 1000; |
| localStorage.setItem('refresh_token_expiry', refreshTokenExpiry.toString()); |
|
|
| this.loggedInSubject.next(true); |
|
|
| }), |
| catchError(error => { |
| |
| if (error.status === 401 && error.error.message === 'Token has expired') { |
| |
| } |
| return throwError(error); |
| }) |
| ); |
| } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| logout(): Observable<any> { |
| const token = this.getToken(); |
| console.log('π Token at logout start:', token); |
|
|
| this.removeToken(); |
| this.loggedInSubject.next(false); |
|
|
| if (!token) { |
| console.warn('β οΈ No token found. Emitting success anyway.'); |
| return new Observable(observer => { |
| observer.next(true); |
| observer.complete(); |
| }); |
| } |
|
|
| const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`); |
| console.log('π€ Sending logout request with headers:', headers); |
|
|
| return this.http.post(`${this.apiUrl}/logout`, {}, { headers }).pipe( |
| tap(() => { |
| console.log('β
Logout API request completed'); |
| }), |
| catchError((error) => { |
| console.error('β Logout error in service:', error); |
| return new Observable(observer => { |
| observer.next(true); |
| observer.complete(); |
| }); |
| }) |
| ); |
| } |
|
|
|
|
|
|
|
|
|
|
|
|
| |
| getToken(): string | null { |
| return localStorage.getItem('access_token'); |
| } |
|
|
| |
| storeToken(token: string): void { |
| localStorage.setItem('access_token', token); |
| console.log('Token stored:', token); |
| this.loggedInSubject.next(true); |
| } |
| |
| removeToken(): void { |
| localStorage.removeItem('access_token'); |
| localStorage.removeItem('refresh_token'); |
| localStorage.removeItem('access_token_expiry'); |
| this.loggedInSubject.next(false); |
| } |
|
|
| |
| isLoggedIn(): boolean { |
| return !!this.getToken(); |
| } |
| |
| get isLoggedIn$(): Observable<boolean> { |
| return this.loggedInSubject.asObservable(); |
| } |
|
|
|
|
|
|
| checkAndRefreshToken() { |
| const accessTokenExpiry = localStorage.getItem('access_token_expiry'); |
| if (accessTokenExpiry && Date.now() >= (+accessTokenExpiry - 5000)) { |
| |
| this.refreshAccessToken(); |
| } |
|
|
| |
| } |
|
|
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| refreshAccessToken() { |
| const refreshToken = localStorage.getItem('refresh_token'); |
|
|
| if (refreshToken) { |
| this.http.post(`${this.apiUrl}/refresh`, { refresh_token: refreshToken }).subscribe( |
| (response: any) => { |
| |
| localStorage.setItem('access_token', response.access_token); |
|
|
| |
| const newAccessTokenExpiry = Date.now() + 2 * 60 * 1000; |
| localStorage.setItem('access_token_expiry', newAccessTokenExpiry.toString()); |
|
|
| |
| }, |
| error => { |
| console.log("Error refreshing token", error); |
|
|
| if ( |
| error.status === 401 && |
| (error.error.message === 'Refresh token has expired' || error.error.message === 'Invalid refresh token') |
| ) { |
| |
|
|
| |
| this.removeToken(); |
| this.loggedInSubject.next(false); |
| window.location.href = '/authentication'; |
| } else { |
| |
| console.error("Unexpected error:", error); |
| } |
| } |
| ); |
| } |
| } |
|
|
|
|
| } |
|
|