next-auth icon indicating copy to clipboard operation
next-auth copied to clipboard

Cannot control redirect_uri when fetching id_token from auth provider

Open renevangsgaardjp opened this issue 2 years ago • 2 comments

Environment

  System:
    OS: Linux 5.15 Ubuntu 22.04 LTS 22.04 LTS (Jammy Jellyfish)
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
    Memory: 11.29 GB / 31.08 GB
    Container: Yes
    Shell: 3.4.0 - /usr/bin/fish
  Binaries:
    Node: 18.3.0 - ~/.local/share/nvm/v18.3.0/bin/node
    npm: 8.11.0 - ~/.local/share/nvm/v18.3.0/bin/npm
  Browsers:
    Chromium: 102.0.5005.61
    Firefox: 101.0
  npmPackages:
    next: 12.1.6 => 12.1.6 
    next-auth: 4.3.4 => 4.3.4 
    react: 18.1.0 => 18.1.0 

Reproduction URL

Not available.

Describe the issue

When next-auth after a successful sign in attempts to fetch an id token from the auth provider, next-auth sends a wrong redirect_uri. And the auth provider response makes next-auth print this in the console:

[next-auth][error][OAUTH_CALLBACK_ERROR] 
https://next-auth.js.org/errors#oauth_callback_error invalid_grant (Incorrect redirect_uri) {
  error: {
    message: 'invalid_grant (Incorrect redirect_uri)',
    stack: 'OPError: invalid_grant (Incorrect redirect_uri)\n' +
      ... clipped ...
    name: 'OPError'
  },
  providerId: 'keycloak',
  message: 'invalid_grant (Incorrect redirect_uri)'
}

My desire is to have one application support multiple domain names. Overwriting callbackUrl at various places does not seem to work, for example overwriting `NextAuth.callbacks.redirect({ ur, baseUrl }) does not fix anything.

I have managed to overwrite the redirect_uri used when performing the sign in like this:

signIn("keycloak", undefined, {
  // Make sure to overwrite the redirect_uri.
  redirect_uri: `https://${host}/api/auth/callback/keycloak`,
})

But when next-auth wants to fetch the corresponding id token, the auth provider refuses as a wrong redirect_uri is passed to it.

Looking at https://github.com/nextauthjs/next-auth/blob/e4ee520b4aba55fbc123801291bcba404f578d3f/packages/next-auth/src/core/lib/oauth/callback.ts#L113 it seem that it always uses the value of provider.callbackUrl.

How to reproduce

Not available.

Expected behavior

Use the callbackUrl/redirect_uri that was used when performing sign in.

renevangsgaardjp avatar Jun 03 '22 11:06 renevangsgaardjp

Yep, I'm also experiencing this which means I can't really use the Rest API :/

I wonder if we could just:

import oAuthCallback from "next-auth/core/lib/oauth/callback";

And pass the required values ourselves? I can't seem to find the InternalOptions interface though so I have no clue how this would be shaped 😂

Edit: Nevermind. VSCode doesn't complain on import but Next doesn't like it. image

leo-petrucci avatar Jun 27 '22 10:06 leo-petrucci

I've got a fix! At least for my usecase.

So, for a while I thought (like you) that the key to getting this to work was through Next Auth, but it turns out we were both looking in the wrong place all along.

The secret for me was actually in the provider's setup. Twitter 2.0 may not have a redirect_uri option, but it does have a token property:

https://github.com/nextauthjs/next-auth/blob/e4ee520b4aba55fbc123801291bcba404f578d3f/packages/next-auth/src/providers/twitter.ts#L182-L194

This token property is a function which tells Next Auth how to fetch the token for the specific provider, so all I had to do was change my provider's configuration so that it would redirect to my own page:

    TwitterProvider({
      clientId: process.env.TWITTER_CLIENT_ID!,
      clientSecret: process.env.TWITTER_CLIENT_SECRET!,
      version: "2.0", // opt-in to Twitter OAuth 2.0,
      token: {
        url: "https://api.twitter.com/2/oauth2/token",

        async request({ client, params, checks }) {
          const response = await client.oauthCallback(
            "http://localhost:3000/custom-callback",
            params,
            checks,
            {
              exchangeBody: {
                client_id: process.env.TWITTER_CLIENT_ID,
              },
            }
          );
          return {
            tokens: response,
          };
        },
      },
    }),

You cannot even imagine how long I've been stuck on this issue, I think I tried getting this to work last year 😂 Let me know if this is helpful.

@balazsorban44 I think this would be super useful to have in the docs, I also think this may make Next Auth finally usable with native oauth clients.

Would you accept a PR to add this info?

Edit: This allows native clients to use the in-app browser to login, I've just tested it 😁

leo-petrucci avatar Jun 27 '22 14:06 leo-petrucci

I had a similiar issue and fixed it by specifiying the NEXTAUTH_URL with the proper base domain like https://example.org. This properly reformatted the callback url to my expected host.

DracoBlue avatar Nov 02 '22 10:11 DracoBlue