spring-projects / spring-security

Spring Security
http://spring.io/projects/spring-security
Apache License 2.0
8.82k stars 5.9k forks source link

OAuthClient fails on 2nd login attempt - Auth Server suceeds on both - Concurrent Sessions set to > 1 #15552

Closed dreamstar-enterprises closed 1 month ago

dreamstar-enterprises commented 3 months ago

Hi,

I need some help

I'm not sure why it is that when I try logging in via an OAuthClient to my Auth Server, it suceeds on the 1st try, and I get redirected back to the login page. But when I try logging in again via the OAuthClient, that fails, even though the AuthServer suceeds everytime? I have set max concurrent sessions to 5, but I do notice that on each login attempt the Session ID gets reset (SESSION: between Angular and the OAuthClient)

Here are my logs:

Login attempt 1:
Session ID: 1a7718ab-dcc2-4d83-a5fa-6a1e304d7864
Session Attributes before update: {}
Session Attributes after update: {post_login_failure_uri=http://localhost:7080/angular-ui/login-error, post_login_success_uri=http://localhost:7080/angular-ui/home}
RUNNING REDIRECT STRATEGY: 302 FOUND
ON SUCCESSFUL REDIRECT URI: http://localhost:7080/angular-ui/home
RUNNING REDIRECT STRATEGY: 302 FOUND
Removing matching request for http://localhost:7080/bff/login-options

Login attempt 2:
Session ID: a63df846-a55c-432c-a11e-6d095e259dcb
Session Attributes before update: {}
Session Attributes after update: {post_login_failure_uri=http://localhost:7080/angular-ui/login-error, post_login_success_uri=http://localhost:7080/angular-ui/home}
RUNNING REDIRECT STRATEGY: 302 FOUND
ON FAILURE REDIRECT URI: http://localhost:7080/angular-ui/login-error
URI with Query Parameters: http://localhost:7080/angular-ui/login-error?error=%5Bauthorization_request_not_found%5D%20
RUNNING REDIRECT STRATEGY: 302 FOUND
Removing matching request for http://localhost:7080/bff/login-options
Removing matching request for http://localhost:7080/bff/login-options

Login attempt 3:
Session ID: a63df846-a55c-432c-a11e-6d095e259dcb
Why does this extra attribute appear in attributes?
Session Attributes before update: {post_login_failure_uri=http://localhost:7080/angular-ui/login-error, post_login_success_uri=http://localhost:7080/angular-ui/home, org.springframework.security.oauth2.client.web.server.WebSessionOAuth2ServerAuthorizationRequestRepository.AUTHORIZATION_REQUEST=org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest@7c949b1f}
Session Attributes after update: {post_login_failure_uri=http://localhost:7080/angular-ui/login-error, post_login_success_uri=http://localhost:7080/angular-ui/home, org.springframework.security.oauth2.client.web.server.WebSessionOAuth2ServerAuthorizationRequestRepository.AUTHORIZATION_REQUEST=org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest@7c949b1f}
RUNNING REDIRECT STRATEGY: 302 FOUND
ON FAILURE REDIRECT URI: http://localhost:7080/angular-ui/login-error
URI with Query Parameters: http://localhost:7080/angular-ui/login-error?error=%5Bauthorization_request_not_found%5D%20
RUNNING REDIRECT STRATEGY: 302 FOUND
Removing matching request for http://localhost:7080/bff/login-options

GitHub repository https://github.com/dreamstar-enterprises/docs/tree/master/Spring%20BFF/bff

Relevant files

OAuth2 Success Handler: https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/auth/handlers/OAuth2ServerAuthenticationSuccessHandler.kt

OAuth2 Failure Handler: https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/auth/handlers/OAuth2ServerAuthenticationFailureHandler.kt

OAuth2 Request Resolver: https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/auth/resolvers/OAuthAuthorizationRequestResolver.kt

SessionRegistry: https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/auth/sessions/SessionRegistryConfig.kt

WebSessionStore: https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/auth/sessions/WebSessionStoreConfig.kt

ConcurrentSessionControl: https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/auth/handlers/ConcurrentSessionControlServerAuthenticationSuccessHandler.kt

Cookies: https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/auth/cookies/CookiesConfig.kt

Application Properties: https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/bff/props/AppPropertiesConfig.kt (see Session Properties, and Spring Session Properties) Note, even though in the properties I set the session cookie to be called "JSESSIONID" its actually called SESSIONID in Angular. The JSESSIONID is from the AuthServer. Also , I have no idea where the first SESSION ID is from: 67e9c54e-d6aa-4c00-bf05-fffc5f6e7263 (I don't see that being issued in any of my 3 login attemps)

Screenshot 2024-08-10 at 21 31 58

Can somebody help?

Describe the bug A clear and concise description of what the bug is.

To Reproduce Steps to reproduce the behavior.

Expected behavior A clear and concise description of what you expected to happen.

Sample

A link to a GitHub repository with a minimal, reproducible sample.

Reports that include a sample will take priority over reports that do not. At times, we may require a sample, so it is good to try and include a sample up front.

sjohnr commented 1 month ago

@dreamstar-enterprises, thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add a minimal sample that reproduces this issue if you feel this is a genuine bug.

Having said that, I am happy to help. However, the link you provided is to a repository that is not minimal. Please help us first by providing a minimal sample that reproduces the problem. This often helps narrow down the problem making it much easier for both you and others to determine and solve. I'm going to close this issue but please feel free to add a comment with a minimal sample and/or a stackoverflow link.

dreamstar-enterprises commented 1 month ago

Hi Steve,

Thanks for the kind reply!

Don't worry about it.

After much soul searching, I decided to use Auth0 for my Authorization Server, rather than try to build my own in-house Spring server. I had too much on, and was heavily focussed in getting my Spring Cloud Gateway BFF server to work. (which after 2.5 months, on and off, I completed here: https://github.com/dreamstar-enterprises/docs/tree/master/Spring%20BFF/BFF)

In my Spring BFF, Spring Security worked quite well! In my Resource Server it is working really well too, with the PreAuthorization annotations, and so forth.

I had a lot of troubles with Spring Session with Redis (getting the De-serialisation to work, and the Indexed Sessions not being allocated a TTL - - so they were left in Redis indefinitely, even though the normal session key was deleted. So I had to expand the Session Evictor significantly to accomodate for orphaned sessions (https://github.com/dreamstar-enterprises/docs/blob/master/Spring%20BFF/BFF/src/main/kotlin/com/frontiers/bff/auth/sessions/RedisSessionCleanUpConfig.kt) - it was painful.

With my Spring BFF, I just had to be organised with all the Spring security modules: https://github.com/dreamstar-enterprises/docs/tree/master/Spring%20BFF/BFF/src/main/kotlin/com/frontiers/bff/auth (but it worked as expected... apart from Spring Session)

With my Spring Resource server, I had to be careful when trying to get the Auth0 JWT URI Token,, from the Auth0 JWT endpoint, as I wasn't sure if that was being called on every resource server request to get the public key, (which would be a performance disadvange as token introspection, introspecting on every call)

So, decided to implement a caching solution, which I think is better.:

@Bean
fun jwtDecoder(): ReactiveJwtDecoder {
    val jwkSetUri = URI(serverProperties.auth0JwKeySetUri)

    // Define cache properties
    val timeToLive = TimeUnit.HOURS.toMillis(1)
    val cacheRefreshTimeout = TimeUnit.MINUTES.toMillis(50)

    // Create a JWK source with caching
    val jwkSource: JWKSource<SecurityContext> = JWKSourceBuilder.create<SecurityContext>(jwkSetUri.toURL())
        .cache(timeToLive, cacheRefreshTimeout)
        .refreshAheadCache(true)
        .build()

    // Create a JWS key selector from the JWK source
    val jwsKeySelector = JWSAlgorithmFamilyJWSKeySelector.fromJWKSource(jwkSource)

    // Set up JWT Processor
    val jwtProcessor = DefaultJWTProcessor<SecurityContext>()
    jwtProcessor.jwsKeySelector = jwsKeySelector

    // Create ReactiveJwtDecoder using the appropriate factory method
    return NimbusReactiveJwtDecoder { jwt ->
        Mono.fromCallable {
            jwtProcessor.process(jwt, null)
        }
    }
}

I also don't think Spring Webflux has an explicity Session Management configuraiton like Spring MVC so have just assumed it is turned off in my Spring Resource Server.

Right now I'm stuck on Spring Docs and a Spring Cloud Gateway, issue where the internally generated re-direct URI created by Swagger in the resource server,, is not adding the Gateway prefix, that gets stripped out by a reverse proxy, but Phil Webb, from your team, I believe, is trying to help with that.

It does feel like I've gone done the Mariana trench and back with Spring Security, the past 2 months, but I have learnt a lot... coming from a Typescript, Kotlin, and Angular background.

But yes, as for the above issue, no need to worry about it. I've moved to Auth0. When I have my backend resource server complete, and front end, I plan to revisit the Authorization server, and see if I can create an in-house one using Spring.

Thanks for replying again though, and offering to help!