{"record":{"id":"a18a698071850d81","repo":"dgraph-io/dgraph","slug":"expecting-either-jwkurl-jwkurls-or-verificationke","errorCode":null,"errorMessage":"expecting either JWKUrl/JWKUrls or (VerificationKey, Algo), both were given","messagePattern":"expecting either JWKUrl/JWKUrls or \\(VerificationKey, Algo\\), both were given","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphql/authorization/auth.go","lineNumber":78,"sourceCode":"\thttpClient      *http.Client\n\tClosedByDefault bool\n}\n\n// Validate required fields.\nfunc (a *AuthMeta) validate() error {\n\tvar fields string\n\n\t// If JWKUrl/JWKUrls is provided, we don't expect (VerificationKey, Algo),\n\t// they are needed only if JWKUrl/JWKUrls is not present there.\n\tif len(a.JWKUrls) != 0 || a.JWKUrl != \"\" {\n\n\t\t// User cannot provide both JWKUrl and JWKUrls.\n\t\tif len(a.JWKUrls) != 0 && a.JWKUrl != \"\" {\n\t\t\treturn fmt.Errorf(\"expecting either JWKUrl or JWKUrls, both were given\")\n\t\t}\n\n\t\tif a.VerificationKey != \"\" || a.Algo != \"\" {\n\t\t\treturn fmt.Errorf(\"expecting either JWKUrl/JWKUrls or (VerificationKey, Algo), both were given\")\n\t\t}\n\n\t\t// Audience should be a required field if JWKUrl is provided.\n\t\tif len(a.Audience) == 0 {\n\t\t\tfields = \" `Audience` \"\n\t\t}\n\t} else {\n\t\tif a.VerificationKey == \"\" {\n\t\t\tfields = \" `Verification key`/`JWKUrl`/`JWKUrls`\"\n\t\t}\n\n\t\tif a.Algo == \"\" {\n\t\t\tfields += \" `Algo`\"\n\t\t}\n\t}\n\n\tif a.Header == \"\" {\n\t\tfields += \" `Header`\"","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/authorization/auth.go#L60-L96","documentation":"`validate` in Dgraph's authorization package rejects an AuthMeta that specifies both a JWK source (JWKUrl/JWKUrls) and an inline verification key pair (VerificationKey + Algo). These are mutually exclusive ways to obtain the signing key: fetch from a JWKS endpoint versus embed the key statically.","triggerScenarios":"Calling Parse with a Dgraph.Authorization header where JWKUrl or JWKUrls is set AND VerificationKey or Algo is non-empty — e.g. `{\"JWKUrl\":\"https://idp/jwks.json\",\"VerificationKey\":\"...\",\"Algo\":\"RS256\",...}`.","commonSituations":"Upgrading from an old config that used an embedded key to JWKS and forgetting to delete VerificationKey/Algo; combining snippets from two tutorials; the JWKS URL not working so someone re-added an embedded key without removing the URL.","solutions":["Delete the `VerificationKey` and `Algo` fields and rely solely on the JWKS endpoint (JWKUrl/JWKUrls)","Or delete `JWKUrl`/`JWKUrls` and keep the inline VerificationKey + Algo pair","Ensure Algo is only present alongside VerificationKey (it's meaningless with JWKS, which publishes its own alg)"],"exampleFix":"// before\n{\"JWKUrl\":\"https://idp/.well-known/jwks.json\",\"VerificationKey\":\"-----BEGIN PUBLIC KEY-----...\",\"Algo\":\"RS256\"}\n// after\n{\"JWKUrl\":\"https://idp/.well-known/jwks.json\"}","handlingStrategy":"validation","validationCode":"const auth = JSON.parse(process.env.DGRAPH_AUTHORIZATION);\nconst hasJwk = auth.JWKUrl || auth.JWKUrls?.length;\nif (hasJwk && (auth.VerificationKey || auth.Algo)) {\n  throw new Error('Use JWKUrl/JWKUrls OR (VerificationKey + Algo), not both');\n}","typeGuard":"const isInlineKeyConfig = (a) => !a.JWKUrl && !a.JWKUrls?.length && !!a.VerificationKey && !!a.Algo;","tryCatchPattern":null,"preventionTips":["When migrating to JWKS, remove VerificationKey and Algo in the same change","Lint the authorization header for mutually exclusive fields in CI"],"tags":["authentication","jwt","configuration"],"backgroundTag":"jwt-provider-config-conflict","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}