-
Notifications
You must be signed in to change notification settings - Fork 4k
Description
Environment
System:
OS: Windows 10 10.0.19042
CPU: (4) x64 Intel(R) Xeon(R) CPU E5-2697 v3 @ 2.60GHz
Memory: 9.92 GB / 16.00 GB
Binaries:
Node: 16.14.2 - ~\AppData\Local\Volta\tools\image\node\16.14.2\node.EXE
Yarn: 1.22.18 - ~\AppData\Local\Volta\tools\image\yarn\1.22.18\bin\yarn.CMD
npm: 8.5.0 - ~\AppData\Local\Volta\tools\image\node\16.14.2\npm.CMD
Browsers:
Edge: Spartan (44.19041.1266.0), Chromium (101.0.1210.39)
Internet Explorer: 11.0.19041.1566
npmPackages:
next: ^12.1.5 => 12.1.5
next-auth: ^4.3.3 => 4.3.3
Reproduction URL
unfortunately the code is not public
Describe the issue
Description
Hi there, we are using next-auth with a custom provider (see config below) on a custom node server (like so: #531 (comment)) in order to use next-auth on nextjs static generated pages (SSG). Unfortunately we have to use a custom callback URL pattern in order to get this running which is not working properly. What we tried so far is setting the custom URL as callbackUrl parameter (within the provider config) and handling the redirect stuff (custom callback URL <-> /api/auth/*) on our node server.
Provider config:
export const providerConfig = {
id: "xyz",
name: "XYZ",
type: "oauth",
version: "2.0",
wellKnown: "[...]/.well-known/openid-configuration",
authorization: {
params: {
scope:
"openid profile offline_access customer ACR_Level_10 ACR_Level_20 ACR_Level_30",
code_challenge_method: "S256",
protocol: "oauth2",
access_type: "",
response_type: "code",
// not necessary if options -> callbackUrl is fixed
redirect_uri: `${process.env.NEXTAUTH_URL}/oauth2/callback`,
},
},
clientId: "xyz_id",
checks: ["pkce", "state"],
idToken: true,
client: {
token_endpoint_auth_method: "none",
// see: https://github.com/nextauthjs/next-auth/issues/3559 in order to change expected algorithm
authorization_signed_response_alg: "ES384",
id_token_signed_response_alg: "ES384",
},
options: {
// Dev hint: works only if following library code has changed
// file: /node_modules/next-auth/core/lib/provider.js; line: 23 ff
// move method parameter '...userOptions' to 3rd place
// @ts-ignore
callbackUrl: `${process.env.NEXTAUTH_URL}/oauth2/callback`,
},
profile(profile) {
return {
id: profile.sub,
email: profile.authenEmail,
};
},
};Server.ts (only relevant part)
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
var corsOptions = {
origin: true,
credentials: true
}
app.use(cors(corsOptions));
(async () => {
await server.start();
server.applyMiddleware({ app });
app.use((req, res, next) => {
// Fill in the "nextauth" [catch all route parameter](https://nextjs.org/docs/routing/dynamic-routes#catch-all-routes)
req.query.nextauth = req.url.slice(authBaseUrl.length).replace(/\?.*/, "").split("/");
// @ts-ignore
return NextAuth(req, res, {
providers: [providerConfig],
secret: "...",
debug: true,
});
});
app.listen({ port: 4200 }, () =>
);
})();Error message
After filling out user credentials the generated code verifier and challenge should be validated. But in this case the callbackURL is not the configured one.
[next-auth][error][OAUTH_CALLBACK_ERROR]
https://next-auth.js.org/errors#oauth_callback_error invalid_request (Invalid or missing redirect URI) {
error: {
message: 'invalid_request (Invalid or missing redirect URI)',
stack: 'OPError: invalid_request (Invalid or missing redirect URI)\n' +
' at processResponse (\\node_modules\\openid-client\\lib\\helpers\\process_response.js:38:13)\n' +
' at Client.grant (\\node_modules\\openid-client\\lib\\client.js:1347:22)\n' +
' at processTicksAndRejections (node:internal/process/task_queues:96:5)\n' +
' at async Client.callback (\\node_modules\\openid-client\\lib\\client.js:474:24)\n' +
' at async oAuthCallback (\\node_modules\\next-auth\\core\\lib\\oauth\\callback.js:112:16)\n' +
' at async Object.callback (\\node_modules\\next-auth\\core\\routes\\callback.js:50:11)\n' +
' at async NextAuthHandler (\\node_modules\\next-auth\\core\\index.js:139:28)\n' +
' at async NextAuthNextHandler (\\node_modules\\next-auth\\next\\index.js:21:19)',
name: 'OPError'
},
providerId: '...',
message: 'invalid_request (Invalid or missing redirect URI)'
}
[next-auth][error][CALLBACK_OAUTH_ERROR]
https://next-auth.js.org/errors#callback_oauth_error invalid_request (Invalid or missing redirect URI) OPError: invalid_request (Invalid or missing redirect URI)
at processResponse (\node_modules\openid-client\lib\helpers\process_response.js:38:13)
at Client.grant (\node_modules\openid-client\lib\client.js:1347:22)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Client.callback (\node_modules\openid-client\lib\client.js:474:24)
at async oAuthCallback (\node_modules\next-auth\core\lib\oauth\callback.js:112:16)
at async Object.callback (\node_modules\next-auth\core\routes\callback.js:50:11)
at async NextAuthHandler (\node_modules\next-auth\core\index.js:139:28)
at async NextAuthNextHandler (\node_modules\next-auth\next\index.js:21:19) {
name: 'OAuthCallbackError',
code: undefined
}
The (quick) fix
Setting the callbackURL within the provider config is not working. What I figured out so far is: moving method parameter '...userOptions' to 3rd place within the following next-auth code snippet will keep the configured callbackURL instead of overriding it.
next-auth/packages/next-auth/src/core/lib/providers.ts
Lines 25 to 29 in 2838dd7
| return merge(defaultOptions, { | |
| ...userOptions, | |
| signinUrl: `${url}/signin/${userOptions?.id ?? rest.id}`, | |
| callbackUrl: `${url}/callback/${userOptions?.id ?? rest.id}`, | |
| }) |
How to reproduce
- create node (express) server
- create nextjs/next-auth app (use https://github.com/nextauthjs/next-auth-example), additionally:
- delete api routes
- add basePath to SessionProvider (_app.tsx)
<SessionProvider basePath="http://localhost:4200/api/auth" session={pageProps.session} refetchInterval={0}>
<Layout>
<Component {...pageProps} />
</Layout>
</SessionProvider>
Expected behavior
Correct (configured) callbackURL is added before triggering /api/auth/callback/<idp_id> in order to validate code verifier and challenge. Keep mind that we have to use a certain callbackURL to meet the IDP specification.