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

Bug: OAuth Callback Authorization Error on Sign-in #235

Closed
jacksonkasi1 opened this issue Apr 17, 2024 · 7 comments
Closed

Bug: OAuth Callback Authorization Error on Sign-in #235

jacksonkasi1 opened this issue Apr 17, 2024 · 7 comments
Labels

Comments

@jacksonkasi1
Copy link

Describe the bug

Description

I encountered an authorization error when attempting to sign into Badget.io using OAuth. The callback URL returned an "Unauthorized request" error, preventing login.

Steps to Reproduce

  1. Navigate to Badget.io and initiate the sign-in process.
  2. Complete the OAuth consent screen.
  3. Encounter the error on the callback.

Expected Behavior

The OAuth process should complete successfully, and I should be logged into the system.

Actual Behavior

An error message is displayed stating "Unauthorized request," and I am unable to log in.

Error Messages

  • Message: Unauthorized request
  • Long Message: You are not authorized to perform this request
  • Error Code: authorization_invalid

Additional Information

  • Clerk Trace ID: 0a6219171a2a41f6758823ff34ca2436

Screenshots

image
image

Steps to reproduce

Steps to Reproduce

  1. Attempt to log in via Google OAuth on Badget.io.

Browsers

Chrome

Additional context (Is this in dev or production?)

production

@Codehagen
Copy link
Owner

Thanks for this @jacksonkasi1 - Going to look into it.

@encryptedcommerce
Copy link

encryptedcommerce commented Jan 3, 2025

I'm curious if/how this issue was resolved because I'm running into a similar issue for an Electron desktop app that wraps an existing web app.

The existing web app has been working in production. I have implemented custom protocol routing to an internal server via HTTP, and updated allowed_origins. I can authenticate to Clerk (environment and client endpoints return 200), but after Google SSO the oauth_callback has the same behavior as OP.

In staging environment, it works. In production environment, it doesn't. Is this due to some differences between the environments? The configuration is very similar, but maybe there's stricter security policies in production preventing the Electron app from working?

@mboudreau
Copy link

@encryptedcommerce take a look at this repo we created to show how we did it with electron and clerk :)
https://github.com/gameglass/clerk-electron-login/

@UtsavChokshiCNU
Copy link

@mboudreau ... Can you help with setting these env variables mentioned in your repo : https://github.com/gameglass/clerk-electron-login/

This is what are are using, consider that xyz is our org name.

VITE_CLERK_PUBLIC_KEY="pk_xxx"
VITE_CLERK_DOMAIN=clerk.xyz.ai
VITE_HTTPS_DOMAIN=https://local.hub.electron.vite
VITE_APP_DOMAIN=https://xyz.ai
VITE_DOMAIN=http://localhost:5173
VITE_CLERK_DEV_DOMAIN=guiding-mosquito-xx.clerk.accounts.dev

We are able to run the repo but authentication with google still does not work. Can you guide ?

Please note that : https://local.hub.electron.vite/sso-callback has been added as redirect URL using clerk's API.

This is error we receive :

{"errors": ["message": "Unauthorized request", "long_message":"You are not authorized to perform this
request", "code" :"authorization_invalid"}],"clerk_trace_id"="xxxx"}

Essentially, oauth_callback always fails.

@mboudreau
Copy link

@UtsavChokshiCNU It's important to use the custom clerk provider with the custom clerk instance to inject _is_native=1 in the query string to do the native flow. It's also required to intecept the web data to remove the origin mentioned here: https://github.com/GameGlass/clerk-electron-login/blob/main/src/main/index.ts#L136

The way we're doing it is nothing special. It is literally just taking what Clerk has done for Expo/React Native and porting it to electron. The code we based it on is this: https://github.com/clerk/javascript/blob/2659108ed55d558c656d184d4113873b28e86441/packages/expo/src/hooks/useOAuth.ts#L36

However, we did find another way of doing this is a much more centralized way. You could use a website (if you have one) to go through the oauth flow, and after the flow is done, take the userid and create a Sign In Token and then use that to deeplink back to your electron application (ex: myapp://some-domain/sso-token?signInToken=<insert token here> which your app then uses this sign in token to login.

Best of luck getting it working. Cheers.

@UtsavChokshiCNU
Copy link

UtsavChokshiCNU commented Jan 18, 2025

@mboudreau ... Sorry to bother you again. We were able to implement the following flow :

However, we did find another way of doing this is a much more centralized way. You could use a website (if you have one) to go through the oauth flow, and after the flow is done, take the userid and create a [Sign In Token](https://clerk.com/docs/custom-flows/embedded-email-links) and then use that to deeplink back to your electron application (ex: myapp://some-domain/sso-token?signInToken=<insert token here> which your app then uses this sign in token to login.

Login on the Desktop App (e.g., the Electron App) worked, but it is not able to refresh the token. So, I wanted to know how you have handled that.

In particular, request to touch (e.g. https:/clerk.myapp.com/v1/client/sessions/session_id/touch?__clerk_api_version=2024-10-01&_clerk_js_version=5.45.0) and /tokens endpoints kept failing with 401 unauthorized. As soon as this fails, clerk signs us out from the app.

Here is the Sequence Diagram for your reference :

sequenceDiagram
    participant User
    participant Desktop as Desktop App
    participant WebApp as Web Frontend
    participant Backend as Python Backend
    participant Clerk as Clerk Auth

    Desktop->>Desktop: 1. Register myapp:// protocol
    User->>Desktop: 2. Launch desktop app
    User->>Desktop: 3. Click "Continue with Google"
    Desktop->>WebApp: 4. Open /desktop-auth
    WebApp->>Clerk: 5. Check session status
    Clerk->>WebApp: 6. No session found
    WebApp->>Clerk: 7. Start Google OAuth flow
    Clerk->>User: 8. Show Google sign-in popup
    User->>Clerk: 9. Complete Google sign-in
    Clerk->>WebApp: 10. OAuth Success
    WebApp->>WebApp: 11. Redirect to /desktop-auth-session-generator
    WebApp->>Backend: 12. Request sign-in token
    Backend->>WebApp: 13. Return token
    WebApp->>Desktop: 14. Redirect myapp://auth?signin-token=xyz
    Desktop->>Desktop: 15. Create session with token
    
    Note over Desktop,Clerk: Session Token Refresh Flow (Continuous)
    loop Every 50 seconds
        Desktop->>Clerk: Request new session token
        Clerk->>Desktop: Return fresh token (60s validity)
    end
Loading

Please note that our electron app's main process starts the express server (on localhost:3000) to render UI. All clerk request originates from that express server.
So I believe , production instance of clerk (clerk.myapp.com) does not allow refreshing token from localhost:3000. I want to know how you have mitigated that ?

Here are things we already tried (and failed):

  1. Add localhost:3000 as allowed origins on clerk instance
  2. Update request and response headers for origin and referrer to use webapp URL rather than localhost:3000.

Your guidance is much appreciated !

@mboudreau
Copy link

@UtsavChokshiCNU Hey mate,

We actually didn't implement this flow for our desktop app yet, we're using the example at the github repo given for the time being as it's working and haven't tried this flow yet other than with our mobile app.

That being said, you should look at our web request interceptors example for clerk APIs in this file. The thing about Clerk is that authentication is done one of 2 ways: with cookies based on origin headers (browser based) or using the Authorization header and giving it the user JWT (native). The latter must have the origin header removed for it to work - you can't have both authorization and origin headers at the same time. Secondly, you'll also need to intercept the response headers so you can add the CORS headers necessary to inject your localhost domain that goes to the electron "browser" window so that V8 doesn't kick up a fuss.

And that should do it :)

For any other support requests, please contact clerk directly - they're really responsive, especially on slack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants