aileftech / snap-admin

A plug-and-play, auto-generated CRUD database admin panel for Spring Boot apps
MIT License
256 stars 20 forks source link

Question: how to use Keycloak to protect the admin pages ? #45

Open daaa57150 opened 5 months ago

daaa57150 commented 5 months ago

Hi,

I'm currently testing Snap Admin and I'm a bit stuck with the security. We are using Keycloak as our JWT token provider to secure our endpoints, I'm a bit lost as how I could use that to protect the admin pages.

Has anyone tried that ? Or any other JWT identity provider ?

Thanks!

aileftech commented 5 months ago

Hi,

I assume that the procedure listed in the Security section of the documentation is not applicable in your case (maybe with some adaptations)?

I've never used JWT so I'm just trying to understand what is different w.r.t "normal" authentication. Can you show what your configuration looks like/where the problem occurs exactly?

daaa57150 commented 5 months ago

This is what I currently have as my SecurityFilterChain:

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((authz) ->
                authz.requestMatchers(HttpMethod.GET, "/*").permitAll()
                        .anyRequest().authenticated());

        // was using REST only up to now, so STATELESS made sense
        http.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
        // Custom conversion from the JWT token to our User/Principal class
        http.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtConverter)));

        return http.build();
    }

Since we are all beginners in this part of the project, not sure it's totally correct but for now it works with our rest controllers.

I can probably adapt what's in the in the Security section, but the question is how ;). A login page doesn't make sense as the login is made from outside the app in Keycloak.

I'll see if I can find something, I hoped someone would have done it already.

aileftech commented 5 months ago

From the code it seems you have permitAll() on every GET request, so If I understand correctly you could try something like this and change the policy for requests that are inside SnapAdmin:

@Autowired
private SnapAdminProperties properties;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
       String baseUrl = properties.getBaseUrl(); // <- Get the SnapAdmin base URL

    http.authorizeHttpRequests((authz) ->
            authz
                      // Added these two lines to make requests to the baseURL authenticated instead of permitAll
                    .requestMatchers(AntPathRequestMatcher.antMatcher("/" + baseUrl + "/**"))
                     .authenticated()
                    .requestMatchers(HttpMethod.GET, "/*").permitAll()
                    .anyRequest().authenticated());

    // was using REST only up to now, so STATELESS made sense
    http.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
    // Custom conversion from the JWT token to our User/Principal class
    http.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtConverter)));

    return http.build();
}

I believe this should work with any authentication method since we're just editing the security filter chain, but I've never tried JWT so let me know if it actually works.