我有一个带有 Next Auth 的私人下一个项目,并且我正在实施仅凭据电子邮件和密码,因为这些用户将在 Firebase Auth 面板中创建。我的下一个身份验证看起来像这样:
import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import { auth, app } from '@/util/firebase';
import { signInWithEmailAndPassword } from 'firebase/auth';
export default NextAuth({
secret: process.env.NEXTAUTH_SECRET,
pages: {
signIn: '/auth/signin',
},
providers: [
CredentialsProvider({
name: 'Credentials',
credentials: {
email: { label: 'Email', type: 'email' },
password: { label: 'Password', type: 'password' },
},
async authorize(credentials, req) {
try {
const userCredential = await signInWithEmailAndPassword(
auth,
credentials.email,
credentials.password
);
// I want to get this token and save as Bearer Authorization token userCredential.idToken
if (userCredential.user) return { email: userCredential.user.email };
else return null;
} catch (error) {
throw new Error('Invalid email or password');
}
},
}),
],
});
但是有一个小问题。对于请求 API,我需要发送有效的 Bearer 令牌。如何存储和检索令牌?
观察:代币可用于
userCredential.idToken
next-auth 的目的是将用户数据存储在受保护的会话中
因此,首先您必须从
authorize
方法返回要在会话中存储的内容:
async authorize(credentials, req) {
//...
if (userCredential) {
return {
email: userCredential.user.email,
accessToken: userCredential.idToken
//... any other keys you want to include in the returned object
}
}
else return null;
} catch (error) {
throw new Error("Invalid email or password");
}
}
接下来您需要将这些数据存储在会话中,为此,您必须使用回调:
JWT回调
每当创建 JSON Web 令牌(即登录时)或更新(即每当在客户端中访问会话时)都会调用此回调。返回值将被加密,并存储在 cookie 中。
会话回调
每当检查会话时都会调用会话回调。默认情况下,仅返回令牌的子集以提高安全性。如果您想让通过 jwt() 回调添加到令牌的某些内容(例如上面的 access_token 和 user.id)可用,您必须在此处显式转发它以使其可供客户端使用。
很可能,
authorize
方法返回的对象可用作 jwt 回调中名为 user
的参数,因此您可以利用后者来更新令牌并返回它token
的参数使用,因此您再次使用此令牌来更新会话
callbacks: {
async jwt({ user, token }) {
// update token if user is returned
if (user) {
token.email = user.email;
token.accessToken= user.accessToken;
}
// return final_token
return token;
},
async session({ session, token}) {
// update session from token
session.email = token.email;
session.accessToken= token.accessToken;
return session;
},
},
您现在的会话包含您想要存储的信息。
因此,从客户端您可以使用 useSession()
访问它import { useSession } from "next-auth/react";
const Home = () => {
const session = useSession();
const myAccessToken = session.data.accessToken;
//...
}
另请参阅 getServerSession()
用户的 accessToken 属性是否应该存储在数据库中?或者它是在回调时生成的?