Estoy usando GraphQL Code Generator con React Query , este es mi 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/jsonEsto genera el siguiente buscador:
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 hace referencia a una API de GraphQL externa. En mi aplicación Next.js intenté usar nextjs-auth0 y auth0-react .
nextjs-auth0 me permite acceder al token de ID de Auth0 desde las rutas de la API de Next.js:
export default (req: NextApiRequest, res: NextApiResponse) => { const session = getSession(req, res) const idToken = session?.idToken mientras que auth0-react me permite obtener el token del lado del cliente:
const claims = await auth0.getIdTokenClaims(); const idToken = claims.__raw;El problema es que, debido a estas abstracciones, no puedo encontrar una manera de incluir este token en las solicitudes a mi punto final de GraphQL como:
headers: { authorization: `Bearer ${session?.idToken}`, },Después de publicar una solicitud de función para incluir el token de ID dentro de una cookie, pensé que la cookie "appSession" establecida por nextjs-auth0 es un token encriptado que incluye el token de ID, implementé una lógica de servidor personalizada usando el código fuente nextjs-auth0 como referencia:
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, ... } }, }) No es bonito pero funciona. AUTH0_SECRET es el mismo secreto que se usa para cifrar el token en nextjs-auth0