How to exchange the code for an Access Token

814 views
Skip to first unread message

Karl Li

unread,
Feb 1, 2013, 1:08:59 AM2/1/13
to google-oauth...@googlegroups.com
I am using google-oauth-java-client  v1.13.1-beta

Here is my code

AuthorizationCodeTokenRequest request = (AuthorizationCodeTokenRequest) new AuthorizationCodeTokenRequest(
new NetHttpTransport(), new JacksonFactory(),
new GenericUrl("https://graph.facebook.com/oauth/access_token"), "ThisIsMyCode")
.setGrantType("authorization_code")
.setRedirectUri("MyRedirectUrl")
.set("client_id", "MyClientId")
.set("client_secret", "MyClientSecret");
response = request.execute();   //there is an error 

 org.codehaus.jackson.JsonParseException: Unexpected character ('a' (code 97)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@76fd5428; line: 1, column: 2]
at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:1433)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportError(JsonParserMinimalBase.java:521)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportUnexpectedChar(JsonParserMinimalBase.java:442)
at org.codehaus.jackson.impl.Utf8StreamParser._handleUnexpectedValue(Utf8StreamParser.java:2090)
at org.codehaus.jackson.impl.Utf8StreamParser._nextTokenNotInObject(Utf8StreamParser.java:606)
at org.codehaus.jackson.impl.Utf8StreamParser.nextToken(Utf8StreamParser.java:492)
at com.google.api.client.json.jackson.JacksonParser.nextToken(JacksonParser.java:57)
at com.google.api.client.json.JsonParser.startParsing(JsonParser.java:194)
at com.google.api.client.json.JsonParser.parse(JsonParser.java:288)
at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:76)
at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:71)
at com.google.api.client.http.HttpResponse.parseAs(HttpResponse.java:495)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:323)
at com.dodopipe.api.client.auth.oauth2.AccessProvider.getAccessToken(AccessProvider.java:48)
at com.dodopipe.api.client.auth.oauth2.FacebookAccessProviderTest.test(FacebookAccessProviderTest.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
---------------------------------------------------------------------------------------------------------------------------------------
https://graph.facebook.com/oauth/access_token?
    client_id=YOUR_APP_ID
   &redirect_uri=YOUR_REDIRECT_URI
   &client_secret=YOUR_APP_SECRET
   &code=CODE_GENERATED_BY_FACEBOOK
If I copy this to the browser ,it would return a vlue like  access_token=ThisIsAceessToken   (without { } or [ ]  , So it should not be a JSONObject or JSONArray)

Who can help me to solve this?


Ivaylo Kalatchev

unread,
Jul 17, 2013, 2:24:21 PM7/17/13
to google-oauth...@googlegroups.com
I see the same error with v.1.15.0-rc.
Basically the issue is that Facebook does not send a JSON encoded response like described in Section 5.1: http://tools.ietf.org/html/rfc6749#section-5.1
What they return looks like this: 
access_token={actual value}&expires={actual value}

And should instead look like this:
{
 "access_token" : "{actual value}",
 "expires_in" : {actual value}
}

GitHub's default is the same - they return it w/o being JSON-encoded, but at least GitHub allows you to suggest a different format (XML or JSON) by suplying an Accept header. You can suggest JSON format like this (the method is on the Builder class):
.setRequestInitializer(
new HttpRequestInitializer() {
public void initialize(HttpRequest request) {
request.setHeaders(new HttpHeaders().setAccept("application/json"));
}
}
)
In this case GitHub complies by returning JSON which this library can successfully parse.
In the Facebook's case, the Accept header doesn't help (FB doesn't honor it).

Fundamentally both FB and GitHub violate Section 5.1 of the OAuth2 spec by not returning JSON, but would be nice if the Google OAuth2 library can handle cases like this. One way I can think of would be by supplying a response pre-processor of some sort.

Or maybe Yaniv Inbar can reach out to FB and ask them to either: change the implementation (unlikely that they will comply), have FB honor Accept header, or have FB provide another URL that returns JSON encoded access token?

Ivaylo Kalatchev

unread,
Jul 17, 2013, 5:01:55 PM7/17/13
to google-oauth...@googlegroups.com
Another way to avoid the error would be to use request.executeUnparsed() instead of request.execute() and then do the parsing yourself.

Tobias Viehweger

unread,
Oct 15, 2013, 6:48:53 AM10/15/13
to google-oauth...@googlegroups.com, kar...@dodopipe.com
Hi,

I have the same problem with facebook.. Is there a way to get an extension possibilty like Apache Otlu has (https://cwiki.apache.org/confluence/display/OLTU/OAuth+2.0+Client+Quickstart) for parsing non-conform responses in a future release?

For now, executeUnparsed is fine..

Keep up the good work :)
Reply all
Reply to author
Forward
0 new messages