Next Auth [v5.0.0-beta.4] Middleware and Scope not working
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
- Set up the NextAuth configuration with the Discord provider and Prisma adapter.
- Define scopes as
['identify', 'guilds']. - Implement middleware to protect the root path and redirect to
/login. - Observe that the specified scopes are not applied and the middleware does not redirect as intended.
Expected behavior
- The Discord authentication should use the specified scopes (
identify,guilds). - Unauthenticated users trying to access the root path should be redirected to the
/loginpage.
Actual Behavior:
- The default scope is used instead of the specified custom scopes.
- The middleware does not redirect unauthenticated users to
/login.
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
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.
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.
Update: The issue has already been raised here, my apologies. https://github.com/nextauthjs/next-auth/issues/9307
@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
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.
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
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
authorization default fails:
The in question:
mergegets called recursively ifsource[key]is an object- But if the
targetvalue for thatkeyis NOT an object,mergeskips the override silently and returns the default. (ifcondition checksisObject(target)buttarget[key]is technicallyany, 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 .
Possible solutions:
- 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
- Mark this is as intentional? Any non-object default values are not supposed to be overridden by config supplied to provider function?
- Take a look at
mergeso it can override any default