{"record":{"id":"2b3b485bba456016","repo":"dgraph-io/dgraph","slug":"expecting-either-jwkurl-or-jwkurls-both-were-give","errorCode":null,"errorMessage":"expecting either JWKUrl or JWKUrls, both were given","messagePattern":"expecting either JWKUrl or JWKUrls, both were given","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphql/authorization/auth.go","lineNumber":74,"sourceCode":"\tNamespace       string\n\tAlgo            string\n\tSigningMethod   jwt.SigningMethod `json:\"-\"` // Ignoring this field\n\tAudience        []string\n\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}","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/authorization/auth.go#L56-L92","documentation":"The `validate` method of Dgraph's Authorization configuration (AuthMeta, from the @auth directive's Dgraph.Authorization header) rejects configs that set both `JWKUrl` (single URL) and `JWKUrls` (list of URLs). Only one mechanism for supplying JSON Web Key sets is allowed.","triggerScenarios":"Setting the Dgraph.Authorization header so that its JSON contains a non-empty JWKUrls array AND a non-empty JWKUrl string at the same time, then calling Parse (typically at server start-up when the authorization header is parsed).","commonSituations":"Migrating a config from the old single JWKUrl field to the newer JWKUrls list and leaving the old key in place; copying a sample config that already had JWKUrl and adding JWKUrls without removing it; merging multiple auth config fragments.","solutions":["Remove `JWKUrl` and keep only the `JWKUrls` array (preferred for multiple key sets)","Or remove `JWKUrls` and keep only `JWKUrl` if you have exactly one JWKS endpoint","Restart Dgraph after fixing the Dgraph.Authorization header value"],"exampleFix":"// before\nDgraph.Authorization: {\"JWKUrl\":\"https://idp/.well-known/jwks.json\",\"JWKUrls\":[\"https://idp/.well-known/jwks.json\"],\"Namespace\":\"https://dgraph.io/jwt/claims\",\"Audience\":[\"dgraph\"],\"Algo\":\"RS256\"}\n// after\nDgraph.Authorization: {\"JWKUrls\":[\"https://idp/.well-known/jwks.json\"],\"Namespace\":\"https://dgraph.io/jwt/claims\",\"Audience\":[\"dgraph\"],\"Algo\":\"RS256\"}","handlingStrategy":"validation","validationCode":"const auth = JSON.parse(process.env.DGRAPH_AUTHORIZATION);\nif (auth.JWKUrl && Array.isArray(auth.JWKUrls) && auth.JWKUrls.length) {\n  throw new Error('Set either JWKUrl or JWKUrls, not both');\n}","typeGuard":"const usesSingleJwk = (a) => typeof a.JWKUrl === 'string' && a.JWKUrl !== '' && !(a.JWKUrls?.length);\nconst usesMultipleJwks = (a) => Array.isArray(a.JWKUrls) && a.JWKUrls.length > 0 && !a.JWKUrl;","tryCatchPattern":null,"preventionTips":["Pick one JWKS mechanism during config migrations and delete the other key","Validate the Dgraph.Authorization JSON before deploying","Keep a canonical auth config snippet in your repo"],"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"}