Seemingly valid access_token returns 401 even with correct grants

70 views
Skip to first unread message

al...@alexquick.com

unread,
Aug 7, 2014, 7:39:25 PM8/7/14
to adsen...@googlegroups.com
Hi,

I'm running into some authentication/authorization issues. What's interesting is that this is with a client that works with many other users, and this particular issue can be recreated in a homemade client, the Google API Python bindings, and manual HTTP requests. The issue is that a seemingly valid refresh_token ends up giving 401s when making requests to the AdSense API.

Here's the flow--given a refresh token, we exchange it for an access token: 

 $ curl -vv -XPOST https://accounts.google.com/o/oauth2/token \
 
-d"client_id=869353560953.apps.googleusercontent.com" \
 
-d"client_secret=snip" \
 
-d"refresh_token=1/snip" \
 
-d"grant_type=refresh_token"
> POST /o/oauth2/token HTTP/1.1
> User-Agent: curl/7.37.0
> Host: accounts.google.com
> Accept: */*
> Content-Length: 173
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: Fri, 01 Jan 1990 00:00:00 GMT
< Date: Thu, 07 Aug 2014 21:24:50 GMT
< Content-Disposition: attachment; filename="json.txt"; filename*=UTF-8''json.txt
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< Server: GSE
< Alternate-Protocol: 443:quic
< Transfer-Encoding: chunked
<
{
  "access_token" : "ya29.snip",
  "token_type" : "Bearer",
  "expires_in" : 3600,
  "id_token" : "snip"
}



Then see if the token is valid:
 curl -vv "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=ya29.snip"
> GET /oauth2/v1/tokeninfo?access_token=ya29.snip HTTP/1.1
> User-Agent: curl/7.37.0
> Host: www.googleapis.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: Fri, 01 Jan 1990 00:00:00 GMT
< Date: Thu, 07 Aug 2014 21:26:09 GMT
< Content-Type: application/json; charset=UTF-8
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< Server: GSE
< Alternate-Protocol: 443:quic
< Transfer-Encoding: chunked
<
{
 "issued_to": "869353560953.apps.googleusercontent.com",
 "audience": "869353560953.apps.googleusercontent.com",
 "user_id": "snip",
 "scope": "https://www.googleapis.com/auth/adsense.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.me",
 "expires_in": 3521,
 "email": "em...@example.com",
 "verified_email": true,
 "access_type": "offline"
}



Then try to make a request with it that needs only the adsense.readonly scope:


$ curl
-vv "https://www.googleapis.com/adsense/v1.3/accounts?access_token=ya29.snip"


> GET /adsense/v1.3/accounts?access_token=ya29.snip HTTP/1.1
> User-Agent: curl/7.37.0
> Host: www.googleapis.com
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< WWW-Authenticate: Bearer realm="https://accounts.google.com/AuthSubRequest", error=invalid_token
< Content-Type: application/json; charset=UTF-8
< Date: Thu, 07 Aug 2014 21:29:41 GMT
< Expires: Thu, 07 Aug 2014 21:29:41 GMT
< Cache-Control: private, max-age=0
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< Server: GSE
< Alternate-Protocol: 443:quic
< Transfer-Encoding: chunked
<
{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "authError",
    "message": "Invalid Credentials",
    "locationType": "header",
    "location": "Authorization"
   }
  ],
  "code": 401,
  "message": "Invalid Credentials"
 }
}



The same is true when sending the token in the authentication header, (Authorization: Bearer ya29.snip).

Renegotiating the refresh_token yields the same results. Changing the deprecated scope 'https://www.googleapis.com/auth/userinfo.email' to its replacement 'email' also doesn't change the behavior. I have a feeling there's something about the users's account that is nonstandard but don't see anything in the documentation about this.

Has anyone seen something like this or have any ideas?

Jose Alcérreca (AdSense API Team)

unread,
Aug 8, 2014, 7:17:46 AM8/8/14
to adsen...@googlegroups.com
Hey Alex,

Everything looks good indeed. It could be a problem with the user. Are they able to access the AdSense web interface? If they can, please send me the username privately and we'll investigate.

Cheers,
Jose
Reply all
Reply to author
Forward
0 new messages