I have a fairly basic Spring Boot setup and I have installed Spring Security and I have managed to successfully set up OAuth2 to protect my API.
I had some trouble a few days back and asked (and answered) a question with regards to hitting my /oauth/token
end point. I soon figured out that the problem was that I was trying to send my client credentials in the body of my POST
request but the token end point is configured in Spring Security to accept the client credentials (client_id
and secret
) via HTTP Basic Auth instead.
Most of my experience with consuming OAuth2 APIs has involved sending client credentials in the body of the POST
request and I was wondering if it was possible to configure Spring Security to function in the same way?
I've tried a few different things with no success, like setting the following configuration option, but I feel like that might only be used when configuring an OAuth2 client:
security.oauth2.client.clientAuthenticationScheme=form
This is my Authorization server configuration.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Autowired
private UserApprovalHandler userApprovalHandler;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client_id")
.secret("secret")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("read", "write")
.accessTokenValiditySeconds(600)
.refreshTokenValiditySeconds(3600);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(this.tokenStore)
.userApprovalHandler(this.userApprovalHandler)
.authenticationManager(this.authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.passwordEncoder(this.passwordEncoder);
}
}
As pointed out by @chrylis in the comments, the trick is to use the allowFormAuthenticationForClients
method on AuthorizationServerSecurityConfigurer
when configuring the authorization server. In my case, I have this in my AuthorizationServerConfig
class:
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.passwordEncoder(this.passwordEncoder)
.allowFormAuthenticationForClients();
}
That will allow passing client credentials via standard parameters, such as in the body of the POST
request (or in the query string), though Spring prefers using HTTP Basic Auth by joining the client_id
and secret
together with a colon (<client_id>:<secret>
), base-64 encoding the result, prefixing it with Basic
and passing that to the Authorization
header, so you would end up with something like this:
Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With