{"record":{"id":"873e862ff49c9555","repo":"fatedier/frp","slug":"couldn-t-generate-oidc-token-for-login-v","errorCode":null,"errorMessage":"couldn't generate OIDC token for login: %v","messagePattern":"couldn't generate OIDC token for login: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/auth/oidc.go","lineNumber":191,"sourceCode":"\t// source.  This avoids an eager network call at construction time, which\n\t// would prevent loopLoginUntilSuccess from retrying on transient IdP\n\t// outages.\n\tcachingSource := tokenGenerator.TokenSource(ctx)\n\n\treturn &OidcAuthProvider{\n\t\tadditionalAuthScopes: additionalAuthScopes,\n\t\ttokenSource: &oidcTokenSource{\n\t\t\tsource:      cachingSource,\n\t\t\tfallbackCfg: tokenGenerator,\n\t\t\tfallbackCtx: ctx,\n\t\t},\n\t}, nil\n}\n\nfunc (auth *OidcAuthProvider) generateAccessToken() (accessToken string, err error) {\n\ttokenObj, err := auth.tokenSource.Token()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"couldn't generate OIDC token for login: %v\", err)\n\t}\n\treturn tokenObj.AccessToken, nil\n}\n\nfunc (auth *OidcAuthProvider) SetLogin(loginMsg *msg.Login) (err error) {\n\tloginMsg.PrivilegeKey, err = auth.generateAccessToken()\n\treturn err\n}\n\nfunc (auth *OidcAuthProvider) SetPing(pingMsg *msg.Ping) (err error) {\n\tif !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {\n\t\treturn nil\n\t}\n\n\tpingMsg.PrivilegeKey, err = auth.generateAccessToken()\n\treturn err\n}\n","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/auth/oidc.go#L173-L209","documentation":"This is the client side of OIDC login. Before sending the Login message, OidcAuthProvider.SetLogin calls generateAccessToken, which asks the oauth2 client-credentials TokenSource for a token (via oidcTokenSource, possibly falling back to a non-caching source when the provider omits expires_in). Any failure of that token request — network error, bad client credentials, wrong token endpoint, or failing to decode the token response — surfaces here.","triggerScenarios":"frpc with authentication.method=oidc calling SetLogin: the POST to oidc.tokenEndpointURL with client_id/client_secret fails DNS/TLS/connectivity, returns 401 (invalid client credentials), returns a non-token body, or the provider's token endpoint URL is misconfigured.","commonSituations":"Wrong oidc.clientid/clientsecret pair; token endpoint URL missing or mistyped; the IdP is internal and unreachable from the frpc host; the IdP's TLS cert is not trusted (no trustedCaFile set); clock skew on the client.","solutions":["Read the wrapped %v — oauth2 errors include the HTTP status and response body from the IdP","Verify oidc.tokenEndpointURL, oidc.clientid, oidc.clientsecret in the frpc config against the IdP","Reproduce the request manually: curl -d 'grant_type=client_credentials&client_id=...&client_secret=...' <tokenEndpointURL>","If the IdP uses a private CA, set oidc.trustedCaFile (or temporarily test with oidc.insecureSkipVerify)","Check network/DNS/firewall reachability of the IdP from the frpc host"],"exampleFix":"# before\nauthentication.method = \"oidc\"\nauthentication.oidc.tokenEndpointURL = \"https://idp.example.com/token\"\n\n# after (correct issuer path + credentials + CA)\nauthentication.method = \"oidc\"\nauthentication.oidc.tokenEndpointURL = \"https://idp.example.com/realms/frp/protocol/openid-connect/token\"\nauthentication.oidc.clientid = \"frp-client\"\nauthentication.oidc.clientsecret = \"***\"\nauthentication.oidc.trustedCaFile = \"/etc/frp/idp-ca.pem\"","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"token, err := auth.generateAccessToken()\nif err != nil {\n    if isRetryableTokenErr(err) { // network/5xx/timeouts\n        token, err = backoff.Retry(auth.generateAccessToken)\n    }\n    if err != nil { return fmt.Errorf(\"login token fetch failed: %w\", err) }\n}","preventionTips":["Smoke-test credentials with curl against the token endpoint in CI","Configure oidc.trustedCaFile for private IdPs from day one","Monitor frpc logs for the wrapped oauth2 error to distinguish 401 (credentials) from network failures"],"tags":["frp","oidc","authentication","token","oauth2"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}