Google credentials stop working after a while

Describe the issue/error/question

I handle the multiple user oauth flows on my backend, then I inject the google oauthdata into n8n though the api. Based on previous threads, it is all working out well when I add it, but after a while when I try to test it again (I never measured the delay) it stops working with error EAUTH even though everything seems to be setup correctly. Is it a bug in n8n or I am setting up something wrong in n8n?

Extra info:

  • The redirect url’s are all registered and valid
  • All data seems to be consistent
  • Adding a credential through n8n credentials tab works normally (indicates that the url’s are valid) but never tested it after a while

here is a sample from when I run n8n export:credentials --id=1 --decrypted:

[
  {
    "createdAt": "2023-02-19T21:35:01.154Z",
    "updatedAt": "2023-03-10T21:44:09.175Z",
    "id": "1",
    "name": "test-1676842500961",
    "data": {
      "clientId": "xxx.apps.googleusercontent.com",
      "clientSecret": "xxx",
      "oauthTokenData": {
        "access_token": "xxx",
        "token_type": "Bearer",
        "refresh_token": "xxx",
        "scope": "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email openid https://www.googleapis.com/auth/drive.readonly",
        "callbackQueryString": {
          "scope": "openid https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
        },
        "expires_in": 3599,
        "id_token": "xxx"
      }
    },
    "type": "googleDriveOAuth2Api",
    "nodesAccess": [
      {
        "nodeType": "n8n-nodes-base.googledriveoauth2api",
        "date": "2023-02-19T21:35:01.140Z"
      },
      {
        "nodeType": "n8n-nodes-base.googleDrive",
        "date": "2023-03-10T21:44:09.172Z"
      }
    ]
  }
]

ps: all xxx’s are valid strings I removed

What is the error message (if any)?

ERROR: UNKNOWN ERROR - check the detailed error for more information
The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.

Please share the workflow

Information on your n8n setup

  • n8n version: 0.219.1
  • Database you’re using (default: SQLite): default
  • Running n8n with the execution process [own(default), main]: default
  • Running n8n via [Docker, npm, n8n.cloud, desktop app]: npm

Hey @waffles,

When you say you handle the Auth on your backend does this mean n8n is not currently doing the authentication and it is happening outside and you are just adding parts of it to a credential?

It would be worth adding a credential through n8n and testing it over a few hours so we can see if the issue is generic and not reported by anyone else yet or something with the process that might be causing an issue.

Yes, correct. I am handling oauth for multiple users externally then sending the required data needed to n8n through the api. refer to this for more information: Can n8n be used to authenticate with multiple different users?

Will do that, and update you.

Thanks for the reply

1 Like

The first thing I noticed there was your credential doesn’t have the Auth query parameter for offline access which from what I remember is fairly important for Google credentials.

Did you try refreshing the credential outside of n8n as well like with insomnia / postman that might also help show where the issue is.

I think it might be with your process, oauth is not fun and debugging can be a pain.

@Jon can you elaborate on which exact param are you talking about as I didn’t include any auth query. And you are absolutely correct, the offline access and prompt consent are needed, and they are present in my oauth flow in the backend. In n8n on the other hand, i didn’t include or touch anything else, i assumed i just have to select the googleDriveOAuth2Api and give it the data it needs and it internally always sets the correct scopes n8n needs, as I matched n8n and my usage to n8n with the google app’s api, permissions and scopes

Yes, i’m getting a 200 OK with new and different tokens all the time. the data I am feeding n8n is valid.

I ran n8n export:credentials --id=1 --decrypted for id 1 and 3 and I got these, which are interestingly different:

id=1 is the credential added through n8n api

[
  {
    "createdAt": "2023-02-19T21:35:01.154Z",
    "updatedAt": "2023-03-10T21:44:09.175Z",
    "id": "1",
    "name": "test-1676842500961",
    "data": {
      "clientId": "644xxx.apps.googleusercontent.com",
      "clientSecret": "GOxxxr4",
      "oauthTokenData": {
        "access_token": "yaxxx67",
        "token_type": "Bearer",
        "refresh_token": "1//09xxxNQ",
        "scope": "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email openid https://www.googleapis.com/auth/drive.readonly",
        "callbackQueryString": {
          "scope": "openid https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
        },
        "expires_in": 3599,
        "id_token": "eyxxxsyg"
      }
    },
    "type": "googleDriveOAuth2Api",
    "nodesAccess": [
      {
        "nodeType": "n8n-nodes-base.googledriveoauth2api",
        "date": "2023-02-19T21:35:01.140Z"
      },
      {
        "nodeType": "n8n-nodes-base.googleDrive",
        "date": "2023-03-10T21:44:09.172Z"
      }
    ]
  }
]

id=3 is the credential added through n8n credentials tab (normal UI way)

[
  {
    "createdAt": "2023-03-10T22:38:33.280Z",
    "updatedAt": "2023-03-13T21:36:06.015Z",
    "id": "3",
    "name": "Google Drive account",
    "data": {
      "grantType": "authorizationCode",
      "authUrl": "https://accounts.google.com/o/oauth2/v2/auth",
      "accessTokenUrl": "https://oauth2.googleapis.com/token",
      "clientId": "644xxx.apps.googleusercontent.com",
      "clientSecret": "GOxxxr4",
      "scope": "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.photos.readonly",
      "authQueryParameters": "access_type=offline&prompt=consent",
      "authentication": "body",
      "oauthTokenData": {
        "access_token": "yaxxx67",
        "expires_in": 3599,
        "refresh_token": "1//09xxxX34",
        "scope": "https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.photos.readonly",
        "token_type": "Bearer",
        "callbackQueryString": {
          "scope": "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.photos.readonly https://www.googleapis.com/auth/drive.appdata"
        }
      }
    },
    "type": "googleDriveOAuth2Api",
    "nodesAccess": [
      {
        "nodeType": "n8n-nodes-base.googleDrive",
        "date": "2023-03-10T22:38:33.275Z"
      },
      {
        "nodeType": "n8n-nodes-base.googleDriveTrigger",
        "date": "2023-03-10T22:38:33.275Z"
      }
    ]
  }
]

Notice that credential id=3 is old enough and works while id=1 doesn’t

Hey @waffles,

I think your credential output shows the value that I noticed was missing if you compare the 2 (authQueryParameters), I would maybe see if making your imported credential more like what we use will help.

@Jon Welp I tried to add them but n8n doesn’t allow it.

this is a list of everything I was NOT able to add to the data field in the POST request:

"data": {
      "grantType": "authorizationCode",
      "authUrl": "https://accounts.google.com/o/oauth2/v2/auth",
      "accessTokenUrl": "https://oauth2.googleapis.com/token",
      "scope": "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.photos.readonly",
      "authQueryParameters": "access_type=offline&prompt=consent",
      "authentication": "body"
    }

The response message was always:

{
  "message": "request.body.data is not allowed to have the additional property \"authQueryParameters\""
}

for the above fields it was the same error but with the appropriate field name used.

Here is a sample of the body of my POST request that failed with the above error from n8n:

{
  "name": "Test-account-000",
  "type": "googleDriveOAuth2Api",
  "data": {
    "clientId": "xxx",
    "clientSecret": "xxx",
    "oauthTokenData": {
      "access_token": "xxx",
      "token_type": "Bearer",
      "refresh_token": "xxx",
      "callbackQueryString": {
        "scope": "openid https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
      },
      "expires_in": 3599
    },
    "authQueryParameters": "access_type=offline&prompt=consent"
  }
}

I of course tried all the fields mentioned and all of them failed. Tried them 1 by 1.
And @jan (sorry if being a nuisance) mentioned this: Can n8n be used to authenticate with multiple different users? - #15 by jan

So if the fields in data are being applied automatically, is it a bug that they are not in the data, such as authQueryParameters param, when I export a credential?

Could it be the bug preventing token refreshing?

PS: the google drive credential added by n8n credential tab UI is still working as expected, while the one added programmatically by me is still, as expected, failing

Interesting, I am fresh out of ideas. It does sound like we have a bug there I am just not sure where. Will get an internal ticket created so it can be looked into more.

@Jon alright thanks a lot, hopefully it will get fixed soon!

1 Like

We will need to reproduce it first then work out what is going on.

I did just look at the error again and noticed some more info that could be useful at the end of it, as you are not using the same client and I suspect redirect uri I wonder if that is what is causing the issue.

does not match the redirection URI used in the authorization request, or was issued to another client.

I can’t remember if this has been tried already but if you take the token generated and use it in something else does that work? So say you use postman are you then able to refresh the token from curl?

Also curious to know what happens if you import the credential using the cli option and add in the rest of the data rather than using the api to see if maybe it is just the api missing something.

I am using the same client id all the time, i have a single client id and client secret. Lol, I am not trying to drive myself crazy either :stuck_out_tongue:

Yes, i was able to refresh the token with the same refresh token used in the credentials using postman

Guide me how to do it so I can try it. Also where can i find a list of available commands for n8n? All i found is the API docs

Hey @waffles,

You can find the CLI docs here: CLI commands - n8n Documentation so the plan would be to import a credential using the tokens you generate outside of n8n then add in the other options from an n8n created credential to see if that works. Just to double check as well, You are not using the same refresh token with anything else right?

I will set up a local instance today to see if I can reproduce this.

Hey @waffles,

So I have given this a test and for me it is working as expected. I used Postman to do my initial auth then copied the tokens it returned to a post request to the API. To test I have had a workflow that does a list on Google Drive running every minute, Checking the decrypted credential using the CLI I can see that the token has been changing as expected.

Data I sent to the API was…

{
    "name": "Google Test Postman Generated token",
    "type": "googleDriveOAuth2Api",
    "data": {
        "clientId": "GOOGLE_CLIENT_ID",
        "clientSecret": "GOOGLE_CLIENT_SECRET",
        "oauthTokenData": {
            "access_token": "ACCESS_TOKEN_FROM_POSTMAN",
            "expires_in": 3599,
            "refresh_token": "REFRESH_TOKEN_FROM_POSTMAN",
            "scope": "https://www.googleapis.com/auth/drive.photos.readonly https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive",
            "token_type": "Bearer",
            "callbackQueryString": {
                "scope": "https://www.googleapis.com/auth/drive.photos.readonly https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive"
            }
        }
    }
}

In Postman to generate the token I used…

Add Auth Data To - Request Headers
Header Prefix - Bearer
Grant Type - Authorization Code
Auth URL - https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent < This is important
Access Token URL - https://oauth2.googleapis.com/token
Client ID - Value from Google
Client Secret - Value from Google
Scope - https://www.googleapis.com/auth/drive.photos.readonly https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive
State - test
Client Authentication - Send Client Credentials in Body

Can you share a bit more on how you are generating your token or the values you are setting so I can try them? I am wondering if maybe when you create your token initially you don’t have the access_type set on the auth url.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.