{"record":{"id":"883e080598474c19","repo":"siyuan-note/siyuan","slug":"decode-oidc-claims-failed-w","errorCode":null,"errorMessage":"decode OIDC claims failed: %w","messagePattern":"decode OIDC claims failed: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc_provider/provider.go","lineNumber":112,"sourceCode":"\t\treturn nil, fmt.Errorf(\"exchange OIDC authorization code failed: %w\", err)\n\t}\n\tif p.kind == conf.OIDCProviderGitHub {\n\t\treturn exchangeGitHubClaims(ctx, token)\n\t}\n\trawIDToken, ok := token.Extra(\"id_token\").(string)\n\tif !ok || rawIDToken == \"\" {\n\t\treturn nil, errors.New(\"OIDC response does not contain an ID token\")\n\t}\n\tidToken, err := p.verifier.Verify(ctx, rawIDToken)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"verify OIDC ID token failed: %w\", err)\n\t}\n\tif idToken.Nonce != nonce {\n\t\treturn nil, errors.New(\"OIDC nonce does not match\")\n\t}\n\tclaims := map[string]any{}\n\tif err = idToken.Claims(&claims); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode OIDC claims failed: %w\", err)\n\t}\n\treturn claims, nil\n}\n\nfunc newGitHub(config *conf.OIDC, redirectURL string) *Provider {\n\tscopes := append([]string{}, config.Scopes...)\n\tif len(scopes) == 0 || isDefaultOIDCScopes(scopes) {\n\t\tscopes = []string{\"read:user\", \"user:email\"}\n\t} else {\n\t\tfiltered := scopes[:0]\n\t\tfor _, scope := range scopes {\n\t\t\tif scope != oidc.ScopeOpenID && scope != \"profile\" && scope != \"email\" {\n\t\t\t\tfiltered = append(filtered, scope)\n\t\t\t}\n\t\t}\n\t\tscopes = filtered\n\t\tif !contains(scopes, \"read:user\") {\n\t\t\tscopes = append([]string{\"read:user\"}, scopes...)","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/oidc_provider/provider.go#L94-L130","documentation":"After verification, Exchange() unmarshals the ID token's claims into a map[string]any via idToken.Claims. This only fails if the verified token's claims cannot be decoded into the target type, which is essentially an internal invariant violation: go-oidc verified the token, but its claim set is not a JSON object.","triggerScenarios":"Calling Exchange against a provider that returns an ID token whose claims payload is not a JSON object (e.g. top-level array or string), producing a json unmarshal error inside go-oidc's Claims.","commonSituations":"Extremely rare; seen with non-conformant or experimental identity providers that mint structurally invalid ID tokens, or with a proxy MITM-ing and corrupting the token payload after signature checks are bypassed by an unusual setup.","solutions":["Capture the raw id_token from the token response and inspect its payload; confirm the claims section is a JSON object","Update or fix the identity provider, which is producing a non-conformant ID token","Retry the login flow, since a transiently corrupted response will not reproduce","File the issue with the IdP vendor if the token payload is persistently non-object JSON"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"claims := map[string]any{}\nif err := idToken.Claims(&claims); err != nil {\n    return nil, fmt.Errorf(\"identity provider returned non-object claims; report to IdP vendor: %w\", err)\n}","preventionTips":["Validate the IdP against a standard OIDC conformance test before production use","Capture the raw id_token when this occurs to file a vendor bug","Keep go-oidc updated for improved claim decoding robustness"],"tags":["oidc","json","claims","decoding"],"backgroundTag":"json-decode-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}