Re: OAuth 2.0 400 - error:invalid_grant and ideas?

Nick Apr 6, 2012 10:04 AM
Posted in group: google-analytics-data-export-api
Hi ok,

fixing docs is easy enough.

OAuth2 is both currently supported and our best practice to handle authorization.

Though notice there are 6 OAuth 2 flows documented:

My question is why you need the Service Account flow vs the Web Server flow?

Web Server works fine today. Service Account is quite new and we need to add support in our API for it.


On Friday, April 6, 2012 2:12:58 AM UTC-7, Ian Ibbotson wrote:
Hiya Nick, thanks for asking...

To be (brutally) honest, I think I've not explained myself very well..

the data API is completely fine for me.. it's just that the path I had taken through the documentation paints a very clear picture that older authentication mechanisms will be deprecated (In the very near future is the impression given). As this was starting out a new project, it seemed to only make sense to code it to the suggested api rather than the legacy one. If the old api isn't going away, I'll very happily re-code to use that. The docs certainly didn't make it obvious that OAuth2 isn't yet supported.

FWIW tho, I strongly believe that the documentation path devs are led through (from the sign-up / API screens) give the impression that OAuth2 is the only legitimate choice. So I'd suggest it's more a documentation bug than a feature request really.

Cheers, for following up, and many thanks to everyone else who has posted on this. I'll be having a go this weekend and will report back, but looks like it's sorted for now!


On Friday, 6 April 2012 07:49:03 UTC+1, Nick wrote:

We're looking into supporting this.

In the mean time can you help me understand the use case on why you need 'server to server' authentication?

It seems like if you have GA today, you must have signed our TOS, and used our UI once. So how is going through the server side OAuth 2 flow once, (and storing / using refresh) tokens a less appealing option to access data though our API?


On Sunday, April 1, 2012 4:18:50 PM UTC-7, doucol wrote:

I was able to get it all working.  First, you have to abandon any idea of getting a "server to server" authentication setup working against the analytics service - it doesn't support it (yet).  And, yes, it's very frustrating because everything I read lead me to believe that we should be using that - at least for my situation.  And, *nothing* I read ever gave me a sign that perhaps the analytics service did not support this authentication model yet.  <sigh>

Ok, so here is how I did it:
  • Go to Google APIs Console and make sure you have a "Client ID for web applications"
  • If you don't have that type of client ID, click "Create another Client ID..." button and create one
  • Go to OAuth 2.0 Playground
  • Click on the settings button in the top-right.
  • Click on "Use your own OAuth credentials"
  • Enter your OAuth client ID and client secret and close it
  • Go to step 1 and select "Analytics" and click "Authorize APIs"
  • Go through consent page
  • Go to step 2 and click "Exchange authorization code for tokens"
  • You should get an access token and a refresh token
  • Save this refresh token to a secure file which your groovy code can read 
  • Click on the "Refresh access token" button
  • Now you should see the POST on the right which gets a new access token using a refresh token
  • Write your groovy code which can perform that POST using the refresh token you stored in the file
  • You will get back an access code which you can use to perform queries against the analytics API
  • When it expires, you will need to obtain a new access code using the same technique
Here is the downside to this approach - first, this refresh token, and hence the queries, are now tied to the actual google user who gave the consent in the OAuth 2.0 playground.  secondly, I'm not sure about this, but I *think* that if you authorized again and got a new refresh token, the original refresh token might not work.  I would need to test this to be sure.

This worked for me and I hope it works for you. If / when the 'server to server' authentication is turned for analytics, I will switch over to that.

Let me know how it goes.

On Saturday, March 31, 2012 10:05:50 AM UTC-7, Ian Ibbotson wrote:
Yep.. same boat here and stuck again.. only getting 403 responses :(

On Mar 31, 10:11 am, doucol <> wrote:
> Soooo funny.  I just spent the last two days on the same exact problem.
>  Yeah, very frustrating.
> However, now all I get back is a 403 forbidden from the actual analytics
> service request.  :(
> On Saturday, March 31, 2012 1:45:44 AM UTC-7, Ian Ibbotson wrote:
> > Typically...
> > After fighting with this for 14 odd hours, and finally posting here...
> > I go and fix it in 3 mins!
> > I thought it was just worth trying the email address from the API
> > console instead of the client-Id.. Hey presto, 200OK.
> > Hopefully this will help someone else. Google friends, can I make a
> > suggestion that
> >
> > could use a small edit in under the "Forming the JWT Claim Set"
> > heading, "Required Claims" section. Specifically, the table listing
> > the parameters reads "iss - the client_id of the application making
> > the access token request". I think it should really read "the Email
> > address as taken from the API Console service account setting".. I'm
> > pretty sure it says to send client_id in a few other places, but that
> > page seems to be the authoritative one, and is linked from the API
> > console. Making it a bit clearer would have saved me a bit of pain.
> > Thanks all!
> > Ian.
> > On Mar 31, 9:30 am, Ian Ibbotson <> wrote:
> > > Hi All.
> > > Apologies if I'm asking a dumb question, did search around and I
> > struggled
> > > to find anything that matched. Please feel free to tell me to go search
> > > harder if I'm just being dumb....
> > > I have a server app that needs to collect it's own analytics data from
> > the
> > > API, and had planned to use the service-accounts scenario to collect the
> > > data... At first I tried to use the google libraries, but they seem to
> > come
> > > with a world of dependency hell that I'd like to avoid if at all
> > possible.
> > > Aside from that, I thought it would be good to try and understand the
> > > process from the ground up.
> > > I've had some limited success getting the JWT request together and
> > signing
> > > it.. I *think* everything is as it should be, but when I make my first
> > call
> > > the server always returns 400 : error:invalid_grant
> > > I've tried generating a new key, but nothing seems to help, and I'm a
> > bit
> > > stuck to know whats going wrong and why.
> > > I've attached a .groovy test that demonstrates the problem if anyone is
> > > sufficiently motivated to take a look. To run it, you'll need to
> > generate a
> > > new service account from the api console, download the key and then
> > update
> > > the test file with your client_id and path to the downloaded .p12 file.
> > > The test script should grab all the dependencies it needs. Hopefully
> > > someone out there will take a look and spot that I've just done
> > something
> > > really dumb.
> > > Thanks for any assistance!
> > > Ian.
> > >  test.groovy
> > > 4KViewDownload