Обновление JWT в Angular 17
Мой бэкенд - это Django restframework. Когда я предоставляю свои учетные данные, он выдает мне токены, которые состоят из refresh и access tokens. В моем бэкенде время действия access_tokens составляет 2 минуты (только для тестирования, но будет увеличиваться до 15 минут), а время действия refresh_tokens составляет 15 дней. Когда срок действия access_token истекает, я отправляю refresh_token для получения нового access_token (только предоставляет access_token).
На front_end (Angular 17) я реализовал получение новых access_tokens, вместо получения новых токенов я получаю logout через 2 минуты.
Я новичок в Angular. Я пытался отладить, но не смог найти решение. Я размещаю свой класс сервиса и перехватчик.
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const auth_service = inject(AuthService);
const accessToken = auth_service.getAccessToken();
let authReq = req;
if (accessToken)
{
authReq = req.clone({
setHeaders: {
Authorization: `Bearer ${accessToken}`
}
});
}
return next(authReq).pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 401 && error.error.code === 'token_not_valid') {
console.log('Token expired, attempting to refresh...');
// Token expired, attempt to refresh
return auth_service.refreshTokenRequest().pipe(
switchMap(() => {
const newAccessToken = auth_service.getAccessToken();
if (newAccessToken) {
console.log('New access token received');
authReq = req.clone({
setHeaders: {
Authorization: `Bearer ${newAccessToken}`
}
});
}
return next(authReq);
}),
catchError((err) => {
console.error('Token refresh failed:', err);
auth_service.logout();
return throwError(() => err);
})
);
}
return throwError(() => error);
})
);
};
и мой класс обслуживания -
export class AuthService {
constructor() { }
http = inject(HttpClient);
router = inject(Router);
private apiUrl = 'http://localhost:8000/api/v1/';
private jwtHelper = new JwtHelperService();
private accessToken: string | null = null;
private refreshToken: string | null = null;
private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
storeJWTToken(token: any): void
{
localStorage.setItem('access_token', token.access);
localStorage.setItem('refresh_token', token.refresh);
if (token.access)
this.accessToken = token.access;
if (token.refresh)
this.refreshToken = token.refresh;
this.isAuthenticatedSubject.next(true);
}
login(user: User) : Observable<any>
{
return this.http.post<any>(this.apiUrl + 'login/', user)
.pipe(tap(response => {
console.log('tokens:', response.access);
this.storeJWTToken(response);
}))
;
}
logout(): void {
try
{
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
this.isAuthenticatedSubject.next(false);
this.router.navigate(['/login']);
}
catch (error)
{
console.error('Error while logging out:', error);
}
}
isLoggedIn()
{
const Token = this.getAccessToken();
return Token ? !this.jwtHelper.isTokenExpired(Token) : false;
}
isAuthenticated() : boolean
{
const token = this.accessToken || localStorage.getItem('access_token');
return token ? !this.jwtHelper.isTokenExpired(token) : false;
}
getAccessToken() : string | null
{
return this.accessToken || localStorage.getItem('access_token');
}
refreshTokenRequest() : Observable<any>
{
const refreshToken = this.refreshToken || localStorage.getItem('refresh_token');
if (!refreshToken)
return throwError(() => new Error('No refresh token found'));
return this.http.post<any>(this.apiUrl + 'login/refresh/', {refresh: refreshToken})
.pipe(tap(response => {
this.accessToken = response.access;
if (this.accessToken)
localStorage.setItem('access_token', this.accessToken);
})
);
}
}
Я пробовал это, но так и не смог найти проблему.
и мой файл app.config.ts имеет следующий вид
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideAnimationsAsync(),
provideHttpClient(
withXsrfConfiguration({
cookieName: 'csrftoken',
headerName: 'X-CSRFToken',
}),
withInterceptors([authInterceptor]),
),
importProvidersFrom([
JwtModule.forRoot({
config: {
tokenGetter: () => localStorage.getItem('access_token')
}
})
]),
]
};