Reputation: 284
I have oauth2 authorization server with one custom endpoint (log out specific user manually as admin) I want this endpoint to be secured with rest client credentials (client id and secret as Basic encoded header value), similar to /oauth/check_token.
This endpoint can be called only from my resource server with specific scope.
I could not find any docs or way to use the Spring`s mechanism for client authentication check.
EDIT 1
I use java config not an xml one
Upvotes: 6
Views: 1650
Reputation: 284
So I ended up with the following solution
Authentication Manager
public class ClientAuthenticationManager implements AuthenticationManager {
private ClientDetailsService clientDetailsService;
private PasswordEncoder passwordEncoder;
public HGClientAuthenticationManager(ClientDetailsService clientDetailsService, PasswordEncoder passwordEncoder) {
Assert.notNull(clientDetailsService, "Given clientDetailsService must not be null!");
Assert.notNull(passwordEncoder, "Given passwordEncoder must not be null!");
this.clientDetailsService = clientDetailsService;
this.passwordEncoder = passwordEncoder;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
ClientDetails clientDetails = null;
try {
clientDetails = this.clientDetailsService.loadClientByClientId(authentication.getPrincipal().toString());
} catch (ClientRegistrationException e) {
throw new BadCredentialsException("Invalid client id or password");
}
if (!passwordEncoder.matches(authentication.getCredentials().toString(), clientDetails.getClientSecret())) {
throw new BadCredentialsException("Invalid client id or password");
}
return new OAuth2Authentication(
new OAuth2Request(null, clientDetails.getClientId(), clientDetails.getAuthorities(), true,
clientDetails.getScope(), clientDetails.getResourceIds(), null, null, null),
null);
}
}
Filter declaration
private BasicAuthenticationFilter basicAuthenticationFilter() {
ClientDetailsUserDetailsService clientDetailsUserDetailsService = new ClientDetailsUserDetailsService(
this.clientDetailsService);
clientDetailsUserDetailsService.setPasswordEncoder(this.passwordEncoder);
return new BasicAuthenticationFilter(
new ClientAuthenticationManager(this.clientDetailsService, this.passwordEncoder));
}
Filter registration
httpSecurity.addFilterBefore(this.basicAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
WARNING!!!
This will prevent any other types of authentication (oauth2, etc.).
ONLY Basic
authentication is accepted and ONLY for registered clients.
Upvotes: 1
Reputation: 2148
@PreAuthorize("#oauth2.hasScope('TEST_SCOPE')")
On the controller method should be sufficiënt. If the client is not authenticated, no scope is available and the scope check will fail.
If you want, you can use the Spring Security expression @PreAuthorize("isAuthenticated()")
to check if a client is authenticated: https://docs.spring.io/spring-security/site/docs/5.0.0.RELEASE/reference/htmlsingle/#el-common-built-in
You could also configure the HttpSecurity
instead of working with @PreAuthorize
Upvotes: 0