fix(auth): harden oauth identity upgrade paths
This commit is contained in:
@@ -355,15 +355,20 @@ func (h *AuthHandler) findLinuxDoCompatEmailUser(ctx context.Context, email stri
|
||||
}
|
||||
|
||||
userEntity, err := client.User.Query().
|
||||
Where(dbuser.EmailEqualFold(email)).
|
||||
Only(ctx)
|
||||
Where(userNormalizedEmailPredicate(email)).
|
||||
Order(dbent.Asc(dbuser.FieldID)).
|
||||
All(ctx)
|
||||
if err != nil {
|
||||
if dbent.IsNotFound(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, infraerrors.InternalServer("COMPAT_EMAIL_LOOKUP_FAILED", "failed to look up compat email user").WithCause(err)
|
||||
}
|
||||
return userEntity, nil
|
||||
switch len(userEntity) {
|
||||
case 0:
|
||||
return nil, nil
|
||||
case 1:
|
||||
return userEntity[0], nil
|
||||
default:
|
||||
return nil, infraerrors.Conflict("USER_EMAIL_CONFLICT", "normalized email matched multiple users")
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AuthHandler) createLinuxDoOAuthChoicePendingSession(
|
||||
@@ -411,9 +416,15 @@ func (h *AuthHandler) createLinuxDoOAuthChoicePendingSession(
|
||||
completionResponse["choice_reason"] = "force_email_on_signup"
|
||||
}
|
||||
|
||||
var targetUserID *int64
|
||||
if compatEmailUser != nil && compatEmailUser.ID > 0 {
|
||||
targetUserID = &compatEmailUser.ID
|
||||
}
|
||||
|
||||
return h.createOAuthPendingSession(c, oauthPendingSessionPayload{
|
||||
Intent: oauthIntentLogin,
|
||||
Identity: identity,
|
||||
TargetUserID: targetUserID,
|
||||
ResolvedEmail: resolvedChoiceEmail,
|
||||
RedirectTo: redirectTo,
|
||||
BrowserSessionKey: browserSessionKey,
|
||||
@@ -490,9 +501,13 @@ func (h *AuthHandler) CompleteLinuxDoOAuthRegistration(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
tokenPair, user, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, req.InvitationCode)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
client := h.entClient()
|
||||
if client == nil {
|
||||
response.ErrorFrom(c, infraerrors.ServiceUnavailable("PENDING_AUTH_NOT_READY", "pending auth service is not ready"))
|
||||
return
|
||||
}
|
||||
if err := ensurePendingOAuthRegistrationIdentityAvailable(c.Request.Context(), client, session); err != nil {
|
||||
respondPendingOAuthBindingApplyError(c, err)
|
||||
return
|
||||
}
|
||||
decision, err := h.ensurePendingOAuthAdoptionDecision(c, session.ID, oauthAdoptionDecisionRequest{
|
||||
@@ -503,17 +518,16 @@ func (h *AuthHandler) CompleteLinuxDoOAuthRegistration(c *gin.Context) {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if err := applyPendingOAuthAdoption(c.Request.Context(), h.entClient(), h.authService, h.userService, session, decision, &user.ID); err != nil {
|
||||
response.ErrorFrom(c, infraerrors.InternalServer("PENDING_AUTH_ADOPTION_APPLY_FAILED", "failed to apply oauth profile adoption").WithCause(err))
|
||||
return
|
||||
}
|
||||
h.authService.RecordSuccessfulLogin(c.Request.Context(), user.ID)
|
||||
if _, err := pendingSvc.ConsumeBrowserSession(c.Request.Context(), sessionToken, browserSessionKey); err != nil {
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
tokenPair, user, err := h.authService.LoginOrRegisterOAuthWithTokenPair(c.Request.Context(), email, username, req.InvitationCode)
|
||||
if err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
if err := applyPendingOAuthAdoptionAndConsumeSession(c.Request.Context(), client, h.authService, h.userService, session, decision, user.ID); err != nil {
|
||||
respondPendingOAuthBindingApplyError(c, err)
|
||||
return
|
||||
}
|
||||
h.authService.RecordSuccessfulLogin(c.Request.Context(), user.ID)
|
||||
clearOAuthPendingSessionCookie(c, secureCookie)
|
||||
clearOAuthPendingBrowserCookie(c, secureCookie)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user