removing /logout from filters
This commit is contained in:
committed by
DarioGii
parent
817f43613f
commit
ec72cfd7e2
@@ -158,7 +158,6 @@ public class RequestUriUtils {
|
||||
|
||||
// Public auth endpoints that don't require authentication
|
||||
return trimmedUri.startsWith("/login")
|
||||
|| trimmedUri.startsWith("/logout")
|
||||
|| trimmedUri.startsWith("/auth/")
|
||||
|| trimmedUri.startsWith("/oauth2")
|
||||
|| trimmedUri.startsWith("/saml2")
|
||||
|
||||
+63
-5
@@ -13,6 +13,7 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
||||
@@ -244,7 +245,6 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
|
||||
// Redirect based on OAuth2 provider
|
||||
switch (registrationId.toLowerCase(Locale.ROOT)) {
|
||||
case "keycloak" -> handleOidcLogout(request, response, oAuthToken, oauth, redirectUrl);
|
||||
case "github", "google" -> {
|
||||
// These providers don't support OIDC logout
|
||||
log.info(
|
||||
@@ -253,10 +253,69 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
redirectUrl);
|
||||
response.sendRedirect(redirectUrl);
|
||||
}
|
||||
default -> {
|
||||
// Try generic OIDC logout for any other provider
|
||||
handleOidcLogout(request, response, oAuthToken, oauth, redirectUrl);
|
||||
default -> handleOidcLogout(response, oAuthToken, oauth, redirectUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect for JWT-based OAuth2 authentication logout
|
||||
private void handleJwtOAuth2Logout(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
OAUTH2 oauth = securityProperties.getOauth2();
|
||||
String path = checkForErrors(request);
|
||||
String redirectUrl = UrlUtils.getOrigin(request) + "/login?" + path;
|
||||
|
||||
// For JWT-based auth, we don't have OAuth2AuthenticationToken
|
||||
// Attempt generic OIDC logout
|
||||
String issuer = null;
|
||||
String clientId = null;
|
||||
|
||||
if (oauth.getClient() != null && oauth.getClient().getKeycloak() != null) {
|
||||
KeycloakProvider keycloak = oauth.getClient().getKeycloak();
|
||||
if (keycloak.getIssuer() != null && !keycloak.getIssuer().isBlank()) {
|
||||
issuer = keycloak.getIssuer();
|
||||
clientId = keycloak.getClientId();
|
||||
} else if (oauth.getIssuer() != null && !oauth.getIssuer().isBlank()) {
|
||||
issuer = oauth.getIssuer();
|
||||
clientId = oauth.getClientId();
|
||||
}
|
||||
} else if (oauth.getIssuer() != null && !oauth.getIssuer().isBlank()) {
|
||||
issuer = oauth.getIssuer();
|
||||
clientId = oauth.getClientId();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// If we have an endpoint, construct the logout URL
|
||||
if (endSessionEndpoint != null) {
|
||||
StringBuilder logoutUrlBuilder = new StringBuilder(endSessionEndpoint);
|
||||
logoutUrlBuilder.append(endSessionEndpoint.contains("?") ? "&" : "?");
|
||||
|
||||
// Without OAuth2AuthenticationToken, we don't have id_token_hint
|
||||
// Just use client_id and post_logout_redirect_uri
|
||||
if (clientId != null && !clientId.isBlank()) {
|
||||
logoutUrlBuilder.append("client_id=").append(clientId);
|
||||
logoutUrlBuilder.append("&");
|
||||
}
|
||||
logoutUrlBuilder
|
||||
.append("post_logout_redirect_uri=")
|
||||
.append(response.encodeRedirectURL(redirectUrl));
|
||||
|
||||
String logoutUrl = logoutUrlBuilder.toString();
|
||||
log.info("JWT-based OAuth2 logout URL: {}", logoutUrl);
|
||||
response.sendRedirect(logoutUrl);
|
||||
} else {
|
||||
// No OIDC logout endpoint available - fallback to local logout
|
||||
log.info(
|
||||
"No OIDC logout endpoint available for issuer: {}. Using local logout: {}",
|
||||
issuer,
|
||||
redirectUrl);
|
||||
response.sendRedirect(redirectUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +324,6 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||
* Discovered endpoint 3. Keycloak fallback (if isKeycloak=true) 4. Local logout
|
||||
*/
|
||||
private void handleOidcLogout(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
OAuth2AuthenticationToken oAuthToken,
|
||||
OAUTH2 oauth,
|
||||
|
||||
+28
-8
@@ -6,17 +6,20 @@ import static stirling.software.proprietary.security.model.AuthenticationType.OA
|
||||
import static stirling.software.proprietary.security.model.AuthenticationType.SAML2;
|
||||
import static stirling.software.proprietary.security.model.AuthenticationType.WEB;
|
||||
|
||||
import io.jsonwebtoken.Jwts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
@@ -26,7 +29,6 @@ import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
@@ -40,7 +42,6 @@ import stirling.software.proprietary.security.service.JwtServiceInterface;
|
||||
import stirling.software.proprietary.security.service.UserService;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private final JwtServiceInterface jwtService;
|
||||
@@ -49,6 +50,19 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
private final AuthenticationEntryPoint authenticationEntryPoint;
|
||||
private final ApplicationProperties.Security securityProperties;
|
||||
|
||||
public JwtAuthenticationFilter(
|
||||
JwtServiceInterface jwtService,
|
||||
UserService userService,
|
||||
CustomUserDetailsService userDetailsService,
|
||||
AuthenticationEntryPoint authenticationEntryPoint,
|
||||
ApplicationProperties.Security securityProperties) {
|
||||
this.jwtService = jwtService;
|
||||
this.userService = userService;
|
||||
this.userDetailsService = userDetailsService;
|
||||
this.authenticationEntryPoint = authenticationEntryPoint;
|
||||
this.securityProperties = securityProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(
|
||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
@@ -111,7 +125,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
String tokenUsername = claims.get("sub").toString();
|
||||
|
||||
try {
|
||||
authenticate(request, claims);
|
||||
authenticate(request, jwtToken, claims);
|
||||
} catch (SQLException | UnsupportedProviderException e) {
|
||||
log.error("Error processing user authentication for user: {}", tokenUsername, e);
|
||||
handleAuthenticationFailure(
|
||||
@@ -165,7 +179,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void authenticate(HttpServletRequest request, Map<String, Object> claims)
|
||||
private void authenticate(
|
||||
HttpServletRequest request, String jwtToken, Map<String, Object> claims)
|
||||
throws SQLException, UnsupportedProviderException {
|
||||
String username = claims.get("sub").toString();
|
||||
|
||||
@@ -174,9 +189,14 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||
|
||||
if (userDetails != null) {
|
||||
UsernamePasswordAuthenticationToken authToken =
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
Jwt jwt =
|
||||
Jwt.withTokenValue(jwtToken)
|
||||
.headers(headers -> headers.put("alg", Jwts.SIG.RS256.getId()))
|
||||
.claims(claimsMap -> claimsMap.putAll(claims))
|
||||
.build();
|
||||
|
||||
JwtAuthenticationToken authToken =
|
||||
new JwtAuthenticationToken(jwt, userDetails.getAuthorities());
|
||||
|
||||
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
log.debug("Setting authentication for user: {}", username);
|
||||
|
||||
@@ -102,6 +102,12 @@ export default defineConfig(({ mode }) => {
|
||||
secure: false,
|
||||
xfwd: true,
|
||||
},
|
||||
'/logout': {
|
||||
target: 'http://localhost:8080',
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
xfwd: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
base: process.env.RUN_SUBPATH ? `/${process.env.RUN_SUBPATH}` : './',
|
||||
|
||||
Reference in New Issue
Block a user