I've been trying to get Spring OAuth2 working with XML configuration. I have a fully (non Spring Boot) working application using Spring Security with the latest versions of libraries. I had Spring Social for Google configured and working prior to this.
XML configuration.
Starting with application context (there's a lot more but probably not relevant). I've written my own ClientTokenServicesImpl
, but it functions the same.
<oauth:client id="oAuth2ClientFilter" />
<oauth:resource id="google" type="authorization_code" client-id="${google.clientId}" client-secret="${google.clientSecret}" access-token-uri="${google.accessTokenUri}"
user-authorization-uri="${google.authorisationUri}" scope="email,profile,openid" />
<oauth:rest-template id="oAuthRestTemplate" resource="google" access-token-provider="accessTokenProvider" />
<bean id="accessTokenProvider" class="org.springframework.security.oauth2.client.token.AccessTokenProviderChain">
<property name="clientTokenServices">
<bean class="com.tetsuwantech.atom.manager.authentication.oauth2.ClientTokenServicesImpl" />
</property>
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider" />
<bean class="org.springframework.security.oauth2.client.token.grant.implicit.ImplicitAccessTokenProvider" />
<bean class="org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider" />
<bean class="org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider" />
</list>
</constructor-arg>
</bean>
<security:http entry-point-ref="authenticationEntryPoint" access-decision-manager-ref="accessDecisionManager">
...
<security:intercept-url pattern="/oauth2/**" access="permitAll" />
...
<security:custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="oAuth2ClientFilter" />
</security:http>
Controller
I've got a simple Controller
which just makes a basic call to Google to get the user profile. Once I get the data correctly, I can use it to either create a new user account, or authenticate the user. (I had thought Spring would do the authentication for me.)
@Inject
private RestOperations restTemplate;
@RequestMapping(value = "/oauth2/google")
public String google() {
ObjectNode objectNode = restTemplate.getForObject("https://people.googleapis.com/v1/people/me", ObjectNode.class);
return "redirect:/";
}
UserRedirectRequiredException
If the user is logged in, and then hits the URL I get
org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval
Most of the examples talk about moving oAuth2ClientFilter
higher, to just after SECURITY_CONTEXT_FILTER
but this hasn't worked for me.
InsufficientAuthenticationException
If the user is not authenticated, then I get
org.springframework.security.authentication.InsufficientAuthenticationException: Authentication is required to obtain an access token (anonymous not allowed)
Considering I want to have a user authentication via Google, this seems ironic.
I've looked at the examples in https://projects.spring.io/spring-security-oauth/docs/oauth2.html and through lots and lots of Stackoverflow and other examples, and I can't see what's supposed to happen or where I've gone wrong.