{"record":{"id":"c5da77a3a53593eb","repo":"Tencent/WeKnora","slug":"cannot-verify-oidc-id-token-issuer-is-not-configu","errorCode":null,"errorMessage":"cannot verify OIDC id_token: issuer is not configured","messagePattern":"cannot verify OIDC id_token: issuer is not configured","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/user.go","lineNumber":1945,"sourceCode":"\tif len(jwks.Keys) == 0 {\n\t\treturn nil, errors.New(\"JWKS document contains no keys\")\n\t}\n\treturn &jwks, nil\n}\n\nconst oidcIDTokenLeeway = 2 * time.Minute\n\n// verifyOIDCIDToken cryptographically verifies an OIDC id_token: it checks the\n// RSA signature against the provider's JWKS (matched by kid) and validates the\n// issuer, audience (client_id), expiry and subject. It returns the verified claims.\nfunc (s *userService) verifyOIDCIDToken(\n\tctx context.Context, cfg *config.OIDCAuthConfig, idToken string,\n) (map[string]interface{}, error) {\n\tif strings.TrimSpace(cfg.JwksURI) == \"\" {\n\t\treturn nil, errors.New(\"cannot verify OIDC id_token: no jwks_uri configured\")\n\t}\n\tif strings.TrimSpace(cfg.IssuerURL) == \"\" {\n\t\treturn nil, errors.New(\"cannot verify OIDC id_token: issuer is not configured\")\n\t}\n\tif strings.TrimSpace(cfg.ClientID) == \"\" {\n\t\treturn nil, errors.New(\"cannot verify OIDC id_token: client_id is not configured\")\n\t}\n\n\tjwks, err := s.fetchOIDCJWKS(ctx, cfg.JwksURI)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tkeyFunc := func(token *jwt.Token) (interface{}, error) {\n\t\tif _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {\n\t\t\treturn nil, fmt.Errorf(\"unexpected id_token signing method: %v\", token.Header[\"alg\"])\n\t\t}\n\t\tkid, _ := token.Header[\"kid\"].(string)\n\t\treturn jwks.rsaKeyForKid(kid)\n\t}\n","sourceCodeStart":1927,"sourceCodeEnd":1963,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/user.go#L1927-L1963","documentation":"verifyOIDCIDToken validates the token's iss claim against cfg.IssuerURL, so the issuer must be configured. An empty (or whitespace-only) IssuerURL makes claim validation impossible and the service rejects verification up front.","triggerScenarios":"OIDCAuthConfig passed to verifyOIDCIDToken has empty IssuerURL while JwksURI and ClientID may be set; strings.TrimSpace(cfg.IssuerURL) == \"\" at user.go:1945.","commonSituations":"Config file with an `issuer:` key left blank; env var OIDC_ISSUER unset; copy-pasted config where only client_id and jwks_uri were filled in; YAML parsing mapping the field to the wrong key.","solutions":["Set IssuerURL to the provider's issuer identifier (must exactly match the token's iss claim, including trailing slash).","Copy the issuer value from the provider's .well-known/openid-configuration `issuer` field.","Check env/config wiring so the issuer actually reaches OIDCAuthConfig.IssuerURL.","Trim/guard config loading to fail fast with a clear message when required OIDC fields are blank."],"exampleFix":"// before\nissuer: \"\"\n// after\nissuer: \"https://idp.example.com/realms/main\"","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(cfg.IssuerURL) == \"\" {\n    return errors.New(\"oidc issuer_url is required (must match token iss claim)\")\n}","typeGuard":"func issuerConfigured(c config.OIDCAuthConfig) bool {\n    return strings.TrimSpace(c.IssuerURL) != \"\"\n}","tryCatchPattern":null,"preventionTips":["Copy the issuer exactly from the provider's discovery document.","Add a startup config check that all of jwks_uri/issuer/client_id are set.","Watch for trailing-slash mismatches when setting the issuer."],"tags":["oidc","configuration","issuer","missing-config"],"backgroundTag":"missing-config-value","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}