Wei-Shaw/sub2api · error
userinfo_failed
userinfo_failed
Error message
unsupported oauth provider
What it means
Thrown by fetchEmailOAuthProfile when the normalized provider name (trimmed, lowercased) is neither "github" nor "google" (code=userinfo_failed). The switch is exhaustive over the two supported providers; anything else is rejected before any userinfo call is made.
Source
Thrown at backend/internal/handler/auth_email_oauth.go:519
resp, err := req.C().
R().
SetContext(ctx).
SetBearerAuthToken(token.AccessToken).
SetHeader("Accept", "application/json").
Get(cfg.UserInfoURL)
if err != nil {
return nil, err
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("userinfo endpoint status %d: %s", resp.StatusCode, truncateLogValue(resp.String(), 1024))
}
switch strings.ToLower(strings.TrimSpace(provider)) {
case "github":
return parseGitHubOAuthProfile(ctx, cfg, token, resp.String())
case "google":
return parseGoogleOAuthProfile(resp.String())
default:
return nil, errors.New("unsupported oauth provider")
}
}
func parseGitHubOAuthProfile(ctx context.Context, cfg config.EmailOAuthProviderConfig, token *emailOAuthTokenResponse, body string) (*emailOAuthProfile, error) {
subject := strings.TrimSpace(gjson.Get(body, "id").String())
if subject == "" {
return nil, errors.New("github user id is missing")
}
email := ""
emailsURL := strings.TrimSpace(cfg.EmailsURL)
if emailsURL == "" {
return nil, errors.New("github verified email is missing")
}
verifiedEmail, err := fetchGitHubPrimaryVerifiedEmail(ctx, emailsURL, token.AccessToken)
if err != nil {
return nil, err
}
email = verifiedEmailView on GitHub (pinned to 073e92d171)
Solutions
- Set the provider name to exactly "github" or "google" (case-insensitive, surrounding whitespace is trimmed)
- If you need another IdP, use a provider that speaks the generic flow this system supports, or extend the switch in fetchEmailOAuthProfile
- Remove or disable the misconfigured provider entry so users cannot select it
Example fix
// before
providers:
acme:
name: "azure"
// after
providers:
acme:
name: "github" Defensive patterns
Strategy: validation
Validate before calling
// TS: validate provider before initiating the flow
const SUPPORTED = new Set(['github', 'google']);
const p = provider.trim().toLowerCase();
if (!SUPPORTED.has(p)) throw new Error(`unsupported provider '${provider}'; supported: github, google`); Type guard
type SupportedProvider = 'github' | 'google';
function isSupportedProvider(v: string): v is SupportedProvider {
return ['github', 'google'].includes(v.trim().toLowerCase());
} Prevention
- Restrict the provider dropdown to github/google in any login UI
- Validate provider names in config at startup, failing fast on typos
When it happens
Trigger: Email OAuth login with a provider config whose name is e.g. "azure", "gitlab", or a typo like "Github " that survives trimming only if it is not one of the two exact values after lowercase/trim.
Common situations: Adding a new OIDC provider expecting generic support; copy-paste config errors; renaming an existing provider entry.
Related errors
- dingtalk: internal_only requires app_type=internal
- 缺少 accessToken/access_token
- token_exchange_failed
- base URL must not include a query
- base URL must not include a fragment
AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15).
Data as JSON: /api/errors/5bedd6590136d761.
Report an issue: GitHub.