nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
23.55k stars 3.24k forks source link

OAuthCallbackError on Dropbox #8098

Open wrong7 opened 1 year ago

wrong7 commented 1 year ago

Provider type

Dropbox

Environment

System: OS: Windows 10 10.0.19044 CPU: (12) x64 AMD Ryzen 5 3600 6-Core Processor Memory: 5.36 GB / 15.93 GB Binaries: Node: 18.12.1 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.4 - C:\Program Files (x86)\Yarn\bin\yarn.CMD npm: 9.6.5 - C:\Program Files\nodejs\npm.CMD Browsers: Edge: Spartan (44.19041.1266.0), Chromium (114.0.1823.82) Internet Explorer: 11.0.19041.1566

Reproduction URL

Private

Describe the issue

Whenever I try to log in with the Dropbox provider I get this error:

[next-auth][error][OAUTH_CALLBACK_ERROR] 
https://next-auth.js.org/errors#oauth_callback_error expected 200 OK, got: 404 Not Found {
  error: OPError: expected 200 OK, got: 404 Not Found
      at processResponse (webpack-internal:///(sc_server)/./node_modules/openid-client/lib/helpers/process_response.js:37:15)
      at Client.userinfo (webpack-internal:///(sc_server)/./node_modules/openid-client/lib/client.js:1110:22)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async oAuthCallback (webpack-internal:///(sc_server)/./node_modules/next-auth/core/lib/oauth/callback.js:136:23)
      at async Object.callback (webpack-internal:///(sc_server)/./node_modules/next-auth/core/routes/callback.js:18:79)
      at async AuthHandler (webpack-internal:///(sc_server)/./node_modules/next-auth/core/index.js:202:38)
      at async NextAuthRouteHandler (webpack-internal:///(sc_server)/./node_modules/next-auth/next/index.js:49:30)
      at async NextAuth._args$ (webpack-internal:///(sc_server)/./node_modules/next-auth/next/index.js:83:24)
      at async eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:253:37) {
    name: 'OAuthCallbackError',
    code: undefined
  },
  providerId: 'dropbox',
  message: 'expected 200 OK, got: 404 Not Found'
}

The issue might be on the token URI https://api.dropboxapi.com/oauth2/token which if access with GET method it returns a 404, but with POST it works fine

How to reproduce

Use dropbox provider

Expected behavior

There should not be an error

wrong7 commented 1 year ago

Fixed it with the following settings:

import DropboxProvider from "next-auth/providers/dropbox";
import type { BaseClient } from "openid-client";
import type { TokenEndpointHandler, UserinfoEndpointHandler } from "next-auth/providers";

type DropboxClient = BaseClient & {
  redirect_uris: string[];
}

DropboxProvider({
  clientId: process.env.DROPBOX_CLIENT_ID,
  clientSecret: process.env.DROPBOX_CLIENT_SECRET,
  token: {
    url: "https://api.dropboxapi.com/oauth2/token",
    async request(context) {
      const client: DropboxClient = context.client as DropboxClient;
      const token = context.provider.token as Required<TokenEndpointHandler>

      const res = await fetch(token.url, {
        method: "POST",
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
        },
        body: new URLSearchParams({
          code: context.params.code as string,
          grant_type: "authorization_code",
          code_verifier: context.checks.code_verifier as string,
          client_id: context.provider.clientId as string,
          client_secret: context.provider.clientSecret as string,
          redirect_uri: client.redirect_uris[0],
        }),
      });
      return {
        tokens: await res.json()
      };
    }
  },
  userinfo: {
    url: "https://api.dropboxapi.com/2/users/get_current_account",
    async request({provider, tokens}) {
      const userinfo = provider.userinfo as Required<UserinfoEndpointHandler>;

      const res = await fetch(userinfo.url, {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${tokens.access_token}`,
        }
      });

      return await res.json();
    }
  },
})