Search code examples
google-cloud-platformoauth-2.0google-oauthactions-on-google

oAuth JWT resulting in Invalid Argument Error (400)


I'm trying to enable account linking on my google action using oAuth2 code grant flow.

Unfortunately my linking fails in the last step. I think that I'm not returning the result of my /token endpoint correctly back to google.

I can see this response of a 400 error in my console after getting redirect to my actions page (/authorize worked fine):

Request URL: https://oauthintegrations.clients6.google.com/v1/token:getForService?key=api-key-removed-by-me&alt=json

{
  "error": {
    "code": 400,
    "message": "\u003ceye3 title='/OpenIdConsumerService.ValidateOpenId, INVALID_ARGUMENT'/\u003e APPLICATION_ERROR;apps_auth/OpenIdConsumerService.ValidateOpenId;com.google.identity.accountlinking.error.FederatedProtocolException: \u003ceye3 title='INVALID_ARGUMENT'/\u003e OpenAuth::INPUT_ERROR: ;AppErrorCode=13;StartTimeMs=1602166359350;tcp;Deadline(sec)=59.962523136;ResFormat=UNCOMPRESSED;Originator=traffic-prod;Tag=\u0002cloud_project_number\u0003744920882961\u0002IncomingMethod\u0003/OAuthIntegrationsService.GetTokenForService\u0002cidc\u00032;ServerTimeSec=1.00669508;LogBytes=256;Non-FailFast;EffSecLevel=privacy_and_integrity;ReqFormat=UNCOMPRESSED;ReqID=2d3a46fa4ab8370e;GlobalID=c34268105821e185;Server=[2002:ab3:7310::]:4155",
    "status": "INVALID_ARGUMENT"
  }
}

This is the body I send back to google for /token (I guess this results in the error above):

{
"access_token":"jwt-token-here",
"expires_in":"1602162256000",
"refresh_token":"refresh-token-here",
"refresh_token_expires_in":"31535999",
"token_type":"Bearer",
"scope":"read"
}

Is the structure of the body correct? I think it's because of the jwt-token but when I decode it manualy everything looks fine.

Any help appreciated!

Thank you


Solution

  • Unfortunately my linking fails in the last step. I think that I'm not returning the result of my /token endpoint correctly back to google.

    Just a quick note that your access/refresh tokens are opaque to Google. You are handing over these credentials for Google to pass back to you in future requests. What these tokens mean, and how they are determined to be valid, is up to your OAuth server implementation.

    See the OAuth account linking guide for more details.

    This is the body I send back to google for /token

    The fields scope and refresh_token_expires_in are not parameters Google expects in your token exchange responses, so this is likely where the INVALID_ARGUMENT error is coming from. A basic token response to Google should looking something like this:

    {
      "access_token":"jwt-token-here",
      "expires_in":"1602162256000",
      "token_type":"Bearer",
    }
    

    The expires_in field refers to the access token and when Google should use the refresh token to request a new access token.

    If you want to expire or rotate your refresh tokens, you can do that as well. However, you can't tell Google when a refresh token will "expire". To rotate refresh tokens, you have to pass back the new token the next time Google requests a new access token, such as:

    {
      "access_token":"jwt-token-here",
      "expires_in":"1602162256000",
      "refresh_token":"updated-refresh-token-here",
      "token_type":"Bearer",
    }
    

    See the OAuth implementation guide for more details on the fields in the requests and responses.