mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-12-18 20:04:17 +01:00
moar cleanup
This commit is contained in:
parent
d296e0bd09
commit
d4ac6148d8
@ -65,15 +65,6 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
|
||||
if (!response.isCommitted()) {
|
||||
if (authentication != null) {
|
||||
// Check for JWT-based authentication and extract authType claim
|
||||
String authType;
|
||||
if (authentication instanceof JwtAuthenticationToken jwtAuth) {
|
||||
authType =
|
||||
(String) jwtAuth.getToken().getClaims().getOrDefault("authType", null);
|
||||
|
||||
log.debug("JWT-based logout detected with authType: {}", authType);
|
||||
}
|
||||
|
||||
if (authentication instanceof OAuth2AuthenticationToken oAuthToken) {
|
||||
log.info("OAuth2 logout via JWT - attempting OIDC logout");
|
||||
getAuthRedirect(request, response, oAuthToken);
|
||||
@ -81,7 +72,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
getAuthRedirect(request, response, samlAuthentication);
|
||||
} else if (authentication
|
||||
instanceof JwtAuthenticationToken jwtAuthenticationToken) {
|
||||
getAuthRedirect(request, response, jwtAuthenticationToken);
|
||||
getAuthRedirect(request, response);
|
||||
} else if (authentication instanceof UsernamePasswordAuthenticationToken) {
|
||||
// Handle Username/Password logout
|
||||
getRedirectStrategy().sendRedirect(request, response, LOGOUT_PATH);
|
||||
@ -186,10 +177,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
}
|
||||
|
||||
// Redirect for JWT-based OAuth2 authentication logout
|
||||
private void getAuthRedirect(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
JwtAuthenticationToken jwtAuthenticationToken)
|
||||
private void getAuthRedirect(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
OAUTH2 oauth = securityProperties.getOauth2();
|
||||
String path = checkForErrors(request);
|
||||
@ -213,18 +201,8 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
clientId = oauth.getClientId();
|
||||
}
|
||||
|
||||
// Fallback: extract issuer from JWT token if not found in configuration
|
||||
if (issuer == null) {
|
||||
var jwtIssuer = jwtAuthenticationToken.getToken().getIssuer();
|
||||
if (jwtIssuer != null) {
|
||||
issuer = jwtIssuer.toString();
|
||||
log.debug("Using issuer from JWT token: {}", issuer);
|
||||
}
|
||||
}
|
||||
|
||||
String endSessionEndpoint = getEndSessionEndpoint(oauth, issuer);
|
||||
|
||||
// If no endpoint found, try Keycloak fallback
|
||||
if (endSessionEndpoint == null && issuer != null) {
|
||||
endSessionEndpoint = issuer + "/protocol/openid-connect/logout";
|
||||
log.debug("Using Keycloak fallback logout path: {}", endSessionEndpoint);
|
||||
@ -242,7 +220,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
logoutUrlBuilder.append("post_logout_redirect_uri=").append(encodedRedirectUri);
|
||||
|
||||
String logoutUrl = logoutUrlBuilder.toString();
|
||||
log.info("JWT-based OAuth2 logout URL: {}", logoutUrl);
|
||||
log.debug("JWT-based OAuth2 logout URL: {}", logoutUrl);
|
||||
|
||||
// Return JSON for API requests, redirect for browser requests
|
||||
if (isApi) {
|
||||
|
||||
@ -1009,8 +1009,8 @@ class CustomLogoutSuccessHandlerTest {
|
||||
when(request.getHeader("X-Requested-With")).thenReturn(null);
|
||||
when(response.getWriter()).thenReturn(printWriter);
|
||||
|
||||
when(jwtAuth.getToken()).thenReturn(jwt);
|
||||
when(jwt.getClaims()).thenReturn(Map.of("authType", "OAUTH2"));
|
||||
lenient().when(jwtAuth.getToken()).thenReturn(jwt);
|
||||
lenient().when(jwt.getClaims()).thenReturn(Map.of("authType", "OAUTH2"));
|
||||
|
||||
when(securityProperties.getOauth2()).thenReturn(oauth);
|
||||
when(oauth.getClient()).thenReturn(client);
|
||||
@ -1067,8 +1067,8 @@ class CustomLogoutSuccessHandlerTest {
|
||||
when(request.getHeader("X-Requested-With")).thenReturn("XMLHttpRequest"); // XHR request
|
||||
when(response.getWriter()).thenReturn(printWriter);
|
||||
|
||||
when(jwtAuth.getToken()).thenReturn(jwt);
|
||||
when(jwt.getClaims()).thenReturn(Map.of("authType", "OAUTH2"));
|
||||
lenient().when(jwtAuth.getToken()).thenReturn(jwt);
|
||||
lenient().when(jwt.getClaims()).thenReturn(Map.of("authType", "OAUTH2"));
|
||||
|
||||
when(securityProperties.getOauth2()).thenReturn(oauth);
|
||||
when(oauth.getClient()).thenReturn(client);
|
||||
@ -1115,8 +1115,8 @@ class CustomLogoutSuccessHandlerTest {
|
||||
when(request.getHeader("Accept")).thenReturn("text/html"); // Browser request
|
||||
when(request.getHeader("X-Requested-With")).thenReturn(null);
|
||||
|
||||
when(jwtAuth.getToken()).thenReturn(jwt);
|
||||
when(jwt.getClaims()).thenReturn(Map.of("authType", "OAUTH2"));
|
||||
lenient().when(jwtAuth.getToken()).thenReturn(jwt);
|
||||
lenient().when(jwt.getClaims()).thenReturn(Map.of("authType", "OAUTH2"));
|
||||
|
||||
when(securityProperties.getOauth2()).thenReturn(oauth);
|
||||
when(oauth.getClient()).thenReturn(client);
|
||||
@ -1164,8 +1164,8 @@ class CustomLogoutSuccessHandlerTest {
|
||||
when(request.getHeader("X-Requested-With")).thenReturn(null);
|
||||
when(response.getWriter()).thenReturn(printWriter);
|
||||
|
||||
when(jwtAuth.getToken()).thenReturn(jwt);
|
||||
when(jwt.getClaims()).thenReturn(Map.of("authType", "OAUTH2"));
|
||||
lenient().when(jwtAuth.getToken()).thenReturn(jwt);
|
||||
lenient().when(jwt.getClaims()).thenReturn(Map.of("authType", "OAUTH2"));
|
||||
|
||||
when(securityProperties.getOauth2()).thenReturn(oauth);
|
||||
when(oauth.getClient()).thenReturn(client);
|
||||
|
||||
@ -284,15 +284,9 @@ class SpringAuthClient {
|
||||
*/
|
||||
async signOut(): Promise<{ error: AuthError | null }> {
|
||||
try {
|
||||
// Extract token before removing it (needed for OAuth/SAML logout)
|
||||
// Extract token before making request (needed for OAuth/SAML logout)
|
||||
const token = localStorage.getItem('stirling_jwt');
|
||||
|
||||
// Clean up local storage before logout
|
||||
localStorage.removeItem('stirling_jwt');
|
||||
|
||||
// Call Spring Security's logout endpoint
|
||||
// This will handle OAuth2/SAML logout and return JSON with logout URL for OIDC providers
|
||||
// Include the token so Spring knows which authentication type to logout from
|
||||
const response = await apiClient.post('/logout', null, {
|
||||
headers: {
|
||||
...(token ? { 'Authorization': `Bearer ${token}` } : {}),
|
||||
@ -301,19 +295,24 @@ class SpringAuthClient {
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
// Notify listeners
|
||||
this.notifyListeners('SIGNED_OUT', null);
|
||||
// Clean up local storage after successful logout request
|
||||
localStorage.removeItem('stirling_jwt');
|
||||
|
||||
// If we got a logout URL (for OIDC/OAuth2 providers), navigate to it
|
||||
// If we got a logout URL (for OIDC/OAuth2 providers), redirect immediately
|
||||
// Don't notify listeners to avoid React re-render before redirect
|
||||
if (response.data?.logoutUrl) {
|
||||
window.location.href = response.data.logoutUrl;
|
||||
return { error: null };
|
||||
}
|
||||
|
||||
this.notifyListeners('SIGNED_OUT', null);
|
||||
window.location.href = '/login?logout=true';
|
||||
return { error: null };
|
||||
} catch (error: unknown) {
|
||||
console.error('[SpringAuth] signOut error:', error);
|
||||
// Still notify listeners even if backend call fails
|
||||
localStorage.removeItem('stirling_jwt');
|
||||
this.notifyListeners('SIGNED_OUT', null);
|
||||
window.location.href = '/login?logout=true';
|
||||
return {
|
||||
error: { message: getErrorMessage(error, 'Logout failed') },
|
||||
};
|
||||
|
||||
@ -37,17 +37,9 @@ const AccountSection: React.FC = () => {
|
||||
|
||||
const userIdentifier = useMemo(() => user?.email || user?.username || '', [user?.email, user?.username]);
|
||||
|
||||
const redirectToLogin = useCallback(() => {
|
||||
window.location.assign('/login');
|
||||
}, []);
|
||||
|
||||
const handleLogout = useCallback(async () => {
|
||||
try {
|
||||
await signOut();
|
||||
} finally {
|
||||
redirectToLogin();
|
||||
}
|
||||
}, [redirectToLogin, signOut]);
|
||||
await signOut();
|
||||
}, [signOut]);
|
||||
|
||||
const handlePasswordSubmit = async (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user