7

Spring usually eagerly loading the spring security configuration while starting the application. I'm using OAuth with Spring Security

I'm maintaining a configuration table for storing the SSO related values (like jwk-url, client_id, client_secret). This values will be populated by an admin user via CRUD in the same spring boot application.

Then only the jwk-url is available to be configure in the Spring security configuration (refer below code - jwkSetUri(...)). This would not available at the application startup.

So I wanted to initialise the spring security configuration after the value is loaded into the table, like a lazy loading (@Lazy) at runtime. I know how to do Lazy loading of a regular class/service.

  1. But still I'm not sure how to invoke the configure(HttpSecurity http) method at runtime and how to p ass the HttpSecurity parameter. When I just try invoke new ResourceServerConfiguration() like a lazy loading at runtime, I don't see the configure() method is called. (Or) this class needs to be maintained as bean and lazy load whenever needed. But still not sure about how to call configure() in code.

  2. Another thing is how to refresh/reload the spring security configuration at runtime, if the JWK url is changed by admin. Then only the spring security configuration can take effect of the changes.

@Configuration
@EnableWebSecurity
public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.cors()
                .and()
                .csrf().disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .oauth2ResourceServer()
                .authenticationEntryPoint(oAuth2AuthenticationEntryPoint)
                .accessDeniedHandler(oAuth2AccessDeniedHandler)
                .jwt()
                 // Some Auth server URL which would be fetch from table
                .jwkSetUri(ssoConfigService.getActiveSSOCertificateURL()); 
                 // Eg. http://localhost:8090/auth/realms/demo-app/protocol/openid-connect/certs
    }
}

I have already referred these links. But it doesn't help for my purpose. Any help would be appreciated.

How do I lazy load Spring Security?

How to reload the Configure method of WebSecurityConfigurerAdapter when the application is up and running

Modify Spring Security Config at Runtime

Configure Spring HTTP Security at Runtime

ARods
  • 441
  • 2
  • 5
  • 13

1 Answers1

0

Please, check this link Customizing CORS Filtering at Runtime that include a similar use case related to your but for him, he needed to change allowed origins dynamically. They decide to create a new filter and simple extends OncePerRequestFilter.

Take in account to check the OAuth2ResourceServerProperties for your use case.

UPDATING: Try with this code for this scenario:

Another thing is how to refresh/reload the spring security configuration at runtime, if the JWK url is changed by admin. Then only the spring security configuration can take effect of the changes.

 @Override
    public void configure(HttpSecurity http) throws Exception {
        http.cors()
                .and()
                .csrf().disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .anyRequest().authenticated()

                // TODO: test with and without this and check if work for you
                .and()
                .oauth2ResourceServer()
                .authenticationEntryPoint(oAuth2AuthenticationEntryPoint)
                .accessDeniedHandler(oAuth2AccessDeniedHandler)
                .jwt()
                // Some Auth server URL which would be fetch from table
                .jwkSetUri(ssoConfigService.getActiveSSOCertificateURL());
        // Eg. http://localhost:8090/auth/realms/demo-app/protocol/openid-connect/certs

        http.addFilterBefore(new OncePerRequestFilter() {
            // Every time a request occur, this method will be called.
            @Override
            protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

                try {
                    http.oauth2ResourceServer()
                            .authenticationEntryPoint(oAuth2AuthenticationEntryPoint)
                            .accessDeniedHandler(oAuth2AccessDeniedHandler)
                            .jwt()
                            // Some Auth server URL which would be fetch from table
                            .jwkSetUri(ssoConfigService.getActiveSSOCertificateURL());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, BasicAuthenticationFilter.class);
    }

I hope this info can help you.

  • Thanks will check. Also can you update the correct link for `OAuth2ResourceServerProperties`. You updated the cors help link on both. – ARods Aug 30 '21 at 05:37
  • Also Is there a way to Lazy Initialize spring security at Runtime (not on the application startup), when my configuration table has been filled up by user by an API call, after that I want to initialize with that SSO values and the security should take effect. – ARods Aug 30 '21 at 05:43
  • @ARods, do you configuration table is in the same project that you are trying to implement Spring Security or is it in a external database? Can you explain better the workflow and architecture of your use case to understand better what you want to do and why you need to initialize Spring Security in a Lazy way as you explain above? – Wilson Tineo Moronta Aug 31 '21 at 14:36
  • Yes I have the configuration table and API for that in the same project and same DB and managing UI with React JS as well. I want the admin user to update the OAuth configuration via API, at this point only the configuration table would have filled with entries. Then only we can have the values to initiate to Spring security with OAuth issuer URL (otherwise the application will fail at startup). I don't have the issuer URL value initially. That's why I wanted to do lazy load the Spring Security at Runtime, not at application startup. Is this possible? – ARods Aug 31 '21 at 15:55
  • @ARods, how do you going to protect "the admin user API that you create to update the OAuth configuration in your DB" if you load Spring Security after his fills the DB table? I suppose that you will have an API for the OAuth admin configuration and other API for the ReactJS app. – Wilson Tineo Moronta Aug 31 '21 at 19:29
  • The plan was to enable basic auth for Oauth configuration API with some hard coded users to protect this API and OAuth security for other API's. But while started working only I realised these problems, so only created these question. Still not sure how to make this flow work – ARods Sep 01 '21 at 00:54