Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@clerk/clerk-sdk-node ClerkAPIResponseError: Unprocessable Entity - getUserOauthAccessToken google #1827

Closed
4 tasks done
AlonMiz opened this issue Oct 4, 2023 · 16 comments
Closed
4 tasks done
Labels
linear Created by Linear-GitHub Sync needs-reproduction Awaiting a minimal reproduction Stale

Comments

@AlonMiz
Copy link

AlonMiz commented Oct 4, 2023

Description

Steps to reproduce:

  1. Authorize user with Google and a gmail.send,gmail.readonly scopes
  2. refresh the browser or wait a few hours
  3. use server-side clerk.users.getUserOauthAccessToken(userId, 'oauth_google');
  4. getting ClerkAPIResponseError: Unprocessable Entity error
  • When using the method right after the authentication with Google, everything works fine

Expected behavior:

I would expect the code not to throw and be able to get the OAuth token, even when the last token is expired, using the refresh token it fetched in the initial authentication

Actual behavior:

The getUserOauthAccessToken mechanism seems not to handle situation when it needs to refresh the OAuth token

image

Publishable key

pk_test_cHJvcGVyLXNwYXJyb3ctNDkuY2xlcmsuYWNjb3VudHMuZGV2JA

Environment

System:
    OS: macOS 13.5.2
    CPU: (8) arm64 Apple M1 Pro
    Memory: 70.92 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.16.0 - ~/.volta/tools/image/node/18.16.0/bin/node
    Yarn: 1.22.18 - ~/.volta/tools/image/yarn/1.22.18/bin/yarn
    npm: 9.5.1 - ~/.volta/tools/image/node/18.16.0/bin/npm
    pnpm: 8.5.0 - ~/Library/pnpm/pnpm
  Browsers:
    Brave Browser: 106.1.44.105
    Chrome: 117.0.5938.132
    Safari: 16.6
  npmPackages:
    @clerk/clerk-sdk-node: ^4.12.6 => 4.12.6 
    @clerk/nextjs: ^4.24.0 => 4.24.0 
    @clerk/themes: ^1.7.6 => 1.7.6 

Preliminary Checks

Reproduction / Replay Link

its pretty hard - if there's no other choice ill try to create one

@AlonMiz AlonMiz added the needs-triage A ticket that needs to be triaged by a team member label Oct 4, 2023
@jescalan jescalan added the needs-reproduction Awaiting a minimal reproduction label Oct 16, 2023
@jescalan
Copy link
Contributor

We do indeed need a reproduction in order to handle this one 🙏

@jescalan jescalan removed the needs-triage A ticket that needs to be triaged by a team member label Oct 16, 2023
@LekoArts LekoArts added the linear Created by Linear-GitHub Sync label Oct 16, 2023
@statico
Copy link

statico commented Oct 20, 2023

I'm still trying to find a reproduction here, but we noticed Clerk auth acting strangely in our React Native / Expo app starting a week ago, and we haven't updated our app in over two weeks. It might be this. I'll report back.

@clerk-cookie
Copy link
Collaborator

Hello 👋

We currently close issues after 40 days of inactivity. It's been 30 days since the last update here. If we missed this issue, please reply here. Otherwise, we'll close this issue in 10 days.

As a friendly reminder: The best way to see an issue fixed is to open a pull request. If you're not sure how to do that, please check out our contributing guide.

Thanks for being a part of the Clerk community! 🙏

@clerk-cookie
Copy link
Collaborator

Hello again 👋

After 40 days of no activity, we'll close this issue. Keep in mind, I'm just a robot, so if I've closed this issue in error, please reply here and my human colleagues will reopen it.

As a friendly reminder: The best way to see an issue fixed is to open a pull request. If you're not sure how to do that, please check out our contributing guide.

Thanks for being a part of the Clerk community! 🙏

@clerk-cookie clerk-cookie closed this as not planned Won't fix, can't repro, duplicate, stale Nov 30, 2023
@thecrayon
Copy link

thecrayon commented Jun 19, 2024

@AlonMiz did you find a solution to this? I have the exact same issue as you: 1) User signs into app for first time. 2) User signs out and remains signed out for > 1 hour. 3) I go to fetch the oauth token (from server side). 4) I get the same error message as you.

Getting the access token works well when the user was recently signed in, but not if the user has been signed out for >1 hour. It's fine if I have to manage the user's refresh tokens, but I don't think the Clerk api returns the user's refresh token when the user first authenticates.

Per Clerk's documentation here Clerk says "Clerk ensures that the OAuth Access Token will be always fresh so that you don't have to worry about OAuth Refresh Tokens anymore." This doesn't appear to be the case for Google Oauth

@AlonMiz
Copy link
Author

AlonMiz commented Jun 21, 2024

@thecrayon
actually, eventually, it stopped happening... might be a version or something (I moved to clerk core v2)

@jnimmo
Copy link

jnimmo commented Oct 9, 2024

I've just started running into this issue too. For further context, I'm calling the function inside a cached server action.
I did some optimisations yesterday where I removed a bunch of unnecessary const user = await currentUser() statements, and I wonder whether that could be impacting it. I've added them back in just to see if it reduces the frequency of the problem.

export const getReports = cache(async (propertyId: string, reportId: string): Promise<ReportData> => {
const { userId } = auth();
  if (!userId) {
    throw new Error(`Authentication error`);
  }
  const clerkToken = await clerkClient().users.getUserOauthAccessToken(userId, provider);
})

I've also just noted the header has changed to
const { data, totalCount } = await clerkClient().users.getUserOauthAccessToken(userId, provider);
so I have also just switched to this to see if it helps.

@muratg98
Copy link

hey has anyone got an update on this issue? the refresh token is not automatically refreshing the access token (im using google oauth). The code again works if I log out and log in again (probably because the access token resets), however why is the refresh token not automatically refreshing the access token as outlined in the documentation? Is it to do with the fact that im in dev mode still and can it fix in production? for reference: _ClerkAPIResponseError: Unprocessable Entity errors: [ { code: 'oauth_missing_refresh_token', message: 'Cannot refresh OAuth access token', longMessage: "The current access token has expired and we cannot refresh it, because the authorization server hasn't provided us with a refresh token", meta: [Object] } ]

@jnimmo
Copy link

jnimmo commented Oct 25, 2024

@muratg98 can you advise what Clerk hooks you’re calling prior to requesting the OAuth token?
In my case this started to show up when I switched away from using auth().protect() prior to requesting the token.

The ticket is closed but if we can figure out how to reliably reproduce we should log a new one.

@thecrayon
Copy link

thecrayon commented Oct 25, 2024

@muratg98 I actually swapped out Clerk for Next Auth- I never got this to work in Clerk. Using Next Auth, I find managing the access/refresh tokens to be much easier (you can clearly see error messages and you have much more control over the user authentication in general... the downside is you have to setup a lot more infrastructure with Next Auth to do this). However, It definitely could be because your app is in development mode though. Would not surprise me. Clerk dev mode was buggy and they would release breaking changes that took a while to debug.

@goldsolace
Copy link

@muratg98 I'm also running into this issue. Using Google OAuth like the other's who have experienced this. The token isn't getting refreshed and after an hour calling getUserOauthAccessToken causes throws the following error.

errors: [ { code: 'oauth_missing_refresh_token', message: 'Cannot refresh OAuth access token', longMessage: "The current access token has expired and we cannot refresh it, because the authorization server hasn't provided us with a refresh token", meta: [Object] } ]

Happens both in Dev and Prod environments.

@jnimmo
Copy link

jnimmo commented Nov 19, 2024

@muratg98 I'm also running into this issue. Using Google OAuth like the other's who have experienced this. The token isn't getting refreshed and after an hour calling getUserOauthAccessToken causes throws the following error.

errors: [ { code: 'oauth_missing_refresh_token', message: 'Cannot refresh OAuth access token', longMessage: "The current access token has expired and we cannot refresh it, because the authorization server hasn't provided us with a refresh token", meta: [Object] } ]

Happens both in Dev and Prod environments.

The problem is due to the same OAuth application being used for Clerk Dev and Prod environments; the refresh token is only provided to whichever Clerk environment authenticates an account first.
The solution is to ensure you use two separate projects in Google Cloud, one for Clerk Dev and one for Clerk Prod.

@sergesteban
Copy link

@muratg98 I'm also running into this issue. Using Google OAuth like the other's who have experienced this. The token isn't getting refreshed and after an hour calling getUserOauthAccessToken causes throws the following error.
errors: [ { code: 'oauth_missing_refresh_token', message: 'Cannot refresh OAuth access token', longMessage: "The current access token has expired and we cannot refresh it, because the authorization server hasn't provided us with a refresh token", meta: [Object] } ]
Happens both in Dev and Prod environments.

The problem is due to the same OAuth application being used for Clerk Dev and Prod environments; the refresh token is only provided to whichever Clerk environment authenticates an account first. The solution is to ensure you use two separate projects in Google Cloud, one for Clerk Dev and one for Clerk Prod.

oh wow, i just got into the same issue
thanks for the hint @jnimmo

@jescalan
Copy link
Contributor

This is correct - also we are tracking this specific issue and looking to get a fix implemented internally so this wouldn't be the case anymore, in case that is helpful

@sergesteban
Copy link

just for the record, it happens when using python lib, and clerk api
print(f'user_id: {user_id}') print(f'provider: {provider}') print(f'clerk_api_key: {clerk_api_key}') url = f"https://api.clerk.com/v1/users/{user_id}/oauth_access_tokens/{provider}" headers = {"Authorization": f"Bearer {clerk_api_key}"} response = requests.get(url, headers=headers) print(f'Response: {response.json()}')

response:
Response: {'errors': [{'message': 'Cannot refresh OAuth access token', 'long_message': "The current access token has expired and we cannot refresh it, because the authorization server hasn't provided us with a refresh token", 'code': 'oauth_missing_refresh_token'}], 'clerk_trace_id': '1b224db015e456bf624e4e2d1b3f2860'}

@LauraBeatris
Copy link
Member

Hey everyone, I'm a Software Engineer from @clerk SDK team 👋

The refresh_token is only provided by Google during the initial user authorization. Subsequent authorizations, like those made while testing an OAuth2 integration, will not return the refresh_token again, and therefore calls to getUserOauthAccessToken end up failing.

Clerk will handle these cases, so you won't need to manage Identity Provider-specific behaviors. We will soon implement an API change that redirects users to Google for consent again if a refresh token is missing, requiring no action on your part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
linear Created by Linear-GitHub Sync needs-reproduction Awaiting a minimal reproduction Stale
Projects
None yet
Development

No branches or pull requests