-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Yandex provider + Adaptor issue (invalid_grant(code has expired)) #11611
Comments
The same problem with Yandex provider. Terminal output:
Also, sometimes there is an error with PKCE verification, but authorization occurs. Quite unstable provider.
Environment
|
I spent about a week troubleshooting this error, and the only workable solution I’ve found so far involves opening a second tab. However, I'm not satisfied with this workaround. It would be great if the next-auth developers could consider supporting an OAuth flow similar to the one used by the Yandex provider. The issue originates from the line in the signIn function from
To investigate further, you can insert a process.exit() command right before this line and log the URL for different providers (I tested with Google, GitHub, and Yandex). Then, in your browser's console, manually click on the URI. The behavior for Yandex differs from the others. It likely needs something like
Regarding your second issue related to PKCE, you shouldn’t encounter this error if you haven't modified the default settings for the Yandex provider. Yandex defaults to using checks='state', so perhaps this parameter was changed (by you). Although I haven't extensively used it, even with the |
I will continue to add different approachs I found in the repository which is attached to this issue (reproduction url). I hope that next-auth developers will answer. Maybe I missed something and the error can be solved straightforward. |
The first approach is not acceptable (second tab) because it looks strange relative to the Google or GitHub. I will write second approach. I would like to read your thoughts. Is it acceptable approach? For my local and prod this works fine for now.
Yandex({
clientId: process.env.YANDEX_CLIENT_ID!,
clientSecret: process.env.YANDEX_CLIENT_SECRET!,
authorization:{
params:{
redirect_uri:`${process.env.NEXTAUTH_URL}/api/customYandex`
},
},
allowDangerousEmailAccountLinking: true,
httpOptions: {
timeout: 10000,
},
}), In openIDClient library there is by default written 10 sec. So maybe there is no need to write
import {NextRequest, NextResponse } from "next/server";
import { cookies } from 'next/headers';
export async function GET(req : NextRequest) {
const url = new URL(req.url);
console.log('URL', url)
const code = url.searchParams.get('code');
const cid = url.searchParams.get('cid');
const state = url.searchParams.get('state');
const redirectUrl = ${process.env.NEXTAUTH_URL}/api/auth/callback/yandex?code=${code}&cid=${cid}&state=${state};
return NextResponse.redirect(redirectUrl);
} we get two consols and the error `invalid_grant (code has expired).
import {NextRequest, NextResponse } from "next/server";
import { cookies } from 'next/headers';
export async function GET(req : NextRequest) {
const url = new URL(req.url);
const code = url.searchParams.get('code');
const cid = url.searchParams.get('cid');
const state = url.searchParams.get('state');
const cookieStore = cookies();
const firstRequestReceived = cookieStore.get('yandex_oauth_first_received');
if (!firstRequestReceived) {
cookieStore.set('yandex_oauth_first_received', 'true', {
maxAge: 15,
path: '/api/customYandex',
});
return new Response(null, { status: 204 });
}
cookieStore.set('yandex_oauth_first_received', 'false', {
maxAge: -1,
path: '/api/customYandex',
});
const redirectUrl = ${process.env.NEXTAUTH_URL}/api/auth/callback/yandex?code=${code}&cid=${cid}&state=${state};
return NextResponse.redirect(redirectUrl);
} What do you think about it? What problem can arise from this approach? |
The approach above works. But 1 of 20 attempts failed. I noted that it is enough to set timer like this: import { NextResponse } from "next/server";
export async function GET(req) {
const url = new URL(req.url);
const code = url.searchParams.get('code');
const cid = url.searchParams.get('cid');
await new Promise(resolve => setTimeout(resolve, 5000));
const redirectUrl = `http://localhost:3000/api/auth/callback/yandex?code=${code}&cid=${cid}`;
return NextResponse.redirect(redirectUrl);
} |
Thanks for this workaround, it's worked for me. But I noticed that the described problem only occurs when the app starts "cold" (e.g. right after I run next dev and there is no cache for components). Experimentally, I found out that a 3 seconds timeout is enough for me. |
Provider type
Yandex
Environment
Reproduction URL
https://github.com/KhekhaevSalekh/next-auth-Yandex-issue
Describe the issue
When I use Yandex provider with next-auth all goes well. But when I connect hasura adapter i get error.
The error I get is (invalid_grant(code has expired)).
When a new user presses "Sign in" by Yandex he does not go to home page. He appears at sign-in page. Also there is not next-auth.session-token coockie.
In the same time all necessary information is written in the database.
When he presses "Sign in" by Yandex second time he is on the home page.
With Google and GitHub authorization everything is good.
I have checked this behavior on vercel and locally.
How to reproduce
Just start project from Reproduction URL and try to sighin with yandex.
Expected behavior
Normal sign in flow without this error.
The text was updated successfully, but these errors were encountered: