From a7a8ae072a4f7ab7ec157152ba05ff133a655699 Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 23 Mar 2026 12:56:31 +0100 Subject: [PATCH] fix(auth): return correct error type for locked users in OIDC callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return ErrAccountLocked for locked users instead of ErrAccountDisabled. Also skip profile updates and avatar sync for disabled/locked users found during OIDC login — HandleCallback rejects the auth anyway. --- pkg/modules/auth/openid/openid.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pkg/modules/auth/openid/openid.go b/pkg/modules/auth/openid/openid.go index cbcf1cc5c..7c634daf1 100644 --- a/pkg/modules/auth/openid/openid.go +++ b/pkg/modules/auth/openid/openid.go @@ -158,10 +158,14 @@ func HandleCallback(c *echo.Context) error { return err } - if u.Status == user.StatusDisabled || u.Status == user.StatusAccountLocked { + if u.Status == user.StatusDisabled { _ = s.Rollback() return &user.ErrAccountDisabled{UserID: u.ID} } + if u.Status == user.StatusAccountLocked { + _ = s.Rollback() + return &user.ErrAccountLocked{UserID: u.ID} + } teamData := getTeamDataFromToken(cl.VikunjaGroups, provider) @@ -288,6 +292,12 @@ func getOrCreateUser(s *xorm.Session, cl *claims, provider *Provider, idToken *o } alreadyCreatedFromIssuer = err == nil || user.IsErrUserStatusError(err) + // If the user exists but is disabled/locked, return early — don't update their profile or sync avatar. + // HandleCallback will reject the auth attempt. + if alreadyCreatedFromIssuer && user.IsErrUserStatusError(err) { + return u, nil + } + if !alreadyCreatedFromIssuer && (provider.EmailFallback || provider.UsernameFallback) { // try finding the user on fallback mappingproperties @@ -313,6 +323,11 @@ func getOrCreateUser(s *xorm.Session, cl *claims, provider *Provider, idToken *o return nil, err } fallbackMatchFound = err == nil || user.IsErrUserStatusError(err) + + // Same as above: disabled/locked user found via fallback — return early. + if fallbackMatchFound && user.IsErrUserStatusError(err) { + return u, nil + } } if !alreadyCreatedFromIssuer && !fallbackMatchFound {