next-auth & keycloakProvider:JWT令牌不完整

vhipe2zx  于 2023-04-20  发布在  其他
关注(0)|答案(1)|浏览(91)

我有一个带有next-auth的Next.js应用程序,它使用keycloakProvider连接到keycloak的本地示例。
Next-Auth配置如下:

import NextAuth from "next-auth";
import KeycloakProvider from "next-auth/providers/keycloak";

export const authOptions = {
  providers: [
    KeycloakProvider({
      clientId: process.env.CLIENT_ID,
      clientSecret: process.env.CLIENT_SECRET,
      issuer: process.env.ISSUER,
    })
  ],
}

export default NextAuth(authOptions);

这对于登录和使用useSession()钩子来说非常好。然而,会话钩子只返回name和email,而不是我需要的“sub”和“roles”等字段。如果我查询keycloak via curl,如下所示:

curl --request POST \                                                                                                                      
  --url 'http://localhost:8080/auth/realms/master/protocol/openid-connect/token' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=password' \
  --data-urlencode 'username=<username>' \
  --data-urlencode 'password=<password>' \
  --data-urlencode 'client_id=<client_id>' \
  --data-urlencode 'client_secret=<client_secret>'

并将JWT粘贴到jwt.io上,所有数据都在那里。如果JWT是从本地浏览器存储复制的,jwt.io将返回“Invalid Signature”。“browser-key”也比“curl-key”短得多。
为什么这可以通过 via curl而不是 vianext-auth来实现?

vu8f3i0k

vu8f3i0k1#

我也遇到了同样的问题,我是这样解决的:
首先,如果你的token没有加密,你可以使用这个简单的函数将它转换为JSON对象:

const decode = function (token) {
   return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString())
}

现在我们可以利用NextAuth回调'jwt'和'session',在将令牌和会话对象发送到客户端之前修改它们:

export default NextAuth({
  providers: [
    KeycloakProvider({
      clientId: process.env.KEYCLOAK_CLIENT_ID,
      clientSecret: process.env.KEYCLOAK_CLIENT_SECRET,
      issuer: process.env.KEYCLOAK_ISSUER
    })
  ],
  callbacks: {
    async jwt({ token, user, account, profile }) {
      if (account) {
        const { sub, roles } = decode(account.access_token)

        token.user = {
          ...user,
          sub,
          roles
        }
      }
      return token;
    },
    async session({ session, token, user }) {
      session.user = token.user
      return session;
    },
  },
})

使用这种方法,我们将sub和roles属性添加到useSession钩子中。
为什么会这样?我没有检查nextauth的源代码,但我想它只需要keycloak最相关的属性(姓名和电子邮件)。
希望能成功。

相关问题