如何将 Auth0 的 ID 令牌转发到 GraphQL 代码生成器?

Posted

技术标签:

【中文标题】如何将 Auth0 的 ID 令牌转发到 GraphQL 代码生成器?【英文标题】:How to forward Auth0's ID token to GraphQL Code Generator? 【发布时间】:2021-11-17 02:05:52 【问题描述】:

我正在使用带有 React Query 的 GraphQL 代码生成器,这是我的 codegen.yml

overwrite: true

schema: http://localhost:4000/graphql

generates:
  src/lib/__generated__/graphql.ts:
    documents:
      - "**/graphql/**/*.graphql"
      - "!mysqldata/**"
    plugins:
      - add:
          content: &comment "/* DO NOT EDIT! this file was generated by graphql-codegen */\n/* eslint-disable */"
      - add:
          placement: append
          content: "export  fetcher "
      - typescript
      - typescript-operations
      - typescript-react-query
    config:
      fetcher:
        endpoint: "`$process.env.NEXT_PUBLIC_API_URL/graphql`"
        fetchParams:
          credentials: include
          headers:
            Content-Type: application/json

这会生成以下提取器:

function fetcher<TData, TVariables>(query: string, variables?: TVariables) 
  return async (): Promise<TData> => 
    const res = await fetch(`$process.env.NEXT_PUBLIC_API_URL/graphql` as string, 
      method: "POST",
      credentials: "include",
      headers: "Content-Type":"application/json",
      body: JSON.stringify( query, variables ),
    );
    
    const json = await res.json();

    if (json.errors) 
      const  message  = json.errors[0];

      throw new Error(message);
    

    return json.data;
  

NEXT_PUBLIC_API_URL 指的是外部 GraphQL API。 在我的 Next.js 应用程序中,我尝试使用 nextjs-auth0 和 auth0-react。

nextjs-auth0 允许我从 Next.js API 路由访问 Auth0 的 ID 令牌:

export default (req: NextApiRequest, res: NextApiResponse) => 
  const session = getSession(req, res)
  const idToken = session?.idToken

auth0-react 允许我获取令牌客户端:

const claims = await auth0.getIdTokenClaims();
const idToken = claims.__raw;

问题在于,由于这些抽象,我无法找到一种方法将此令牌包含在对我的 GraphQL 端点的请求中,例如:

headers: 
  authorization: `Bearer $session?.idToken`,
,

【问题讨论】:

【参考方案1】:

在我发布了feature request 以在 cookie 中包含 ID 令牌后,我发现 nextjs-auth0 设置的“appSession”cookie 是包含 ID 令牌的加密令牌,我使用 @ 实现了自定义服务器逻辑987654323@源码作为参考:

type DecodedToken = Record<"idToken" | "token_type", string>

const API_BASE_URL = "https://example.com"
const BYTE_LENGTH = 32
const ENCRYPTION_INFO = "JWE CEK"
const HASH = "SHA-256"
const alg = "dir"
const enc = "A256GCM"

/**
 * Derives appropriate sized keys from provided secret random string/passphrase using
 * HKDF (HMAC-based Extract-and-Expand Key Derivation Function) defined in RFC 8569
 * @see https://tools.ietf.org/html/rfc5869
 */
function deriveKey(secret: string) 
  return hkdf(secret, BYTE_LENGTH,  info: ENCRYPTION_INFO, hash: HASH )


export const meQueryField = queryField("me", 
  type: "User",
  async resolve(_, __, ctx) 
    const jwe = ctx.request.cookies["appSession"]

    if (!jwe) 
      return null
    

    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    const octKey = JWK.asKey(deriveKey(process.env["AUTH0_SECRET"]!))

    const  cleartext  = JWE.decrypt(jwe, octKey, 
      complete: true,
      contentEncryptionAlgorithms: [alg],
      keyManagementAlgorithms: [enc],
    )

    const  idToken, token_type: tokenType  = JSON.parse(
      cleartext.toString()
    ) as DecodedToken

    const response = await fetch(`$API_BASE_URL/users/me`, 
      headers: 
        Authorization: `$tokenType $idToken`,
      ,
    )

    const user = (await response.json()) as Response

    return 
      id: user.data.id,
      ...
    
  ,
)

它不漂亮,但它有效。 AUTH0_SECRETnextjs-auth0 中用于加密令牌的密钥相同

【讨论】:

请考虑将您的答案标记为解决方案(一旦可能)。

以上是关于如何将 Auth0 的 ID 令牌转发到 GraphQL 代码生成器?的主要内容,如果未能解决你的问题,请参考以下文章

我应该将 id 令牌从我的 SPA 发送到我的 rest 后端吗?

登录 Auth0 后找不到如何获取访问令牌

如何使用我的后端中使用的前端反应中的 Auth0 访问令牌

可以使用 Auth0 JWT 令牌向 Django 后端发送 POST 请求吗?

如何使用 auth0 jwt 识别用户

如何从 auth0 中的访问令牌中获取 jwt 令牌