feat: auto refresh of tokens in background

This commit is contained in:
2026-02-19 15:49:25 -08:00
parent b6ac3cbb99
commit ebdb85c3e9
@@ -23,6 +23,7 @@ export class AuthService {
private currentUser = signal<User | null>(null);
public readonly user = this.currentUser.asReadonly();
private refreshing = false;
private refreshInterval?: ReturnType<typeof setInterval>;
login(): void {
// Redirect to API login endpoint
@@ -33,6 +34,7 @@ export class AuthService {
return this.api.get<AuthResponse>('/auth/me').pipe(
tap(response => {
this.currentUser.set(response.user);
this.startRefreshTimer();
}),
catchError(error => {
if (error.status === 401) {
@@ -40,9 +42,11 @@ export class AuthService {
switchMap(() => this.api.get<AuthResponse>('/auth/me')),
tap(response => {
this.currentUser.set(response.user);
this.startRefreshTimer();
}),
catchError(() => {
this.currentUser.set(null);
this.stopRefreshTimer();
return throwError(() => error);
})
);
@@ -66,20 +70,45 @@ export class AuthService {
tap(response => {
this.currentUser.set(response.user);
this.refreshing = false;
this.startRefreshTimer();
}),
catchError(error => {
this.refreshing = false;
this.currentUser.set(null);
this.stopRefreshTimer();
return throwError(() => error);
})
);
}
private startRefreshTimer(): void {
this.stopRefreshTimer();
// Refresh token every 13 minutes (before 15-minute expiry)
const refreshIntervalMs = 13 * 60 * 1000;
this.refreshInterval = setInterval(() => {
this.refreshToken().subscribe({
error: (err) => {
console.error('Background token refresh failed:', err);
this.stopRefreshTimer();
}
});
}, refreshIntervalMs);
}
private stopRefreshTimer(): void {
if (this.refreshInterval) {
clearInterval(this.refreshInterval);
this.refreshInterval = undefined;
}
}
logout(): Observable<{ message: string }> {
return this.api.post<{ message: string }>('/auth/logout', {}).pipe(
tap(() => {
this.currentUser.set(null);
this.api.clearCsrfToken();
this.stopRefreshTimer();
this.router.navigate(['/']);
})
);
@@ -87,6 +116,7 @@ export class AuthService {
clearUser(): void {
this.currentUser.set(null);
this.stopRefreshTimer();
}
isAuthenticated(): boolean {