NextJS中next-auth v4+CognitoProvider角色认证:角色未传入Session
问题描述
使用NextAuth v4的CognitoProvider实现基于角色的认证,已自定义Provider添加角色字段,但返回的session 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; }, }, });
profile对象控制台日志:
实际session对象(无role属性):
已将用户添加至admin组,需实现让该用户访问NextJS应用特定路由的功能,求解决方案。
解决方案
问题核心是session回调未将用户的role属性同步到session对象。NextAuth的session默认仅包含基础用户信息,需手动从user/token中取出role并添加到session里。
修改代码如下:
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: { // 首次登录时将role存入JWT token jwt: ({ token, user }) => { if (user) { token.role = user.role; } return token; }, // 将token中的role同步到session对象 session: ({ session, token }) => { if (session.user) { session.user.role = token.role; } return session; }, }, });
关键说明
profile函数返回的user对象仅在首次登录时传递给jwt回调,这里把role存入token,确保后续请求能持续获取到该字段session回调负责将token中的role同步到前端可见的session.user中,这样前端或服务端都能拿到role属性做权限判断
路由权限验证示例
在需要保护的路由(如pages/admin.js)中,可通过getServerSideProps验证角色:
import { getSession } from "next-auth/react"; export async function getServerSideProps(context) { const session = await getSession(context); // 无session或非admin用户直接跳转登录页 if (!session || !session.user.role?.includes('admin')) { return { redirect: { destination: '/login', permanent: false, }, }; } return { props: {} }; }
内容的提问来源于stack exchange,提问作者Arihant Jain
相关产品推荐
相关产品推荐

