0

I have successfully set up a JWT resource server that retrieves User information from a database.

Now, I need a alternative way of authentication (preferably using Basic Auth and In-Memory Users) to create a default application user, so I can create the database Users.

This is what I tried so far:

Authorization Server Config:

@Configuration
public class AuthorizationServerConfig {

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain oauthServerSecurityFilterChain(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
        return http.build();
    }

    @Bean
    public AuthorizationServerSettings oauthServerSettings() {
        return AuthorizationServerSettings.builder().build();
    }

}

Resource Server Config:

@EnableMethodSecurity
@Configuration
@RequiredArgsConstructor
public class ResourceServerConfig {

    private final UserAuthenticationTokenConverter userAuthenticationTokenConverter;
    private final InMemoryUserDetailsManager inMemoryUserDetailsManager;

    @Bean
    public SecurityFilterChain resourceServerSecurityFilterChain(HttpSecurity http) throws Exception {
        http.oauth2ResourceServer(customizer ->
            customizer.jwt( jwt ->
                jwt.jwtAuthenticationConverter(userAuthenticationTokenConverter)
            )
        ).userDetailsService(inMemoryUserDetailsManager);
        return http.build();
    }

}

InMemoryUserDetailsManager Config:

@Configuration
@RequiredArgsConstructor
public class InMemoryUserPropertiesConfig {

    private final BasicUsersProperties basicUsersProperties;

    @Bean
    public InMemoryUserDetailsManager userDetailsManager() {
        List<UserDetails> users = basicUsersProperties.getUsers().stream()
                .map(PropertiesUserDetails::new)
                .collect(Collectors.toList());
        return new InMemoryUserDetailsManager(users);
    }

}

The InMemoryUserDetails is loading the users correctly, but it don't seems to be used during authentication.

1 Answers1

-1

The problem is that JwtAuthenticationProvider does not invoke UserDetailService - it assumes that the JWT has all the relevant authentication information - so there is no need to go the UserDetailService to fetch Authorities, etc..

So (if I understand what you want to do) in your userAuthenticationTokenConverter you will need to pull the user identifier from the jwt and then call the UserDetailService yourself to authenticate.

I gave a similar answer here https://stackoverflow.com/a/70409011/13675557

  • he should not call the database when someone provides a JWT as this will make his application extremely easy to DDoS, and calling the database on each time someone provides a valid JWT will tank the database extremely quick. Your other answer has this problem too as it uses JWTs as some form of session holder, which JWTs should not be used for. JWTs are extremly insecure to be used as session holders, and this is why spring security doesnt have an implemention for it. – Toerktumlare Jul 20 '23 at 21:31
  • It wouldn't go the database as he created an in-memory UserDetailsManager. My understanding is that is what he wants - to map the jwt to the in-memory UserDetails. But I could be wrong here - that is why added the parenthetical. – Andrew Hall Jul 21 '23 at 19:12
  • Well your other answer points to such solution. Please take some time and read up on why jwts should not be used as session tokens. Also read up on the owasp jwt cheat sheet to understand the security problems. Then read the oauth2 specification and the open id connect spec to understand how bearer tokens should be used, and what you need to use them correctly. – Toerktumlare Jul 21 '23 at 23:57
  • With basic auth, every call needs a user lookup. That is the entire point of UserDetailService. So, I don't see how this scenario is any more or less secure than Basic Auth. And depending on your setup, you may receive a jwt without the needed roles or other required fields, so a lookup can't be avoided. However, performance optimization (session caching) can be applied here just like basic auth. We don't know the context of OP - so I don't want jump to conclusions. – Andrew Hall Jul 22 '23 at 17:00
  • `With basic auth, every call needs a user lookup` with basic auth the lookup is done when you login, once, then a session cookie is issued and cached. Not on each subsequent calls. Here a lookup is done in every request, everytime a token is passed. So yes, it does matter. In general JWTs should not even be used as session barers as it is insecure to do so, and is one of the major reasons as to why there is no such implementation in spring security. – Toerktumlare Jul 22 '23 at 17:23