从next-auth客户端会话中获取用户ID

19
我正在使用 Prisma 和 GraphQL 配合 next-auth。我按照以下说明设置了适配器和相关模型:https://next-auth.js.org/adapters/prisma 认证可以正常工作,但是当我从这里检查 session 对象时: const { data: session, status } = useSession() 我没有看到 ID。 enter image description here 我需要 ID 以便进行进一步的 GraphQL 查询。目前我使用电子邮件值来获取用户,但如果有 ID 可用,那将是更好的选择。
8个回答

25

这是您问题的最快解决方案:

src/pages/api/auth/[...nextAuth].js

export default NextAuth({
  ...
  callbacks: {
    session: async ({ session, token }) => {
      if (session?.user) {
        session.user.id = token.uid;
      }
      return session;
    },
    jwt: async ({ user, token }) => {
      if (user) {
        token.uid = user.id;
      }
      return token;
    },
  },
  session: {
    strategy: 'jwt',
  },
  ...
});

5
这可能已经改变了;对我来说,它显示为 token.sub 而不是 token.uid - Clay Morton

17

我刚刚参考了NextAuth文档(此页面),最终以正确的方式使其工作。

callbacks: {
  jwt({ token, account, user }) {
    if (account) {
      token.accessToken = account.access_token
      token.id = user?.id
    }
    return token
  }
  session({ session, token }) {
      // I skipped the line below coz it gave me a TypeError
      // session.accessToken = token.accessToken;
      session.user.id = token.id;

      return session;
    },
}

如果您使用TypeScript,请将以下内容添加到一个名为next-auth.d.ts的新文件中。
import NextAuth from 'next-auth';

declare module 'next-auth' {
  interface Session {
    user: {
      id: string;
    } & DefaultSession['user'];
  }
}

13
这些解决方案都没有解决我的问题,但在调试过程中,我发现 'token.sub' 表示用户ID。以下是我所做的操作:
callbacks: {
    session: ({ session, token }) => ({
      ...session,
      user: {
        ...session.user,
        id: token.sub,
      },
    }),
  },

我可以确认这是当前正确的答案。谢谢! - Pepelius
你把那个令牌的子ID存储在数据库中吗? - undefined
@German 不,我不。 - undefined
但是你说它代表用户ID。那么你在数据库中存储的是什么作为用户ID呢? - undefined

9

这是我使用的最快解决方案

import NextAuth from "next-auth"
import { MongoDBAdapter } from "@next-auth/mongodb-adapter"
import clientPromise from "../../../lib/mongodb"

export const authOptions = {
    providers: [
      <...yourproviders>
    ],
    callbacks: {
      session: async ({ session, token, user }) => {
        if (session?.user) {
          session.user.id = user.id;
        }
        return session;
      },
    },
    adapter: MongoDBAdapter(clientPromise),
}

1
对我来说很有效!! - Sadeed_pv

4

这对我起作用了。

callbacks: {
    async jwt({token, user, account, profile, isNewUser}) {
        user && (token.user = user)
        return token
    },
    async session({session, token, user}) {
        session = {
            ...session,
            user: {
                id: user.id,
                ...session.user
            }
        }
        return session
    }
}

3
我对此事迟到了,但我遇到了同样的问题,这是我找到的解决方法。
所以在 Next.js@13^ 或 App 路由中,他们要求你不要修改 next-env.d.ts。他们说这是为了帮助他们在将来轻松添加 Next 的更新/功能,所以他们会在每次构建时重新生成它。
具体来说,原始文件中写道,
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

所以解决这个问题的方法是创建一个新的模块,可以随意命名。按照惯例,最好将其命名为next-auth-extensions.d.ts,放在与next-env.d.ts相同的位置/文件夹中,然后将其添加到tsconfig.json中的includes属性中。
所以,以下文件是我在Next、Typescript和Next-Auth配置中的最终结果。
// next-auth-extensions.d.ts
import NextAuth, { DefaultSession } from "next-auth";

declare module "next-auth" {
  /**
   * Returned by `useSession`, `getSession`, and received as a prop on the `SessionProvider` React Context
   */
  interface Session {
    user: {
      /** The user's id */
      id: string;
    } & DefaultSession["user"];
  }
}

// tsconfig.json
{
  ...
  "compilerOptions": {
    ...
  },
  "include": ["next-env.d.ts", "next-auth-extensions.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  ...
}


// /api/auth/[...nextauth]/route.ts
import { db } from "@/db";
import { PrismaAdapter } from "@auth/prisma-adapter";

import NextAuth, { NextAuthOptions } from "next-auth";

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(db),
  providers: [
    ...
  ],
  callbacks: {
    async session({ session, user }) {
      console.log(user);
      session.user.id = user.id;
      return session;
    },
  },
  ...
};

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };


我对GraphQL的任何适配都不确定,因为我以前从未使用过,但这对我来说有效。请查看下面的package.json,以防版本有差异。如果可以,请告诉我它是否有效。
注意:这不是官方的方式,只是我研究并尝试使其工作的一种方法,如果有人有建议或其他任何事情,请告诉我。
{
   ...
   "dependencies": {
    "@auth/prisma-adapter": "^1.0.3",
    "@prisma/client": "^5.4.2",
   ...
    "next": "13.5.4",
    "next-auth": "^4.23.2",
    "react": "^18",
    ...
  },

对于接下来的14个应用程序路由器和TypeScript代码库,这是一个完美有效的答案。 - undefined

0

我相信你可以更改回调函数,以便在会话中包含用户的ID:https://next-auth.js.org/configuration/callbacks

你需要更改JWT回调函数,以便它也包括userId和会话回调函数,以便ID也被持久化到浏览器会话中。


0
I fetched same problem. But now I solved the problem by using this code:

 callbacks: {
    session: async ({ session, token }) => {
      if (session?.user) {
        session.user.id = token.sub;// token.uid or token.sub both work
      }
      return session;
    },
    jwt: async ({ user, token }) => {
      if (user) {
        token.sub = user.id; // token.uid or token.sub both work
      }
      return token;
    },
  },

Thanks @Frahim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接