fix jwt handler to return proper error codes
This commit is contained in:
@@ -64,6 +64,12 @@ public class SecurityConfig {
|
||||
.requestMatchers("/swagger-ui/**", "/api-docs/**").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/api/sites/**").authenticated()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.exceptionHandling(ex -> ex
|
||||
.authenticationEntryPoint((request, response, authException) ->
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"))
|
||||
.accessDeniedHandler((request, response, accessDeniedException) ->
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden"))
|
||||
);
|
||||
|
||||
if (isOAuth2Configured()) {
|
||||
@@ -128,6 +134,9 @@ public class SecurityConfig {
|
||||
} catch (Exception e) {
|
||||
org.springframework.security.core.context.SecurityContextHolder
|
||||
.clearContext();
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
|
||||
"Invalid or expired token");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import {
|
||||
HttpInterceptor,
|
||||
HttpRequest,
|
||||
HttpHandler,
|
||||
HttpEvent,
|
||||
HttpErrorResponse,
|
||||
} from '@angular/common/http';
|
||||
import { BehaviorSubject, Observable, catchError, filter, switchMap, take, throwError } from 'rxjs';
|
||||
import { AuthService } from '../services/auth.service';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class JwtInterceptor implements HttpInterceptor {
|
||||
constructor(private authService: AuthService) {}
|
||||
private authService = inject(AuthService);
|
||||
private router = inject(Router);
|
||||
private isRefreshing = false;
|
||||
private refreshTokenSubject = new BehaviorSubject<string | null>(null);
|
||||
|
||||
intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
||||
const token = this.authService.getAccessToken();
|
||||
@@ -14,6 +24,65 @@ export class JwtInterceptor implements HttpInterceptor {
|
||||
setHeaders: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
}
|
||||
return next.handle(req);
|
||||
|
||||
return next.handle(req).pipe(
|
||||
catchError((error) => {
|
||||
if (
|
||||
error instanceof HttpErrorResponse &&
|
||||
error.status === 401 &&
|
||||
!req.url.includes('/api/auth/refresh')
|
||||
) {
|
||||
return this.handle401Error(req, next);
|
||||
}
|
||||
return throwError(() => error);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private handle401Error(
|
||||
req: HttpRequest<unknown>,
|
||||
next: HttpHandler,
|
||||
): Observable<HttpEvent<unknown>> {
|
||||
if (!this.isRefreshing) {
|
||||
this.isRefreshing = true;
|
||||
this.refreshTokenSubject.next(null);
|
||||
|
||||
const refreshToken = this.authService.getRefreshToken();
|
||||
if (!refreshToken) {
|
||||
this.authService.clearSessionForLogout();
|
||||
this.router.navigate(['/login']);
|
||||
return throwError(() => new Error('No refresh token available'));
|
||||
}
|
||||
|
||||
return this.authService.refreshToken(refreshToken).pipe(
|
||||
switchMap((res) => {
|
||||
this.isRefreshing = false;
|
||||
this.refreshTokenSubject.next(res.accessToken);
|
||||
return next.handle(
|
||||
req.clone({
|
||||
setHeaders: { Authorization: `Bearer ${res.accessToken}` },
|
||||
}),
|
||||
);
|
||||
}),
|
||||
catchError((err) => {
|
||||
this.isRefreshing = false;
|
||||
this.authService.clearSessionForLogout();
|
||||
this.router.navigate(['/login']);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
return this.refreshTokenSubject.pipe(
|
||||
filter((token): token is string => token !== null),
|
||||
take(1),
|
||||
switchMap((token) =>
|
||||
next.handle(
|
||||
req.clone({
|
||||
setHeaders: { Authorization: `Bearer ${token}` },
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user