From 2482bb87007c364e7dbf5956fef6f8a81ee91779 Mon Sep 17 00:00:00 2001 From: Livio Spring Date: Tue, 10 Jan 2023 15:58:10 +0100 Subject: [PATCH] Merge pull request from GHSA-6rrr-78xp-5jp8 --- internal/command/user.go | 2 +- .../command/user_human_refresh_token_model.go | 9 +- .../command/user_human_refresh_token_test.go | 91 ++++++++++++++++++- internal/repository/user/human.go | 10 +- 4 files changed, 106 insertions(+), 6 deletions(-) diff --git a/internal/command/user.go b/internal/command/user.go index 049756baed..96ca0d1e68 100644 --- a/internal/command/user.go +++ b/internal/command/user.go @@ -261,7 +261,7 @@ func (c *Commands) addUserToken(ctx context.Context, userWriteModel *UserWriteMo if err != nil { return nil, nil, err } - if !isUserStateExists(userWriteModel.UserState) { + if userWriteModel.UserState != domain.UserStateActive { return nil, nil, errors.ThrowNotFound(nil, "COMMAND-1d6Gg", "Errors.User.NotFound") } diff --git a/internal/command/user_human_refresh_token_model.go b/internal/command/user_human_refresh_token_model.go index 32111122aa..dd49cdf47f 100644 --- a/internal/command/user_human_refresh_token_model.go +++ b/internal/command/user_human_refresh_token_model.go @@ -18,6 +18,7 @@ type HumanRefreshTokenWriteModel struct { UserState domain.UserState IdleExpiration time.Time Expiration time.Time + UserAgentID string } func NewHumanRefreshTokenWriteModel(userID, resourceOwner, tokenID string) *HumanRefreshTokenWriteModel { @@ -48,6 +49,8 @@ func (wm *HumanRefreshTokenWriteModel) AppendEvents(events ...eventstore.Event) continue } wm.WriteModel.AppendEvents(e) + default: + wm.WriteModel.AppendEvents(e) } } } @@ -61,14 +64,18 @@ func (wm *HumanRefreshTokenWriteModel) Reduce() error { wm.IdleExpiration = e.CreationDate().Add(e.IdleExpiration) wm.Expiration = e.CreationDate().Add(e.Expiration) wm.UserState = domain.UserStateActive + wm.UserAgentID = e.UserAgentID case *user.HumanRefreshTokenRenewedEvent: if wm.UserState == domain.UserStateActive { wm.RefreshToken = e.RefreshToken } wm.RefreshToken = e.RefreshToken wm.IdleExpiration = e.CreationDate().Add(e.IdleExpiration) + case *user.HumanSignedOutEvent: + if wm.UserAgentID == e.UserAgentID { + wm.UserState = domain.UserStateDeleted + } case *user.HumanRefreshTokenRemovedEvent, - *user.HumanSignedOutEvent, *user.UserLockedEvent, *user.UserDeactivatedEvent, *user.UserRemovedEvent: diff --git a/internal/command/user_human_refresh_token_test.go b/internal/command/user_human_refresh_token_test.go index 67031983f7..760604c66d 100644 --- a/internal/command/user_human_refresh_token_test.go +++ b/internal/command/user_human_refresh_token_test.go @@ -64,10 +64,16 @@ func TestCommands_AddAccessAndRefreshToken(t *testing.T) { }, }, { - name: "add refresh token, user inactive, error", + name: "add refresh token, user deactivated, error", fields: fields{ eventstore: eventstoreExpect(t, - expectFilter(), + expectFilter( + eventFromEventPusher( + user.NewUserDeactivatedEvent(context.Background(), + &user.NewAggregate("userID", "orgID").Aggregate, + ), + ), + ), ), idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "refreshTokenID1"), }, @@ -912,6 +918,87 @@ func TestCommands_renewRefreshToken(t *testing.T) { err: caos_errs.IsErrorInvalidArgument, }, }, + { + name: "user deactivated, error", + fields: fields{ + eventstore: eventstoreExpect(t, + expectFilter( + eventFromEventPusherWithCreationDateNow(user.NewHumanRefreshTokenAddedEvent( + context.Background(), + &user.NewAggregate("userID", "orgID").Aggregate, + "tokenID", + "applicationID", + "userAgentID", + "de", + []string{"clientID1"}, + []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopeOfflineAccess}, + []string{"password"}, + time.Now(), + 1*time.Hour, + 24*time.Hour, + )), + eventFromEventPusher( + user.NewUserDeactivatedEvent( + context.Background(), + &user.NewAggregate("userID", "orgID").Aggregate, + ), + ), + ), + ), + keyAlgorithm: refreshTokenEncryptionAlgorithm(gomock.NewController(t)), + }, + args: args{ + ctx: context.Background(), + userID: "userID", + orgID: "orgID", + refreshToken: base64.RawURLEncoding.EncodeToString([]byte("userID:tokenID:tokenID")), + idleExpiration: 1 * time.Hour, + }, + res: res{ + err: caos_errs.IsErrorInvalidArgument, + }, + }, + { + name: "user signedout, error", + fields: fields{ + eventstore: eventstoreExpect(t, + expectFilter( + eventFromEventPusherWithCreationDateNow(user.NewHumanRefreshTokenAddedEvent( + context.Background(), + &user.NewAggregate("userID", "orgID").Aggregate, + "tokenID", + "applicationID", + "userAgentID", + "de", + []string{"clientID1"}, + []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopeOfflineAccess}, + []string{"password"}, + time.Now(), + 1*time.Hour, + 24*time.Hour, + )), + eventFromEventPusher( + user.NewHumanSignedOutEvent( + context.Background(), + &user.NewAggregate("userID", "orgID").Aggregate, + "userAgentID", + ), + ), + ), + ), + keyAlgorithm: refreshTokenEncryptionAlgorithm(gomock.NewController(t)), + }, + args: args{ + ctx: context.Background(), + userID: "userID", + orgID: "orgID", + refreshToken: base64.RawURLEncoding.EncodeToString([]byte("userID:tokenID:tokenID")), + idleExpiration: 1 * time.Hour, + }, + res: res{ + err: caos_errs.IsErrorInvalidArgument, + }, + }, { name: "token renewed, ok", fields: fields{ diff --git a/internal/repository/user/human.go b/internal/repository/user/human.go index 3d72241569..5d3b598a98 100644 --- a/internal/repository/user/human.go +++ b/internal/repository/user/human.go @@ -396,7 +396,13 @@ func NewHumanSignedOutEvent( } func HumanSignedOutEventMapper(event *repository.Event) (eventstore.Event, error) { - return &HumanSignedOutEvent{ + signedOut := &HumanSignedOutEvent{ BaseEvent: *eventstore.BaseEventFromRepo(event), - }, nil + } + err := json.Unmarshal(event.Data, signedOut) + if err != nil { + return nil, errors.ThrowInternal(err, "USER-WFS3g", "unable to unmarshal human signed out") + } + + return signedOut, nil }