Spring OAuth2 M6 and Google Analytics: No OAuth 2 Security Context
I'm trying to write a service that will pull data from Google Analytics via OAuth2. I've read the docs from Google and Spring and search the net. But this one has given me a headache.
I've setup the necessary Google API console for the client ID, client secret, redirect URI and etc.
Basically, I have an MVC app. To test a sample pulling of data from Google Analytics, I have the following URL: http://localhost:8080/app/google/test (see the controller below).
When going to this URL, I'm presented to the login page. So I have to login first then I'm redirected to the Google Auth permission. So I granted permission to the app. Then it's redirected to http://localhost:8080/app/google/test again (This is the same redirect URI I declared in the Google Console API).
However, this time two parameters are added the state and the code. Why am I given these two parameters? Isn't OAuth2RestTemplate supposed to handle the OAuth dance for me?
Am I missing something?
I'm receiving the following exception:
Code:
org.springframework.security.oauth2.client.http.AccessTokenRequiredException: No OAuth 2 security context has been established. Unable to access resource 'oauth-resource'.
at org.springframework.security.oauth2.client.http.OAuth2ClientHttpRequestFactory.createRequest(OAuth2ClientHttpRequestFactory.java:55)
at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:76)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:434)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:199)
at com.newmedia.jobboard.controller.GoogleAnalyticsController.test(GoogleAnalyticsController.java:56)
Here's my configuration:
Maven
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>3.1.0.RELEASE</spring.version>
<spring.security.version>3.1.0.RELEASE</spring.security.version>
<spring.data.jpa.version>1.1.0.M1</spring.data.jpa.version>
<spring.security.oauth.version>1.0.0.M6</spring.security.oauth.version>
...
</properties>
oauth.xml
Code:
<oauth:client id="oauth2AuthenticationClientFilter" resource-details-service-ref="resourceDetailsService"/>
<beans:bean id="resourceDetailsService" class="org.springframework.security.oauth2.client.resource.InMemoryOAuth2ProtectedResourceDetailsService"
p:resourceDetailsStore-ref="oauthResourceMap"/>
<util:map id="oauthResourceMap">
<beans:entry key="1" value-ref="oauth-resource"/>
</util:map>
<oauth:resource id="oauth-resource"
type="authorization_code"
access-token-uri="https://accounts.google.com/o/oauth2/token"
user-authorization-uri="https://accounts.google.com/o/oauth2/auth"
client-id="dlkfjglksdjglsdjglsdfgdfgagsd"
client-secret="sgsdfgsdfgdfgdfgdf"
scope="https://www.googleapis.com/auth/analytics.readonly"/>
<beans:bean id="oAuth2RestTemplate" class="org.springframework.security.oauth2.client.OAuth2RestTemplate"
c:resource-ref="oauth-resource"/>
security.xml
Code:
<http use-expressions="true">
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/logout" access="permitAll"/>
....
<intercept-url pattern="/google" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/google/test" access="hasRole('ROLE_ADMIN')"/>
<form-login login-page="/login"
authentication-failure-url="/login?error=true"
default-target-url="${afterLoginPage}"/>
<access-denied-handler error-page="/login/denied"/>
<logout invalidate-session="true"
logout-success-url="${afterLogoutPage}"
logout-url="/logout"/>
<custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="oauth2AuthenticationClientFilter" />
</http>
Controller
Code:
@Controller
@RequestMapping("/google")
public class GoogleAnalyticsController {
protected static Logger logger = Logger.getLogger("controller");
@Autowired
@Qualifier("oAuth2RestTemplate")
private RestTemplate oauth2RestTemplate;
@RequestMapping
public String getMain() {
return "google-analytics.tiles";
}
@RequestMapping(value = "/test", method = RequestMethod.GET)
public @ResponseBody StatusResponse test() {
logger.debug("Calling dataUri");
String dataUri = "https://www.googleapis.com/analytics/v3/data/ga?" +
"ids=ga:11122233&" +
"start-date=2009-04-20&" +
"end-date=2012-06-20&" +
"metrics=ga:visits,ga:bounces";
ObjectNode result = oauth2RestTemplate.getForObject(dataUri, ObjectNode.class);
return new StatusResponse(true, result.toString());
}
}