我正在使用 next-auth v4 使用 CognitoProvider 实现基于角色的身份验证,我修改了它以添加角色,但角色属性未在最终会话 json 中传递
import NextAuth from "next-auth/next";
function CognitoProvider(options) {
return {
id: "cognito",
name: "Cognito",
type: "oauth",
wellKnown: `${options.issuer}/.well-known/openid-configuration`,
idToken: true,
profile(profile) {
console.log(profile);
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: profile.picture,
role: profile["cognito:groups"],
};
},
options,
};
}
export default NextAuth({
providers: [
CognitoProvider({
clientId: process.env.COGNITO_CLIENT_ID,
clientSecret: process.env.COGNITO_CLIENT_SECRET,
issuer: process.env.COGNITO_DOAMIN,
}),
],
callbacks: {
session: (props) => {
console.log(props);
return props.session;
},
},
});
role: profile["cognito:groups"]
我已将一个用户添加到管理组,并希望他访问我的 NextJS 应用程序中的特定路由。
如有任何帮助,我们将不胜感激。
jwt
和 session
回调以在会话中包含更多数据。
来自 Next-Auth 文档:
如果您想让通过
回调添加到令牌 [...] 的某些内容可用,您必须在此处显式转发它 [jwt()
回调],以使其可供客户端使用。session()
添加用户角色:
export default NextAuth({
// ...
callbacks: {
jwt({ token, account, profile }) {
if (account) {
// modify token
token.role = profile.role;
}
return token;
},
session({ session, token }) {
// Send properties to the client
if (session.user) {
// modify session
session.user.roles = token.role;
}
return session;
},
},
});
然后在您的路线中,您将从 session
session.user.role
获取用户的角色
当您不使用任何适配器时,请参阅@koolskateguy89 的答案以获取基于 cookie 的用户信息。
但是为了在数据库上持久保存用户信息和角色,我们使用适配器,在这种情况下我们不需要 jwt 回调。所以这里是该用例的简单实现。
我使用的是Firestore适配器,您可以根据您的适配器和数据库替换代码。
api/auth/[...nextauth]/route.js
...
import { FirestoreAdapter } from "@auth/firebase-adapter"
import { db } from '@/lib/firebase/config'
const ROLES = {
USER: 'user',
MANAGER: 'manager',
ADMIN: 'admin',
OWNER: 'owner'
}
export const authOptions = {
adapter: FirestoreAdapter(db),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
GithubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
// add more providers
],
callbacks: {
async session({ session, user }) {
// Safely add role to the session
try {
session.user.role = user.role ?? ROLES.USER;
return session;
} catch (error) {
console.error("Error in session callback:", error.message)
session.user.role = ROLES.USER; // Ensure we always return a valid session
return session;
}
}
},
events: {
async createUser({ user }) {
try {
if (user?.id) {
// store role on database when user sign up
await db.collection('users').doc(user.id).update({ role: ROLES.USER })
}
} catch (error) {
console.error("Error in createUser event:", error)
}
}
},
debug: process.env.NODE_ENV === 'development',
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
关于代码:
版本:
"firebase-admin": "^12.7.0",
"next": "^14.2.5",
"next-auth": "^4.24.10"
"@auth/firebase-adapter": "^2.7.3"