spring-projects / spring-security

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

WebSessionServerOAuth2AuthorizedClientRepository throws NPE when session is null #14975

Closed akovalyev closed 2 weeks ago

akovalyev commented 3 weeks ago

Describe the bug This line session.getAttributes()throws NPE, if we have WebSession bean configuration like this to disable WebSession:

@Bean
    fun webSessionManager(): WebSessionManager {
        // Emulate SessionCreationPolicy.STATELESS
        return WebSessionManager { exchange: ServerWebExchange? -> Mono.empty() }
    }

Expected behavior I thing we may do null-safety when we are trying to call getAuthorizedClients in this place with nullable session.

Configuration Spring Cloud Gateway.

@Bean
    fun authorizedClientManager(
        clientRegistrationRepository: ReactiveClientRegistrationRepository,
        authorizedClientRepository: ServerOAuth2AuthorizedClientRepository
    ): ReactiveOAuth2AuthorizedClientManager {
        val authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
            .builder()
            .clientCredentials()
            .build()
        val authorizedClientManager = DefaultReactiveOAuth2AuthorizedClientManager(
            clientRegistrationRepository, authorizedClientRepository
        )
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
        return authorizedClientManager
    }

    @Bean
    fun springSecurityFilterChainNonProd(
        httpSecurity: ServerHttpSecurity,
        someIntrospector: SomeIntrospector,
    ): SecurityWebFilterChain? {
        return httpSecurity
            .cors(Customizer.withDefaults())
            .authorizeExchange { auth ->
                auth.anyExchange().authenticated()
            }
            .oauth2ResourceServer { oauth2 ->
                oauth2.opaqueToken {
                    it.introspector(someIntrospector)
                }
            }
            .csrf { csrf -> csrf.disable() }
            .logout { logout -> logout.disable() }
            .build()
    }
sjohnr commented 2 weeks ago

@akovalyev, thanks for reaching out!

I want to point out that the javadoc for WebSessionManager states:

Return the {@link WebSession} for the given exchange. Always guaranteed
to return an instance either matching to the session id requested by the
client, or a new session either because the client did not specify one
or because the underlying session expired.

Your configuration does not honor the contract and therefore the issue is in your application. I'm happy to help you find a way to support your use case, but we prefer to use GitHub issues only for bugs and enhancements, so it would be best to ask a question on Stack Overflow and update this issue with a link to the question (so that other people can find it).

I'm going to close this issue for now with the above explanation.