在localhost上,Google登录工作得很好。但是在将其部署到Vercel时,成功的Google登录后会话总是空的。我查看了Vercel上的日志,我可以看到会话回调从未在Vercel上执行(仅在localhost上执行)
我还在这里创建了issue和vercel url来复制它:https://github.com/nextauthjs/next-auth/issues/9083
[. nextauth].js:
export const authOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
secret: process.env.NEXTAUTH_SECRET,
jwt: {
secret: process.env.NEXTAUTH_SECRET,
encryption: true,
},
debug: true,
session: {
// Choose how you want to save the user session.
// The default is `"jwt"`, an encrypted JWT (JWE) stored in the session cookie.
// If you use an `adapter` however, we default it to `"database"` instead.
// You can still force a JWT session by explicitly defining `"jwt"`.
// When using `"database"`, the session cookie will only contain a `sessionToken` value,
// which is used to look up the session in the database.
strategy: "jwt",
// Seconds - How long until an idle session expires and is no longer valid.
// 30 days.
// We need to handle if backend returns error which says that token has expired
// and then force logout user.
maxAge: 30 * 24 * 60 * 60,
// Seconds - Throttle how frequently to write to database to extend a session.
// Use it to limit write operations. Set to 0 to always update the database.
// Note: This option is ignored if using JSON Web Tokens
// updateAge: 24 * 60 * 60, // 24 hours
// The session token is usually either a random UUID or string, however if you
// need a more customized session token string, you can define your own generate function.
// generateSessionToken: () => {
// return randomUUID?.() ?? randomBytes(32).toString("hex")
// }
},
callbacks: {
async jwt({ token, user, account }) {
// Persist the user.authToken from signIn callback to the token.authToken
if (account) {
// Handle the Google ID token here
const googleIdToken = account.id_token;
// console.log("nextauth.js jwt: got googleIdToken " + googleIdToken);
// Send the Google ID token to our backend for verification
// and exchange it for our backend's token
// TODO: no way to get locale for now.
const res = await reqGoogleTokenSignIn(null, googleIdToken);
const member = res?.data?.data;
if (member == null) {
console.log(
"nextauth.js jwt reqGoogleTokenSignIn: Failed response from be"
);
return false;
}
console.log(
"nextauth.js jwt reqGoogleTokenSignIn: Received response from be. authToken: " +
member.authToken
);
let newToken = {};
newToken.userId = member.id;
newToken.authToken = member.authToken;
newToken.profilePictureUrl = member.profilePictureUrl;
newToken.fullName = member.fullName;
newToken.emailAddress = member.emailAddress;
newToken.phoneNumber = member.phoneNumber;
console.log("nextauth.js jwt: setting token's userId and authToken");
return newToken;
}
return token;
},
async session({ session, token }) {
// Persist the token.authToken from jwt callback to the session.authToken
console.log(
"nextauth.js session: setting session's userId and authToken"
);
session.userId = token?.userId;
session.authToken = token?.authToken;
session.profilePictureUrl = token?.profilePictureUrl;
session.fullName = token?.fullName;
session.emailAddress = token?.emailAddress;
session.phoneNumber = token?.phoneNumber;
return session;
},
},
};
export default NextAuth(authOptions);
字符串
使用session的组件:
LoginBtn.js
function LoginBtn({ provider }) {
const { data: session, status } = useSession();
const [loggedIn, setLoggedIn] = useState(null);
let loginButton = (
<ImageContainer>
<OptimizedImage
onClick={() => signIn("google", { callbackUrl: "/members/profile" })}
priority={true}
src="/assets/google-login.png"
alt={"Login with Google"}
height={32}
width={82}
/>
</ImageContainer>
);
let profileButton = (
<ImageContainer>
<Link prefetch={false} href={"/members/profile"} legacyBehavior>
<OptimizedImage
priority={true}
src={session?.profilePictureUrl}
alt={session?.emailAddress + " profile image"}
height={25}
width={25}
/>
</Link>
</ImageContainer>
);
useEffect(() => {
if (session == null && status === "loading") {
return;
} else if (session == null && status === "unauthenticated") {
setLoggedIn(false);
return;
} else if (session != null && status === "authenticated") {
setLoggedIn(true);
return;
}
}, [session, status]);
return loggedIn == null ? null : loggedIn ? profileButton : loginButton;
}
export default LoginBtn;
型
从Vercel的日志:我可以看到这两个日志打印:
nextauth.js jwt reqGoogleTokenSignIn:已收到来自be的响应。authToken:Lcoury0Lfl5MRHfRVs6GY280H144=
nextauth.js jwt:设置token的userId和authToken
但是它缺少会话回调的日志,并且没有错误或任何东西。如果我在localhost上运行它,则会打印此日志。
请告诉我localhost和Vercel部署之间有什么不同?
尝试在vercel env var. ADDED NEXTAUTH_URL上添加NEXTAUTH_SECRET(仍然没有区别),然后将其删除,因为文档表明它们是不必要的
启用nextauth调试模式以查看上述日志
1条答案
按热度按时间carvr3hs1#
您是否确保将Google客户端中的回调URL更改为新部署的域?
最好为每个环境创建另一个客户端,以避免每次都手动更改URL。