I use the oAuth2 secure services suite. Currently, it works as follows: a client is registered using a username and password. I exchange them for a token. I save the token in the session and send it every time I want to call the service. It works, but the problem is that I do it completely manually, without using most of the support
<authentication-manager alias="authenticationManager"> <authentication-provider ref="oAuth2AuthenticationProvider"/> </authentication-manager> <beans:bean id="oAuth2AuthenticationProvider" class="my.custom.Oauth2AuthenticationProvider"> <beans:constructor-arg name="accessTokenUri" value="http://xxxx/oauth/token"/> <beans:constructor-arg name="clientId" value="myClientId"/> <beans:constructor-arg name="clientSecret" value="myClientSecret"/> <beans:constructor-arg name="scope"> <beans:list> <beans:value>myScope</beans:value> </beans:list> </beans:constructor-arg> </beans:bean> <beans:bean id="resourceOwnerPasswordAccessTokenProvider" class="org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider"/>
As you can see, I myself made an authentication provider. It accepts the standard UserPasswordAuthenticationToken, but produces my own extension, which also supports the actual OAuth2AccessToken, thereby preserving it in a security context.
public class Oauth2AuthenticationProvider implements AuthenticationProvider { @Autowired private ResourceOwnerPasswordAccessTokenProvider provider; private String accessTokenUri; private String clientId; private String clientSecret; private List<String> scope; public Oauth2AuthenticationProvider(String accessTokenUri, String clientId, String clientSecret, List<String> scope) { this.accessTokenUri = accessTokenUri; this.clientId = clientId; this.clientSecret = clientSecret; this.scope = scope; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password = authentication.getCredentials().toString(); OAuth2AccessToken token = obtainToken(username, password); return handleLogonSuccess(authentication, token); } private OAuth2AccessToken obtainToken(String username, String password) { ResourceOwnerPasswordResourceDetails passwordResourceDetails = new ResourceOwnerPasswordResourceDetails(); passwordResourceDetails.setUsername(username); passwordResourceDetails.setPassword(password); passwordResourceDetails.setClientId(clientId); passwordResourceDetails.setClientSecret(clientSecret); passwordResourceDetails.setScope(scope); passwordResourceDetails.setAccessTokenUri(accessTokenUri); DefaultAccessTokenRequest defaultAccessTokenRequest = new DefaultAccessTokenRequest(); OAuth2AccessToken token; try { token = provider.obtainAccessToken(passwordResourceDetails, defaultAccessTokenRequest); } catch (OAuth2AccessDeniedException accessDeniedException) { throw new BadCredentialsException("Invalid credentials", accessDeniedException); } return token; } public OAuth2AccessToken refreshToken(OAuth2AuthenticationToken authentication) { OAuth2AccessToken token = authentication.getoAuth2AccessToken(); OAuth2RefreshToken refreshToken = token.getRefreshToken(); BaseOAuth2ProtectedResourceDetails resourceDetails = new BaseOAuth2ProtectedResourceDetails(); resourceDetails.setClientId(clientId); resourceDetails.setClientSecret(clientSecret); resourceDetails.setScope(scope); resourceDetails.setAccessTokenUri(accessTokenUri); OAuth2AccessToken newToken = provider.refreshAccessToken(resourceDetails, refreshToken, new DefaultAccessTokenRequest()); authentication.setoAuth2AccessToken(newToken); return newToken; } public boolean supports(Class<?> authentication) { return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); } private Authentication handleLogonSuccess(Authentication authentication, OAuth2AccessToken token) { MyCustomOAuth2AuthenticationToken successAuthenticationToken = new MyCustomOAuth2AuthenticationToken(user, authentication.getCredentials(), calculateAuthorities(authentication), token); return successAuthenticationToken; } public list<GrantedAuthority> calculateAuthorities(Authentication authentication) {
}
As you can see, this basically ensures that the token remains in the security area, from where I can simply extract it manually before each call to internal services. Similarly, I will check for freshness of the token before each call. This works well, but I'm sure I can use the Spring oauth namespace in XML (I don't use the Java configuration) to achieve the same thing in more-config-less-code. Most of the examples I find include an oAuth server implementation that I don't care about and just confuse me.
Can anyone help me with this?