1

I was struggling to find the correct way of implementing OAuth with Google API and finally managed to get it working by implementing a DataStore to manage the users access tokens.

However it has now stopped working, and by that I mean once the code has redirected me to Google and I've selected a profile and authorized the app to access the requested information my app throws a TokenResponseException

Server Error in '/' Application.

Error:"State is invalid", Description:"", Uri:""

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"State is invalid", Description:"", Uri:""

What I have noticed is that the FileDataStore I passed to IAuthorizationCodeFlow is no longer creating files in the specified directory. Where as before it was creating a file with a name similar to System.String-oauth_5f798cfd-0d9a-42ad-a05b-567fda21d916 which was just a text file with my url inside of it.

For clarity the url which throws this error is https://myurl.net/AuthCallback/IndexAsync?state=https://myurl.net/dashboard32977907&code=4/PAtdUBSV4noqSna3j5ELkan0eOel.wu5woMyVz9kWYKs_1NgQtmV75cIkiQI

JConstantine
  • 3,980
  • 1
  • 33
  • 46
  • I am facing exactly the same issue when implementing my own IDataStore. Did you succeed in the end? Can you please share how? This is my question : http://stackoverflow.com/questions/27254339/google-drive-api-custom-idatastore-with-entity-framework – Hugo Hilário Dec 03 '14 at 10:25
  • Sorry @HugoHilário I was never able to fix this. Didn't want to waste any more time looking – JConstantine Dec 04 '14 at 05:12

2 Answers2

0

The error means that the state parameter that Google sent back to your application is not the same one that you sent (considering the comparison is being done correctly).

I don't know how you are creating the authentication URL (the one that points to the Google server), but I think you should url-encode the state param.

https%3A%2F%2Fmyurl.net%2Fdashboard32977907

instead of

https://myurl.net/dashboard32977907
Vinicius Braz Pinto
  • 8,209
  • 3
  • 42
  • 60
  • Thanks for your reply. I'm actually using the .NET MVC Extensions for Google APIs so the authentication URL being generated is out of my control. I have noticed however on this SO post http://stackoverflow.com/questions/16411909/google-oauth-2-and-state-parameter-values-need-to-be-registered-in-redirect-url that the state is only the local part and not the full URL as in this case – JConstantine Mar 18 '14 at 13:21
  • I'm not familiar with the .NET lib, but the API docs say the state paramater can be any string, and usually libraries provide a method to set the state before creating the URL. – Vinicius Braz Pinto Mar 18 '14 at 14:09
  • It definitely seems as if the library handles that part of the request. Digging deeper it certainly seems as if the `FileDataStore` isn't saving the oauth details so when it comes to compare the expected and current value is comparing against an empty string – JConstantine Mar 18 '14 at 14:42
  • It doesn't look like `FileDataStore` works well with azure websites. I'm going to create my own abstraction of `IDataStore` and get back to you – JConstantine Mar 18 '14 at 15:33
  • Okay, so I stored the details to table store and found that the state is being stored where the oauth details (acces_token, token_type, etc) should be stored and the oauth details are being stored where the state should be stored. So when it asks for the state is can't find anything by the specified key (in this case guid.) Is there any reason why this would change all of a sudden? – JConstantine Mar 18 '14 at 16:40
  • @JLevett did you find any root cause of why the state is not saved correctly? – Hesham Oct 26 '15 at 22:04
  • Sorry @Hesham the project was scrapped so we never managed to fix this – JConstantine Oct 28 '15 at 16:06
0

This usually happens when the value of userId changes between the authorization steps/redirects.
For example, if you use Session.SessionID as the userId, and don't store anything in the session, ASP.NET changes the SessionID with each request.

By userId, I mean the first parameter of methods like GoogleAuthorizationCodeFlow.ExchangeCodeForTokenAsync() or AuthorizationCodeWebApp.AuthorizeAsync().

Community
  • 1
  • 1
jansokoly
  • 1,994
  • 2
  • 18
  • 25