-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Description
The error message when a user has no tenant memberships is different from a generic authentication failure, allowing attackers to determine whether an email/identity exists in the system.
Location
// auth/handler.go
func (h *OIDCHandler) CallbackHandler(w http.ResponseWriter, r *http.Request) {
// ...
memberships, err := h.store.ListMemberships(r.Context(), userRef.UserID)
if err != nil {
http.Error(w, "failed to list memberships", http.StatusInternalServerError)
return
}
if len(memberships) == 0 {
http.Error(w, "user has no tenant memberships", http.StatusForbidden) // <-- Enumerates users
return
}
// ...
}Attack Scenario
- Attacker authenticates via OIDC with various emails
- If they see "user has no tenant memberships" (403), they know the user exists but isn't provisioned
- If they see "authentication failed" (401/500), they know the user doesn't exist
Recommended Fix
Use a consistent error message that doesn't reveal the distinction:
if len(memberships) == 0 {
slog.Warn("authenticated user has no tenant memberships",
"user_id", userRef.UserID,
"request_id", requestID)
http.Error(w, "authentication failed", http.StatusForbidden)
return
}Consider also:
- Provisioning users to a default tenant automatically
- Requiring admin invitation before users can authenticate
Impact
- Severity: Low
- Likelihood: Medium
- Affected: OAuth callback flow
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels