Spring Security OAuth 2.0 - client secret always needed to provide authorization code

As per the specification, token requests using authorization code permission are not required for authentication if client_id

included in the request and , but client_id

the same one is used to generate the code. However, with the Spring Security OAuth 2.0 implementation, it seems that basic auth is always required on the endpoint /oauth/token

, even if the client has never been assigned a secret.

It looks like there is support for providing clients with no secret because of the method isSecretRequired()

in the frontend ClientDetails

. What do I need to do to ensure that non-privacy clients are URL authenticated /oauth/token

?

4.1.3. Access Token Request

The client makes a request to the token endpoint by sending the request the following parameters using the "application / x-www-form-urlencoded"
format in Appendix B with UTF-8 character encoding in the HTTP request entity-body format:

grant_type MANDATORY. The value MUST be set to "authorization_code".

the code is REQUIRED. The authorization code received from the authorization server.

redirect_uri is REQUIRED if the "redirect_uri" parameter was included in authorizations as described in section 4.1.1 and their values ​​MUST be identical.

client_id is REQUIRED if the client is not authenticated using authorization as described in section 3.2.1.

If the client type is confidential or the client has issued credentials (or other assigned authentication requirements), the
client MUST authenticate with the authorization server, as described in section 3.2.1.

+8


source to share


5 answers


Client authentication using form parameters instead of basic auth is activated using a method allowFormAuthenticationForClients()

as shown in the code example below.

class AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {

    @Override
    void configure(AuthorizationServerSecurityConfigurer security) {
        security
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()")
                .allowFormAuthenticationForClients()
    }
}

      



The method allowFormAuthenticationForClients()

launches an add ClientCredentialsTokenEndpointFilter

that allows authentication through form parameters.

+7


source


Spring allows you to define OAuth2 clients with an empty secret. They can be considered "public" clients or clients who cannot keep secrets. Think Javascript apps, mobile apps, ..... Usually you don't want to store secret customer records there.

As you note, according to the OAuth2 specification, the token endpoint may not require secrets for these public clients.



So, in Spring, just define an OAuth2 client with an empty secret and configure it for a limited set of grant types (authorization_code and refresh_token)

The Spring Security Token Token will accept a non-client secret token exchange for that particular OAuth2 client.

+4


source


I originally had a setup similar to the accepted answer, which is definitely a prerequisite for this to work. But what's missing is that you can't just set the password to zero. You must set an empty password for it, like so:

String secret = PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("");
clientDetails.setClientSecret(secret);

      

If you don't, you will still get 401!

0


source


To solve the problem, see loadUserByUsername

Class Method org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService

::

if (clientSecret == null || clientSecret.trim().length() == 0) {
   clientSecret = this.emptyPassword;
}

      

Probably in your case emptyPassword

it was not initialized with a blank encoded password by your password encoder. Install the missing password encoder in AuthorizationServerConfigurerAdapter

:

@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
    oauthServer.passwordEncoder(passwordEncoder);
}

      

0


source


like this:

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
            .withClient("client").secret(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("")) //empty
            .authorizedGrantTypes("authorization_code", "refresh_token")
            .redirectUris("http://www.dev.com")
            .scopes("all")
            .autoApprove(true);
} @Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
        throws Exception {
    oauthServer.tokenKeyAccess("permitAll()")
            .checkTokenAccess("isAuthenticated()")
            .allowFormAuthenticationForClients();
}

      

This is normal.

-1


source







All Articles