fix: disable one time access token exchange for disabled users

This commit is contained in:
Elias Schneider
2026-07-08 12:04:16 +02:00
parent ce7d3a7e1d
commit c85a4e63da
2 changed files with 53 additions and 0 deletions

View File

@@ -194,6 +194,9 @@ func (s *OneTimeAccessService) ExchangeOneTimeAccessToken(ctx context.Context, t
if oneTimeAccessToken.DeviceToken != nil && deviceToken != *oneTimeAccessToken.DeviceToken { if oneTimeAccessToken.DeviceToken != nil && deviceToken != *oneTimeAccessToken.DeviceToken {
return model.User{}, "", &common.DeviceCodeInvalid{} return model.User{}, "", &common.DeviceCodeInvalid{}
} }
if oneTimeAccessToken.User.Disabled {
return model.User{}, "", &common.UserDisabledError{}
}
accessToken, err := s.jwtService.GenerateAccessToken(oneTimeAccessToken.User, AuthenticationMethodOneTimePassword) accessToken, err := s.jwtService.GenerateAccessToken(oneTimeAccessToken.User, AuthenticationMethodOneTimePassword)
if err != nil { if err != nil {

View File

@@ -0,0 +1,50 @@
package service
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/pocket-id/pocket-id/backend/internal/common"
"github.com/pocket-id/pocket-id/backend/internal/model"
datatype "github.com/pocket-id/pocket-id/backend/internal/model/types"
testutils "github.com/pocket-id/pocket-id/backend/internal/utils/testing"
)
func TestExchangeOneTimeAccessTokenRejectsDisabledUser(t *testing.T) {
db := testutils.NewDatabaseForTest(t)
appConfig := NewTestAppConfigService((&AppConfigService{}).getDefaultDbConfig())
jwtService := initJwtService(t, db, appConfig, newTestEnvConfig())
auditLogService := NewAuditLogService(db, appConfig, nil, &GeoLiteService{})
oneTimeAccessService := NewOneTimeAccessService(db, nil, jwtService, auditLogService, nil, appConfig)
user := model.User{
Base: model.Base{ID: "disabled-user"},
Username: "disabled-user",
Disabled: true,
}
require.NoError(t, db.Create(&user).Error)
loginCode := model.OneTimeAccessToken{
Base: model.Base{ID: "disabled-user-login-code"},
Token: "ABCDEF",
ExpiresAt: datatype.DateTime(time.Now().Add(time.Minute)),
UserID: user.ID,
}
require.NoError(t, db.Create(&loginCode).Error)
exchangedUser, accessToken, err := oneTimeAccessService.ExchangeOneTimeAccessToken(t.Context(), loginCode.Token, "", "", "")
var userDisabledErr *common.UserDisabledError
require.ErrorAs(t, err, &userDisabledErr)
require.Empty(t, exchangedUser.ID)
require.Empty(t, accessToken)
var remainingLoginCode model.OneTimeAccessToken
require.NoError(t, db.Where("token = ?", loginCode.Token).First(&remainingLoginCode).Error)
var auditLogCount int64
require.NoError(t, db.Model(&model.AuditLog{}).Where("user_id = ?", user.ID).Count(&auditLogCount).Error)
require.Zero(t, auditLogCount)
}