mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:17:32 +00:00
feat: allow session deletion without session token (#6889)
* fix: add resource owner of user and change the one of session to instance * use user resource owner from session projection * fix session permission check * integration tests and fixes * update api docs
This commit is contained in:
@@ -90,7 +90,7 @@ func (c *Commands) LinkSessionToAuthRequest(ctx context.Context, id, sessionID,
|
||||
if checkLoginClient && authz.GetCtxData(ctx).UserID != writeModel.LoginClient {
|
||||
return nil, nil, errors.ThrowPermissionDenied(nil, "COMMAND-rai9Y", "Errors.AuthRequest.WrongLoginClient")
|
||||
}
|
||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetCtxData(ctx).OrgID)
|
||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetInstance(ctx).InstanceID())
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -98,7 +98,7 @@ func (c *Commands) LinkSessionToAuthRequest(ctx context.Context, id, sessionID,
|
||||
if err = sessionWriteModel.CheckIsActive(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.sessionPermission(ctx, sessionWriteModel, sessionToken, domain.PermissionSessionWrite); err != nil {
|
||||
if err := c.sessionTokenVerifier(ctx, sessionToken, sessionWriteModel.AggregateID, sessionWriteModel.TokenID); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
|
@@ -164,9 +164,8 @@ func TestCommands_AddAuthRequest(t *testing.T) {
|
||||
func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
mockCtx := authz.NewMockContext("instanceID", "orgID", "loginClient")
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
tokenVerifier func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error)
|
||||
checkPermission domain.PermissionCheck
|
||||
eventstore *eventstore.Eventstore
|
||||
tokenVerifier func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error)
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -192,10 +191,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return nil
|
||||
},
|
||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||
tokenVerifier: newMockTokenVerifierValid(),
|
||||
},
|
||||
args{
|
||||
ctx: mockCtx,
|
||||
@@ -235,10 +231,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return nil
|
||||
},
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
tokenVerifier: newMockTokenVerifierValid(),
|
||||
},
|
||||
args{
|
||||
ctx: mockCtx,
|
||||
@@ -274,10 +267,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return nil
|
||||
},
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
tokenVerifier: newMockTokenVerifierValid(),
|
||||
},
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "orgID", "wrongLoginClient"),
|
||||
@@ -316,10 +306,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
),
|
||||
expectFilter(),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return nil
|
||||
},
|
||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||
tokenVerifier: newMockTokenVerifierValid(),
|
||||
},
|
||||
args{
|
||||
ctx: mockCtx,
|
||||
@@ -357,7 +344,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(mockCtx,
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -366,15 +353,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"userID", testNow.Add(-5*time.Minute)),
|
||||
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"userID", "org1", testNow.Add(-5*time.Minute)),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
testNow.Add(-5*time.Minute)),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
2*time.Minute),
|
||||
),
|
||||
),
|
||||
@@ -390,57 +377,6 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
wantErr: caos_errs.ThrowPreconditionFailed(nil, "COMMAND-Hkl3d", "Errors.Session.Expired"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"missing permission",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
authrequest.NewAddedEvent(mockCtx, &authrequest.NewAggregate("V2_id", "instanceID").Aggregate,
|
||||
"loginClient",
|
||||
"clientID",
|
||||
"redirectURI",
|
||||
"state",
|
||||
"nonce",
|
||||
[]string{"openid"},
|
||||
[]string{"audience"},
|
||||
domain.OIDCResponseTypeCode,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(mockCtx,
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
)),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return nil
|
||||
},
|
||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||
},
|
||||
args{
|
||||
ctx: mockCtx,
|
||||
id: "V2_id",
|
||||
sessionID: "sessionID",
|
||||
},
|
||||
res{
|
||||
wantErr: caos_errs.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid session token",
|
||||
fields{
|
||||
@@ -468,7 +404,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(mockCtx,
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -478,9 +414,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
)),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return caos_errs.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid")
|
||||
},
|
||||
tokenVerifier: newMockTokenVerifierInvalid(),
|
||||
},
|
||||
args{
|
||||
ctx: mockCtx,
|
||||
@@ -519,7 +453,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(mockCtx,
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -528,15 +462,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"userID", testNow),
|
||||
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"userID", "org1", testNow),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
testNow),
|
||||
),
|
||||
eventFromEventPusherWithCreationDateNow(
|
||||
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
2*time.Minute),
|
||||
),
|
||||
),
|
||||
@@ -549,10 +483,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return nil
|
||||
},
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
tokenVerifier: newMockTokenVerifierValid(),
|
||||
},
|
||||
args{
|
||||
ctx: mockCtx,
|
||||
@@ -607,7 +538,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(mockCtx,
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -616,15 +547,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"userID", testNow),
|
||||
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"userID", "org1", testNow),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
testNow),
|
||||
),
|
||||
eventFromEventPusherWithCreationDateNow(
|
||||
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
2*time.Minute),
|
||||
),
|
||||
),
|
||||
@@ -637,10 +568,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return nil
|
||||
},
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
tokenVerifier: newMockTokenVerifierValid(),
|
||||
},
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "orgID", "loginClient"),
|
||||
@@ -675,7 +603,6 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||
c := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
sessionTokenVerifier: tt.fields.tokenVerifier,
|
||||
checkPermission: tt.fields.checkPermission,
|
||||
}
|
||||
details, got, err := c.LinkSessionToAuthRequest(tt.args.ctx, tt.args.id, tt.args.sessionID, tt.args.sessionToken, tt.args.checkLoginClient)
|
||||
require.ErrorIs(t, err, tt.res.wantErr)
|
||||
|
@@ -241,6 +241,17 @@ func newMockPermissionCheckNotAllowed() domain.PermissionCheck {
|
||||
}
|
||||
}
|
||||
|
||||
func newMockTokenVerifierValid() func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
func newMockTokenVerifierInvalid() func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return errors.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid")
|
||||
}
|
||||
}
|
||||
|
||||
type plainHasher struct {
|
||||
x string // arbitrary info that triggers update when different from encoding
|
||||
}
|
||||
|
@@ -153,7 +153,7 @@ func (c *Commands) newOIDCSessionAddEvents(ctx context.Context, authRequestID st
|
||||
if err = authRequestWriteModel.CheckAuthenticated(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sessionWriteModel := NewSessionWriteModel(authRequestWriteModel.SessionID, authz.GetCtxData(ctx).OrgID)
|
||||
sessionWriteModel := NewSessionWriteModel(authRequestWriteModel.SessionID, authz.GetInstance(ctx).InstanceID())
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -166,7 +166,7 @@ func TestCommands_AddOIDCSessionAccessToken(t *testing.T) {
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -177,7 +177,7 @@ func TestCommands_AddOIDCSessionAccessToken(t *testing.T) {
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
||||
"userID", testNow),
|
||||
"userID", "org1", testNow),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
||||
@@ -367,7 +367,7 @@ func TestCommands_AddOIDCSessionRefreshAndAccessToken(t *testing.T) {
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -378,7 +378,7 @@ func TestCommands_AddOIDCSessionRefreshAndAccessToken(t *testing.T) {
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
||||
"userID", testNow),
|
||||
"userID", "org1", testNow),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
||||
|
@@ -55,12 +55,12 @@ func (c *Commands) NewSessionCommands(cmds []SessionCommand, session *SessionWri
|
||||
}
|
||||
|
||||
// CheckUser defines a user check to be executed for a session update
|
||||
func CheckUser(id string) SessionCommand {
|
||||
func CheckUser(id string, resourceOwner string) SessionCommand {
|
||||
return func(ctx context.Context, cmd *SessionCommands) error {
|
||||
if cmd.sessionWriteModel.UserID != "" && id != "" && cmd.sessionWriteModel.UserID != id {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "", "user change not possible")
|
||||
}
|
||||
return cmd.UserChecked(ctx, id, cmd.now())
|
||||
return cmd.UserChecked(ctx, id, resourceOwner, cmd.now())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,10 +170,11 @@ func (s *SessionCommands) Start(ctx context.Context, userAgent *domain.UserAgent
|
||||
s.eventCommands = append(s.eventCommands, session.NewAddedEvent(ctx, s.sessionWriteModel.aggregate, userAgent))
|
||||
}
|
||||
|
||||
func (s *SessionCommands) UserChecked(ctx context.Context, userID string, checkedAt time.Time) error {
|
||||
s.eventCommands = append(s.eventCommands, session.NewUserCheckedEvent(ctx, s.sessionWriteModel.aggregate, userID, checkedAt))
|
||||
func (s *SessionCommands) UserChecked(ctx context.Context, userID, resourceOwner string, checkedAt time.Time) error {
|
||||
s.eventCommands = append(s.eventCommands, session.NewUserCheckedEvent(ctx, s.sessionWriteModel.aggregate, userID, resourceOwner, checkedAt))
|
||||
// set the userID so other checks can use it
|
||||
s.sessionWriteModel.UserID = userID
|
||||
s.sessionWriteModel.UserResourceOwner = resourceOwner
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -267,7 +268,7 @@ func (s *SessionCommands) gethumanWriteModel(ctx context.Context) (*HumanWriteMo
|
||||
if s.sessionWriteModel.UserID == "" {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-eeR2e", "Errors.User.UserIDMissing")
|
||||
}
|
||||
humanWriteModel := NewHumanWriteModel(s.sessionWriteModel.UserID, "")
|
||||
humanWriteModel := NewHumanWriteModel(s.sessionWriteModel.UserID, s.sessionWriteModel.UserResourceOwner)
|
||||
err := s.eventstore.FilterToQueryReducer(ctx, humanWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -296,7 +297,7 @@ func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, met
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetCtxData(ctx).OrgID)
|
||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetInstance(ctx).InstanceID())
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -307,12 +308,12 @@ func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, met
|
||||
}
|
||||
|
||||
func (c *Commands) UpdateSession(ctx context.Context, sessionID, sessionToken string, cmds []SessionCommand, metadata map[string][]byte, lifetime time.Duration) (set *SessionChanged, err error) {
|
||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetCtxData(ctx).OrgID)
|
||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetInstance(ctx).InstanceID())
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.sessionPermission(ctx, sessionWriteModel, sessionToken, domain.PermissionSessionWrite); err != nil {
|
||||
if err := c.sessionTokenVerifier(ctx, sessionToken, sessionWriteModel.AggregateID, sessionWriteModel.TokenID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd := c.NewSessionCommands(cmds, sessionWriteModel)
|
||||
@@ -328,12 +329,12 @@ func (c *Commands) TerminateSessionWithoutTokenCheck(ctx context.Context, sessio
|
||||
}
|
||||
|
||||
func (c *Commands) terminateSession(ctx context.Context, sessionID, sessionToken string, mustCheckToken bool) (*domain.ObjectDetails, error) {
|
||||
sessionWriteModel := NewSessionWriteModel(sessionID, "")
|
||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetInstance(ctx).InstanceID())
|
||||
if err := c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if mustCheckToken {
|
||||
if err := c.sessionPermission(ctx, sessionWriteModel, sessionToken, domain.PermissionSessionDelete); err != nil {
|
||||
if err := c.checkSessionTerminationPermission(ctx, sessionWriteModel, sessionToken); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -386,13 +387,17 @@ func (c *Commands) updateSession(ctx context.Context, checks *SessionCommands, m
|
||||
return changed, nil
|
||||
}
|
||||
|
||||
// sessionPermission will check that the provided sessionToken is correct or
|
||||
// if empty, check that the caller is granted the necessary permission
|
||||
func (c *Commands) sessionPermission(ctx context.Context, sessionWriteModel *SessionWriteModel, sessionToken, permission string) (err error) {
|
||||
if sessionToken == "" {
|
||||
return c.checkPermission(ctx, permission, authz.GetCtxData(ctx).OrgID, sessionWriteModel.AggregateID)
|
||||
// checkSessionTerminationPermission will check that the provided sessionToken is correct or
|
||||
// if empty, check that the caller is either terminating the own session or
|
||||
// is granted the "session.delete" permission on the resource owner of the authenticated user.
|
||||
func (c *Commands) checkSessionTerminationPermission(ctx context.Context, model *SessionWriteModel, token string) error {
|
||||
if token != "" {
|
||||
return c.sessionTokenVerifier(ctx, token, model.AggregateID, model.TokenID)
|
||||
}
|
||||
return c.sessionTokenVerifier(ctx, sessionToken, sessionWriteModel.AggregateID, sessionWriteModel.TokenID)
|
||||
if model.UserID != "" && model.UserID == authz.GetCtxData(ctx).UserID {
|
||||
return nil
|
||||
}
|
||||
return c.checkPermission(ctx, domain.PermissionSessionDelete, model.UserResourceOwner, model.UserID)
|
||||
}
|
||||
|
||||
func sessionTokenCreator(idGenerator id.Generator, sessionAlg crypto.EncryptionAlgorithm) func(sessionID string) (id string, token string, err error) {
|
||||
|
@@ -39,6 +39,7 @@ type SessionWriteModel struct {
|
||||
|
||||
TokenID string
|
||||
UserID string
|
||||
UserResourceOwner string
|
||||
UserCheckedAt time.Time
|
||||
PasswordCheckedAt time.Time
|
||||
IntentCheckedAt time.Time
|
||||
@@ -58,14 +59,14 @@ type SessionWriteModel struct {
|
||||
aggregate *eventstore.Aggregate
|
||||
}
|
||||
|
||||
func NewSessionWriteModel(sessionID string, resourceOwner string) *SessionWriteModel {
|
||||
func NewSessionWriteModel(sessionID string, instanceID string) *SessionWriteModel {
|
||||
return &SessionWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: sessionID,
|
||||
ResourceOwner: resourceOwner,
|
||||
ResourceOwner: instanceID,
|
||||
},
|
||||
Metadata: make(map[string][]byte),
|
||||
aggregate: &session.NewAggregate(sessionID, resourceOwner).Aggregate,
|
||||
aggregate: &session.NewAggregate(sessionID, instanceID).Aggregate,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +142,7 @@ func (wm *SessionWriteModel) reduceAdded(e *session.AddedEvent) {
|
||||
|
||||
func (wm *SessionWriteModel) reduceUserChecked(e *session.UserCheckedEvent) {
|
||||
wm.UserID = e.UserID
|
||||
wm.UserResourceOwner = e.UserResourceOwner
|
||||
wm.UserCheckedAt = e.CheckedAt
|
||||
}
|
||||
|
||||
|
@@ -204,7 +204,7 @@ func TestCommands_CreateSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
args{
|
||||
ctx: authz.NewMockContext("", "org1", ""),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
userAgent: &domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -231,7 +231,7 @@ func TestCommands_CreateSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
args{
|
||||
ctx: authz.NewMockContext("", "org1", ""),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
userAgent: &domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -244,7 +244,7 @@ func TestCommands_CreateSession(t *testing.T) {
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -252,15 +252,15 @@ func TestCommands_CreateSession(t *testing.T) {
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
),
|
||||
session.NewLifetimeSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, 10*time.Minute),
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewLifetimeSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate, 10*time.Minute),
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID",
|
||||
),
|
||||
),
|
||||
},
|
||||
res{
|
||||
want: &SessionChanged{
|
||||
ObjectDetails: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||
ObjectDetails: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
||||
ID: "sessionID",
|
||||
NewToken: "token",
|
||||
},
|
||||
@@ -326,7 +326,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -335,13 +335,11 @@ func TestCommands_UpdateSession(t *testing.T) {
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID")),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return caos_errs.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid")
|
||||
},
|
||||
tokenVerifier: newMockTokenVerifierInvalid(),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
@@ -359,7 +357,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -368,7 +366,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID")),
|
||||
),
|
||||
),
|
||||
@@ -384,7 +382,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
||||
res{
|
||||
want: &SessionChanged{
|
||||
ObjectDetails: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
ID: "sessionID",
|
||||
NewToken: "",
|
||||
@@ -463,7 +461,7 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
checks: &SessionCommands{
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||
sessionCommands: []SessionCommand{
|
||||
func(ctx context.Context, cmd *SessionCommands) error {
|
||||
return caos_errs.ThrowInternal(nil, "id", "check failed")
|
||||
@@ -481,16 +479,16 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
checks: &SessionCommands{
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||
sessionCommands: []SessionCommand{},
|
||||
},
|
||||
},
|
||||
res{
|
||||
want: &SessionChanged{
|
||||
ObjectDetails: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
ID: "sessionID",
|
||||
NewToken: "",
|
||||
@@ -503,9 +501,9 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
checks: &SessionCommands{
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||
sessionCommands: []SessionCommand{},
|
||||
eventstore: eventstoreExpect(t),
|
||||
createToken: func(sessionID string) (string, string, error) {
|
||||
@@ -528,19 +526,19 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectPush(
|
||||
session.NewLifetimeSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewLifetimeSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
10*time.Minute,
|
||||
),
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID",
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
checks: &SessionCommands{
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||
sessionCommands: []SessionCommand{},
|
||||
eventstore: eventstoreExpect(t),
|
||||
createToken: func(sessionID string) (string, string, error) {
|
||||
@@ -557,7 +555,7 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
res{
|
||||
want: &SessionChanged{
|
||||
ObjectDetails: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
ID: "sessionID",
|
||||
NewToken: "token",
|
||||
@@ -569,27 +567,27 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectPush(
|
||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"userID", testNow,
|
||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"userID", "org1", testNow,
|
||||
),
|
||||
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
testNow,
|
||||
),
|
||||
session.NewMetadataSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewMetadataSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
map[string][]byte{"key": []byte("value")},
|
||||
),
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID",
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
checks: &SessionCommands{
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||
sessionCommands: []SessionCommand{
|
||||
CheckUser("userID"),
|
||||
CheckUser("userID", "org1"),
|
||||
CheckPassword("password"),
|
||||
},
|
||||
eventstore: eventstoreExpect(t,
|
||||
@@ -621,7 +619,7 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
res{
|
||||
want: &SessionChanged{
|
||||
ObjectDetails: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
ID: "sessionID",
|
||||
NewToken: "token",
|
||||
@@ -634,11 +632,11 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
checks: &SessionCommands{
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||
sessionCommands: []SessionCommand{
|
||||
CheckUser("userID"),
|
||||
CheckUser("userID", "org1"),
|
||||
CheckIntent("intent", "aW50ZW50"),
|
||||
},
|
||||
eventstore: eventstoreExpect(t,
|
||||
@@ -673,11 +671,11 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
checks: &SessionCommands{
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||
sessionCommands: []SessionCommand{
|
||||
CheckUser("userID"),
|
||||
CheckUser("userID", "org1"),
|
||||
CheckIntent("intent", "aW50ZW50"),
|
||||
},
|
||||
eventstore: eventstoreExpect(t,
|
||||
@@ -722,11 +720,11 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
checks: &SessionCommands{
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||
sessionCommands: []SessionCommand{
|
||||
CheckUser("userID"),
|
||||
CheckUser("userID", "org1"),
|
||||
CheckIntent("intent2", "aW50ZW50"),
|
||||
},
|
||||
eventstore: eventstoreExpect(t),
|
||||
@@ -753,23 +751,23 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
expectPush(
|
||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
"userID", testNow),
|
||||
session.NewIntentCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"userID", "org1", testNow),
|
||||
session.NewIntentCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
testNow),
|
||||
session.NewMetadataSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewMetadataSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
map[string][]byte{"key": []byte("value")}),
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID"),
|
||||
),
|
||||
),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
ctx: authz.NewMockContext("instance1", "", ""),
|
||||
checks: &SessionCommands{
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
||||
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||
sessionCommands: []SessionCommand{
|
||||
CheckUser("userID"),
|
||||
CheckUser("userID", "org1"),
|
||||
CheckIntent("intent", "aW50ZW50"),
|
||||
},
|
||||
eventstore: eventstoreExpect(t,
|
||||
@@ -807,7 +805,7 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
res{
|
||||
want: &SessionChanged{
|
||||
ObjectDetails: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
ID: "sessionID",
|
||||
NewToken: "token",
|
||||
@@ -828,13 +826,13 @@ func TestCommands_updateSession(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckTOTP(t *testing.T) {
|
||||
ctx := authz.NewMockContext("", "org1", "user1")
|
||||
ctx := authz.NewMockContext("instance1", "org1", "user1")
|
||||
|
||||
cryptoAlg := crypto.CreateMockEncryptionAlg(gomock.NewController(t))
|
||||
key, secret, err := domain.NewTOTPKey("example.com", "user1", cryptoAlg)
|
||||
require.NoError(t, err)
|
||||
|
||||
sessAgg := &session.NewAggregate("session1", "org1").Aggregate
|
||||
sessAgg := &session.NewAggregate("session1", "instance1").Aggregate
|
||||
userAgg := &user.NewAggregate("user1", "org1").Aggregate
|
||||
|
||||
code, err := totp.GenerateCode(key.Secret(), testNow)
|
||||
@@ -961,8 +959,9 @@ func TestCheckTOTP(t *testing.T) {
|
||||
|
||||
func TestCommands_TerminateSession(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
tokenVerifier func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error)
|
||||
eventstore func(t *testing.T) *eventstore.Eventstore
|
||||
tokenVerifier func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error)
|
||||
checkPermission domain.PermissionCheck
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -982,7 +981,7 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
{
|
||||
"eventstore failed",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilterError(caos_errs.ThrowInternal(nil, "id", "filter failed")),
|
||||
),
|
||||
},
|
||||
@@ -996,11 +995,11 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
{
|
||||
"invalid session token",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -1009,13 +1008,11 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID")),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
return caos_errs.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid")
|
||||
},
|
||||
tokenVerifier: newMockTokenVerifierInvalid(),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
@@ -1027,13 +1024,13 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"not active",
|
||||
"missing permission",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -1042,10 +1039,41 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID")),
|
||||
),
|
||||
),
|
||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
sessionID: "sessionID",
|
||||
sessionToken: "",
|
||||
},
|
||||
res{
|
||||
err: caos_errs.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"not active",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID")),
|
||||
eventFromEventPusher(
|
||||
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
|
||||
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate)),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
@@ -1059,18 +1087,18 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
},
|
||||
res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"push failed",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -1079,13 +1107,13 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID"),
|
||||
),
|
||||
),
|
||||
expectPushFailed(
|
||||
caos_errs.ThrowInternal(nil, "id", "pushed failed"),
|
||||
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate),
|
||||
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
@@ -1102,13 +1130,13 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"terminate",
|
||||
"terminate with token",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
@@ -1117,12 +1145,12 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
},
|
||||
)),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID"),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate),
|
||||
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate),
|
||||
),
|
||||
),
|
||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||
@@ -1136,7 +1164,90 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
},
|
||||
res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"terminate own session",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"user1", "org1", testNow),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID"),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
session.NewTerminateEvent(authz.NewMockContext("instance1", "org1", "user1"), &session.NewAggregate("sessionID", "instance1").Aggregate),
|
||||
),
|
||||
),
|
||||
},
|
||||
args{
|
||||
ctx: authz.NewMockContext("instance1", "org1", "user1"),
|
||||
sessionID: "sessionID",
|
||||
sessionToken: "",
|
||||
},
|
||||
res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"terminate with permission",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
session.NewAddedEvent(context.Background(),
|
||||
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"userID", "org1", testNow),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||
"tokenID"),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
session.NewTerminateEvent(authz.NewMockContext("instance1", "org1", "admin1"), &session.NewAggregate("sessionID", "instance1").Aggregate),
|
||||
),
|
||||
),
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
},
|
||||
args{
|
||||
ctx: authz.NewMockContext("instance1", "org1", "admin1"),
|
||||
sessionID: "sessionID",
|
||||
sessionToken: "",
|
||||
},
|
||||
res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1144,8 +1255,9 @@ func TestCommands_TerminateSession(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
sessionTokenVerifier: tt.fields.tokenVerifier,
|
||||
checkPermission: tt.fields.checkPermission,
|
||||
}
|
||||
got, err := c.TerminateSession(tt.args.ctx, tt.args.sessionID, tt.args.sessionToken)
|
||||
require.ErrorIs(t, err, tt.res.err)
|
||||
|
@@ -29,9 +29,9 @@ func (s *SessionCommands) getHumanWebAuthNTokens(ctx context.Context, userVerifi
|
||||
}
|
||||
|
||||
func (s *SessionCommands) getHumanWebAuthNTokenReadModel(ctx context.Context, userVerification domain.UserVerificationRequirement) (readModel HumanWebAuthNTokensReadModel, err error) {
|
||||
readModel = NewHumanU2FTokensReadModel(s.sessionWriteModel.UserID, "")
|
||||
readModel = NewHumanU2FTokensReadModel(s.sessionWriteModel.UserID, s.sessionWriteModel.UserResourceOwner)
|
||||
if userVerification == domain.UserVerificationRequirementRequired {
|
||||
readModel = NewHumanPasswordlessTokensReadModel(s.sessionWriteModel.UserID, "")
|
||||
readModel = NewHumanPasswordlessTokensReadModel(s.sessionWriteModel.UserID, s.sessionWriteModel.UserResourceOwner)
|
||||
}
|
||||
err = s.eventstore.FilterToQueryReducer(ctx, readModel)
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user