mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-28 16:47:01 +09:00
Partially backport #39686
This commit is contained in:
1 parent
6064554b8d
commit
33aaf0cfa3
4 files changed
+54
-11
No files matched your search
@@ -24,9 +24,10 @@ import (
|
||||
// If a device uses the token to login into the instance, a fresh token gets generated which has the same id but a new hash.
|
||||
|
||||
var (
|
||||
ErrAuthTokenInvalidFormat = util.NewInvalidArgumentErrorf("auth token has an invalid format")
|
||||
ErrAuthTokenExpired = util.NewInvalidArgumentErrorf("auth token has expired")
|
||||
ErrAuthTokenInvalidHash = util.NewInvalidArgumentErrorf("auth token is invalid")
|
||||
ErrAuthTokenInvalidFormat = util.NewInvalidArgumentErrorf("auth token has an invalid format")
|
||||
ErrAuthTokenExpired = util.NewInvalidArgumentErrorf("auth token has expired")
|
||||
ErrAuthTokenInvalidHash = util.NewInvalidArgumentErrorf("auth token is invalid")
|
||||
ErrAuthTokenRotationConflict = util.NewInvalidArgumentErrorf("auth token was rotated by another request")
|
||||
)
|
||||
|
||||
func CheckAuthToken(ctx context.Context, value string) (*auth_model.AuthToken, error) {
|
||||
@@ -76,9 +77,23 @@ func RegenerateAuthToken(ctx context.Context, t *auth_model.AuthToken) (*auth_mo
|
||||
ExpiresUnix: timeutil.TimeStampNow().AddDuration(time.Duration(setting.LogInRememberDays*24) * time.Hour),
|
||||
}
|
||||
|
||||
if err := auth_model.UpdateAuthTokenByID(ctx, newToken); err != nil {
|
||||
updated, err := auth_model.UpdateAuthTokenByID(ctx, newToken, t.TokenHash)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if !updated {
|
||||
current, err := auth_model.GetAuthTokenByID(ctx, t.ID)
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
return nil, "", ErrAuthTokenExpired
|
||||
}
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if current.ExpiresUnix < timeutil.TimeStampNow() {
|
||||
return nil, "", ErrAuthTokenExpired
|
||||
}
|
||||
return nil, "", ErrAuthTokenRotationConflict
|
||||
}
|
||||
|
||||
return newToken, token, nil
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"gitea.dev/modules/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCheckAuthToken(t *testing.T) {
|
||||
@@ -105,5 +106,25 @@ func TestRegenerateAuthToken(t *testing.T) {
|
||||
assert.NotEqual(t, token, token2)
|
||||
assert.NotEqual(t, at.ExpiresUnix, at2.ExpiresUnix)
|
||||
|
||||
// Only one request may rotate the same validated cookie.
|
||||
competing, competingToken, err := RegenerateAuthToken(t.Context(), at)
|
||||
require.ErrorIs(t, err, ErrAuthTokenRotationConflict)
|
||||
require.Nil(t, competing)
|
||||
require.Empty(t, competingToken)
|
||||
current, err := CheckAuthToken(t.Context(), at2.ID+":"+token2)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, at2.TokenHash, current.TokenHash)
|
||||
|
||||
assert.NoError(t, auth_model.DeleteAuthTokenByID(t.Context(), at.ID))
|
||||
}
|
||||
|
||||
func TestRegenerateRevokedAuthToken(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
at, _, err := CreateAuthTokenForUserID(t.Context(), 2)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, auth_model.DeleteAuthTokenByID(t.Context(), at.ID))
|
||||
rotated, token, err := RegenerateAuthToken(t.Context(), at)
|
||||
require.ErrorIs(t, err, ErrAuthTokenExpired)
|
||||
require.Nil(t, rotated)
|
||||
require.Empty(t, token)
|
||||
}
|
||||
Reference in new issue
Block a user