0

We have a web server using Google Sign-In to authenticater and authorize for API access (Classroom). We need the sign-in part, so we're using init() and signIn(). We cannot use authorise(). Also, we're not signin in with particular scopes, as we just need identify for normal usage.

The logged-in user can enable a feature that requires offline access on behalf of his/her account to the Google Classrom API. We call grantOfflineAccess() with two scopes related to Classroom to get an authentication code, which is stored for later.

On the server side, we have a gRPC service that doesn't expose any web front-end. We're using C#/.NET with the Google API Client libraries.

I implemented an IDataStore that can respond to TokenResponse requests by either calling AuthorizationCodeFlow.ExchangeCodeForTokenAsync with the above code, or return the last TokenResponse stored in the database. When (well, "if") IDataStore.StoreAsync is called with a new version (normally after a token refresh was required), it saves it again in the database.

My problem is that ExchangeCodeForTokenAsync returns me a TokenResponse without a refresh_token. This means the access_token is only valid for 60 minutes. I would need to intercept exceptions at the service call level to call ExchangeCodeForTokenAsync again (if that works!), instead of relying on the Google API Client Library handling refreshing automatically all nicely.

What could be preventing ExchangeCodeForTokenAsync from returning me a refresh_token?

Thanks.

Martin Plante
  • 4,553
  • 3
  • 33
  • 45
  • why do you need to sign in via the JS libraries? Can't you just do a full server-side sign-in process? In which case your server will already have the token passed to it by Google from the Google Sign in page. Pretty sure this is documented in the API docs. Perhaps I missed something in your requirements. Edit: https://developers.google.com/identity/protocols/OAuth2WebServer documents a full server-side OAuth flow. https://developers.google.com/identity/sign-in/web/server-side-flow documents a hybrid approach using both JS and server-side. – ADyson Oct 17 '17 at 13:24
  • a) To authenticate users. b) We do make API calls in the client app as well. c) The service is a gRPC service without a public front, running maintenance operations periodically. – Martin Plante Oct 17 '17 at 15:57
  • By the way, I did manage to make it work since I posted, pretty much like @ADyson 's second link, but the response does not have a refresh_token. My API calls work, but I'm waiting an hour to see what happens after expiration. – Martin Plante Oct 17 '17 at 16:01

1 Answers1

1

Well, I found the answer in this other question.

The refresh_token is only provided on the first authorization from the user. Subsequent authorizations, such as the kind you make while testing an OAuth2 integration, will not return the refresh_token again. :)

I simply removed my app from my Google account's authorized apps, and my next ExchangeCodeForTokenAsync call returned me a refresh_token.

Martin Plante
  • 4,553
  • 3
  • 33
  • 45