You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成OneLogin SSO:JWT过期后的认证流程疑问

Great question! Let's break this down step by step based on how Spring Security and OneLogin SSO typically work together:

1. Handling JWT Expiration: Clear Context & Redirect to OneLogin

Yes, you absolutely should clear the Spring Security context and redirect users back to OneLogin for re-authentication when their JWT token expires. Here's why:

  • JWT is stateless by design—once it's expired, there's no way to validate the user's identity locally anymore. The Security Context holds the user's authenticated state, so keeping an expired token's context around would lead to invalid auth checks.
  • Redirecting to OneLogin leverages the SSO flow: if the user still has an active session with OneLogin, they'll be redirected back to your app automatically without re-entering credentials; if not, they'll go through OneLogin's login flow first.

To implement this, you can add a custom filter that checks for JWT expiration on each request:

@Component
public class JwtExpirationCheckFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        
        if (auth != null && auth.getCredentials() instanceof String jwtToken) {
            if (jwtTokenProvider.isTokenExpired(jwtToken)) {
                // Clear the invalid auth context
                SecurityContextHolder.clearContext();
                
                // Redirect to OneLogin's authorization endpoint (replace with your config)
                String redirectUrl = "https://your-onelogin-domain.com/oidc/auth" +
                    "?client_id=YOUR_CLIENT_ID" +
                    "&redirect_uri=YOUR_APP_REDIRECT_URI" +
                    "&response_type=code" +
                    "&scope=openid email profile";
                response.sendRedirect(redirectUrl);
                return;
            }
        }
        
        filterChain.doFilter(request, response);
    }
}

2. Syncing Security Context with OneLogin's Auth State

Spring Security's context is local to your app, so you need to actively sync it with OneLogin's authoritative session state. Here are the most practical approaches:

Option A: Use Refresh Tokens for Silent Token Renewal

If you requested the offline_access scope during the OneLogin OIDC flow, you'll get a refresh token alongside the JWT. When the JWT expires, you can use this refresh token to fetch a new JWT from OneLogin without redirecting the user:

public Optional<String> refreshJwtToken(String refreshToken) {
    // Call OneLogin's token endpoint to get a new access token
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    
    MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
    params.add("grant_type", "refresh_token");
    params.add("refresh_token", refreshToken);
    params.add("client_id", "YOUR_CLIENT_ID");
    params.add("client_secret", "YOUR_CLIENT_SECRET");
    
    HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
    ResponseEntity<OneLoginTokenResponse> response = restTemplate.exchange(
        "https://your-onelogin-domain.com/oidc/token",
        HttpMethod.POST,
        request,
        OneLoginTokenResponse.class
    );
    
    if (response.getStatusCode().is2xxSuccessful()) {
        String newJwt = response.getBody().getAccessToken();
        // Update the Security Context with the new token
        Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication();
        UsernamePasswordAuthenticationToken newAuth = new UsernamePasswordAuthenticationToken(
            currentAuth.getPrincipal(),
            newJwt,
            currentAuth.getAuthorities()
        );
        SecurityContextHolder.getContext().setAuthentication(newAuth);
        return Optional.of(newJwt);
    }
    return Optional.empty();
}

If the refresh token is also expired, fall back to clearing the context and redirecting to OneLogin.

Option B: Periodically Validate OneLogin Sessions

Set up a scheduled task to check if users' OneLogin sessions are still active. Use OneLogin's /api/2/sessions/me endpoint to validate the user's session:

@Component
public class OneLoginSessionValidator {

    @Autowired
    private RestTemplate restTemplate;

    @Scheduled(fixedRate = 300000) // Check every 5 minutes
    public void validateActiveSessions() {
        // Get all authenticated users (adjust based on your session management)
        Collection<Authentication> activeAuths = getActiveAuthenticatedUsers();
        
        for (Authentication auth : activeAuths) {
            String oneLoginAccessToken = (String) auth.getCredentials();
            HttpHeaders headers = new HttpHeaders();
            headers.setBearerAuth(oneLoginAccessToken);
            
            try {
                ResponseEntity<Void> response = restTemplate.exchange(
                    "https://your-onelogin-domain.com/api/2/sessions/me",
                    HttpMethod.GET,
                    new HttpEntity<>(headers),
                    Void.class
                );
                
                if (!response.getStatusCode().is2xxSuccessful()) {
                    SecurityContextHolder.clearContext();
                }
            } catch (HttpClientErrorException e) {
                // Session is invalid/expired
                SecurityContextHolder.clearContext();
            }
        }
    }
    
    // Helper method to fetch active authenticated users (use SessionRegistry if applicable)
    private Collection<Authentication> getActiveAuthenticatedUsers() {
        // Implement based on your app's session storage
        return new ArrayList<>();
    }
}

Option C: Handle OneLogin Global Logout

Configure OneLogin to send a logout callback to your app (via the "Logout URL" setting in your OneLogin app config). When this callback is triggered, clear the user's Security Context and invalidate their local session:

@RestController
@RequestMapping("/auth")
public class LogoutController {

    @PostMapping("/onelogin-logout")
    public void handleOneLoginLogout(HttpServletRequest request, HttpServletResponse response) throws IOException {
        SecurityContextHolder.clearContext();
        request.getSession().invalidate();
        response.sendRedirect("/"); // Redirect to your app's home page
    }
}

Key Takeaways

  • Always clear the Security Context when JWT/OneLogin sessions are invalid to avoid stale auth state.
  • Use refresh tokens for a seamless user experience when JWTs expire (when possible).
  • Sync your app's state with OneLogin's via periodic checks or global logout callbacks to maintain consistent auth status.

内容的提问来源于stack exchange,提问作者user12980137

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 18:27:33