feat: on logout we terminate all sessions from agent (#288)

* feat: on logout we terminate all sessions from agent

* Update eventstore.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Fabi 2020-06-29 09:49:40 +02:00 committed by GitHub
parent 509a993d31
commit 79eff2795f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 20 deletions

View File

@ -227,8 +227,16 @@ func (repo *UserRepo) SetPassword(ctx context.Context, userID, code, password st
return repo.UserEvents.SetPassword(ctx, policy, userID, code, password)
}
func (repo *UserRepo) SignOut(ctx context.Context, agentID, userID string) error {
return repo.UserEvents.SignOut(ctx, agentID, userID)
func (repo *UserRepo) SignOut(ctx context.Context, agentID string) error {
userSessions, err := repo.View.UserSessionsByAgentID(agentID)
if err != nil {
return err
}
userIDs := make([]string, len(userSessions))
for i, session := range userSessions {
userIDs[i] = session.UserID
}
return repo.UserEvents.SignOut(ctx, agentID, userIDs)
}
func (repo *UserRepo) UserByID(ctx context.Context, id string) (*model.UserView, error) {

View File

@ -23,7 +23,7 @@ type UserRepository interface {
AddMfaOTP(ctx context.Context, userID string) (*model.OTP, error)
VerifyMfaOTPSetup(ctx context.Context, userID, code string) error
SignOut(ctx context.Context, agentID, userID string) error
SignOut(ctx context.Context, agentID string) error
UserByID(ctx context.Context, userID string) (*model.UserView, error)
}

View File

@ -1049,17 +1049,24 @@ func (es *UserEventstore) verifyMfaOTP(otp *usr_model.OTP, code string) error {
return nil
}
func (es *UserEventstore) SignOut(ctx context.Context, agentID, userID string) error {
user, err := es.UserByID(ctx, userID)
if err != nil {
return err
}
repoUser := model.UserFromModel(user)
err = es_sdk.Push(ctx, es.PushAggregates, repoUser.AppendEvents, SignOutAggregate(es.AggregateCreator(), repoUser, agentID))
if err != nil {
return err
func (es *UserEventstore) SignOut(ctx context.Context, agentID string, userIDs []string) error {
users := make([]*model.User, len(userIDs))
for i, id := range userIDs {
user, err := es.UserByID(ctx, id)
if err != nil {
return err
}
users[i] = model.UserFromModel(user)
}
es.userCache.cacheUser(repoUser)
aggFunc := SignOutAggregates(es.AggregateCreator(), users, agentID)
aggregates, err := aggFunc(ctx)
if err != nil {
return err
}
err = es_sdk.PushAggregates(ctx, es.PushAggregates, nil, aggregates...)
if err != nil {
return err
}
return nil
}

View File

@ -630,13 +630,18 @@ func MfaOTPRemoveAggregate(aggCreator *es_models.AggregateCreator, existing *mod
}
}
func SignOutAggregate(aggCreator *es_models.AggregateCreator, existing *model.User, agentID string) func(ctx context.Context) (*es_models.Aggregate, error) {
return func(ctx context.Context) (*es_models.Aggregate, error) {
agg, err := UserAggregateOverwriteContext(ctx, aggCreator, existing, existing.ResourceOwner, existing.AggregateID)
if err != nil {
return nil, err
func SignOutAggregates(aggCreator *es_models.AggregateCreator, existingUsers []*model.User, agentID string) func(ctx context.Context) ([]*es_models.Aggregate, error) {
return func(ctx context.Context) ([]*es_models.Aggregate, error) {
aggregates := make([]*es_models.Aggregate, len(existingUsers))
for i, existing := range existingUsers {
agg, err := UserAggregateOverwriteContext(ctx, aggCreator, existing, existing.ResourceOwner, existing.AggregateID)
if err != nil {
return nil, err
}
agg.AppendEvent(model.SignedOut, map[string]interface{}{"userAgentID": agentID})
aggregates[i] = agg
}
return agg.AppendEvent(model.SignedOut, map[string]interface{}{"userAgentID": agentID})
return aggregates, nil
}
}

View File

@ -66,7 +66,7 @@ func (o *OPStorage) TerminateSession(ctx context.Context, userID, clientID strin
if !ok {
return errors.ThrowPreconditionFailed(nil, "OIDC-fso7F", "no user agent id")
}
return o.repo.SignOut(ctx, userAgentID, userID)
return o.repo.SignOut(ctx, userAgentID)
}
func (o *OPStorage) GetSigningKey(ctx context.Context, keyCh chan<- jose.SigningKey, errCh chan<- error, timer <-chan time.Time) {