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

Next Auth [v5.0.0-beta.4] Middleware and Scope not working

Open siinghd opened this issue 2 years ago • 7 comments

Environment

System: OS: Windows 11 10.0.22621 CPU: (8) x64 Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz Memory: 2.78 GB / 11.92 GB Binaries: Node: 18.18.2 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD npm: 10.2.5 - C:\Program Files\nodejs\npm.CMD pnpm: 8.10.3 - C:\Program Files\nodejs\pnpm.CMD Browsers: Edge: Chromium (120.0.2210.77) Internet Explorer: 11.0.22621.1 npmPackages: @auth/core: ^0.19.0 => 0.19.0 @auth/prisma-adapter: ^1.0.12 => 1.0.12 next: 14.0.4 => 14.0.4 next-auth: 5.0.0-beta.4 => 5.0.0-beta.4 react: ^18.2.0 => 18.2.0

Reproduction URL

https://github.com/siinghd/question-tracker

Describe the issue

I am using the NextAuth beta to implement a login feature using the Discord provider and Prisma adapter. I am encountering two primary issues:

Issue 1: Scope Not Working as Expected

The specified scope in auth.config.ts doesn't seem to be applied. Instead, the default scope is used. Here's the relevant code snippet:

const scopes = ['identify', 'guilds'];
export default {
  providers: [
    DiscordProvider({
      clientId: process.env.DISCORD_CLIENT_ID || '',
      clientSecret: process.env.DISCORD_CLIENT_SECRET || '',
      authorization: { params: { scope: scopes.join(' ') } },
    }),
  ],
};

Issue 2: Middleware Not Redirecting Properly

The middleware intended to protect the root path / and redirect unauthenticated users to /login is not functioning as expected. The .env file includes AUTH_SECRET and AUTH_URL.

How to reproduce

  1. Set up the NextAuth configuration with the Discord provider and Prisma adapter.
  2. Define scopes as ['identify', 'guilds'].
  3. Implement middleware to protect the root path and redirect to /login.
  4. Observe that the specified scopes are not applied and the middleware does not redirect as intended.

Expected behavior

  1. The Discord authentication should use the specified scopes (identify, guilds).
  2. Unauthenticated users trying to access the root path should be redirected to the /login page.

Actual Behavior:

  1. The default scope is used instead of the specified custom scopes.
  2. The middleware does not redirect unauthenticated users to /login.

siinghd avatar Dec 22 '23 18:12 siinghd

Update:

fixed the middleware problem by using:

 authorized({ auth, request: { nextUrl } }) {
      const isLoggedIn = !!auth?.user;

      const unprotectedPaths = ['/login'];

      const isProtected = !unprotectedPaths.some((path) =>
        nextUrl.pathname.startsWith(path)
      );

      if (isProtected && !isLoggedIn) {
        const redirectUrl = new URL('api/auth/signin', nextUrl.origin);
        redirectUrl.searchParams.append('callbackUrl', nextUrl.href);
        return Response.redirect(redirectUrl);
      }

      return true;
    },

The scope one still remains

siinghd avatar Dec 23 '23 01:12 siinghd

Update 2:

Solved the scope issue by doing

await signIn('discord', {}, 'scope=identify guilds');

I do not know if this is the correct way to do it but seems working.

Let me know if this is ok or not.

siinghd avatar Dec 23 '23 01:12 siinghd

It's great to see you here, @siinghd. Would it be alright if I share an issue I'm experiencing with the next-auth beta version? Specifically, the auth() function doesn't seem to be working in pages routers, even when I pass req and res as arguments. Interestingly, it works fine in the app router, but I have a dependency on pages routers and need to use auth() there. Any insights or assistance would be appreciated.

me-imfhd avatar Dec 23 '23 08:12 me-imfhd

Update: The issue has already been raised here, my apologies. https://github.com/nextauthjs/next-auth/issues/9307

me-imfhd avatar Dec 23 '23 08:12 me-imfhd

@siinghd

I used this method:

providers: [
    DiscordProvider({
      clientId: process.env.DISCORD_CLIENT_ID as string,
      clientSecret: process.env.DISCORD_CLIENT_SECRET as string,
      authorization: "https://discord.com/api/oauth2/authorize?scope=identify+guilds+guilds.members.read",

Checked the discordProvider in 5.0.0-beta.4 image

Just seems to take authorization as this string. Don't know how it should be passed. Many unofficial examples show the params: { scope: ... } way. At least in discord provider's case.

rikurainio avatar Dec 29 '23 06:12 rikurainio

The provided code should work. Likely a bug in our merging of the default config with the user provided one:

https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/lib/utils/providers.ts

https://github.com/nextauthjs/next-auth/blob/d85269d1169d068448b831d2ee9517e4673c78b8/packages/core/src/providers/discord.ts#L143

balazsorban44 avatar Jan 25 '24 02:01 balazsorban44

Reviving this old issue because I may have found the source of the bug: merge assumes that arg target is always an object.

Attempting to override this authorization default fails: example provider

The merge function in question: function

  1. merge gets called recursively if source[key] is an object
  2. But if the target value for that key is NOT an object, merge skips the override silently and returns the default. (if condition checks isObject(target) but target[key] is technically any, potentially ignoring supplied config for merging)

The Spotify provider above provides a string default for authorization, so it will not be overridden even if a config is provided as specified in the docs.

Possible solutions:

  1. Any provider that allows configuration must have fixes like #9866 to expose the desired values for overriding via a config object. I.e. provider default values must be objects to support deep merge, not strings or otherwise
  2. Mark this is as intentional? Any non-object default values are not supposed to be overridden by config supplied to provider function?
  3. Take a look at merge so it can override any default

nic-vo avatar Jun 22 '24 07:06 nic-vo