store project ID in the access token

This commit is contained in:
Tim Möhlmann
2024-04-04 18:52:22 +03:00
parent 25a2cd4aa4
commit 5f0262f239
22 changed files with 115 additions and 60 deletions

27
cmd/setup/26.go Normal file
View File

@@ -0,0 +1,27 @@
package setup
import (
"context"
_ "embed"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/eventstore"
)
var (
//go:embed 26.sql
addTokenProjectID string
)
type AddProjectIDToAuthTokens struct {
dbClient *database.DB
}
func (mig *AddProjectIDToAuthTokens) Execute(ctx context.Context, _ eventstore.Event) error {
_, err := mig.dbClient.ExecContext(ctx, addTokenProjectID)
return err
}
func (mig *AddProjectIDToAuthTokens) String() string {
return "26_add_project_id_col_to_auth_tokens"
}

1
cmd/setup/26.sql Normal file
View File

@@ -0,0 +1 @@
ALTER TABLE auth.tokens ADD COLUMN project_id varchar null;

View File

@@ -104,6 +104,7 @@ type Steps struct {
s23CorrectGlobalUniqueConstraints *CorrectGlobalUniqueConstraints
s24AddActorToAuthTokens *AddActorToAuthTokens
s25User11AddLowerFieldsToVerifiedEmail *User11AddLowerFieldsToVerifiedEmail
s26AddProjectIDToAuthTokens *AddProjectIDToAuthTokens
}
func MustNewSteps(v *viper.Viper) *Steps {

View File

@@ -138,6 +138,7 @@ func Setup(config *Config, steps *Steps, masterKey string) {
steps.s23CorrectGlobalUniqueConstraints = &CorrectGlobalUniqueConstraints{dbClient: esPusherDBClient}
steps.s24AddActorToAuthTokens = &AddActorToAuthTokens{dbClient: queryDBClient}
steps.s25User11AddLowerFieldsToVerifiedEmail = &User11AddLowerFieldsToVerifiedEmail{dbClient: esPusherDBClient}
steps.s26AddProjectIDToAuthTokens = &AddProjectIDToAuthTokens{dbClient: queryDBClient}
err = projection.Create(ctx, projectionDBClient, eventstoreClient, config.Projections, nil, nil, nil)
logging.OnError(err).Fatal("unable to start projections")
@@ -175,6 +176,7 @@ func Setup(config *Config, steps *Steps, masterKey string) {
steps.s22ActiveInstancesIndex,
steps.s23CorrectGlobalUniqueConstraints,
steps.s24AddActorToAuthTokens,
steps.s26AddProjectIDToAuthTokens,
} {
mustExecuteMigration(ctx, eventstoreClient, step, "migration failed")
}

View File

@@ -23,6 +23,7 @@ type accessToken struct {
resourceOwner string
subject string
clientID string
projectID string
audience []string
scope []string
authMethods []domain.UserAuthMethodType
@@ -75,6 +76,7 @@ func accessTokenV1(tokenID, subject string, token *model.TokenView) *accessToken
resourceOwner: token.ResourceOwner,
subject: subject,
clientID: token.ApplicationID,
projectID: token.ProjectID,
audience: token.Audience,
scope: token.Scopes,
tokenCreation: token.CreationDate,
@@ -91,6 +93,7 @@ func accessTokenV2(tokenID, subject string, token *query.OIDCSessionAccessTokenR
resourceOwner: token.ResourceOwner,
subject: subject,
clientID: token.ClientID,
projectID: token.ProjectID,
audience: token.Audience,
scope: token.Scope,
authMethods: token.AuthMethods,

View File

@@ -218,7 +218,7 @@ func (o *OPStorage) CreateAccessToken(ctx context.Context, req op.TokenRequest)
}()
if authReq, ok := req.(*AuthRequestV2); ok {
activity.Trigger(ctx, "", authReq.CurrentAuthRequest.UserID, activity.OIDCAccessToken, o.eventstore.FilterToQueryReducer)
return o.command.AddOIDCSessionAccessToken(setContextUserSystem(ctx), authReq.GetID())
return o.command.AddOIDCSessionAccessToken(setContextUserSystem(ctx), authReq.GetID(), "")
}
userAgentID, applicationID, userOrgID, authTime, amr, reason, actor := getInfoFromRequest(req)
@@ -227,7 +227,7 @@ func (o *OPStorage) CreateAccessToken(ctx context.Context, req op.TokenRequest)
return "", time.Time{}, err
}
resp, err := o.command.AddUserToken(setContextUserSystem(ctx), userOrgID, userAgentID, applicationID, req.GetSubject(), req.GetAudience(), req.GetScopes(), amr, accessTokenLifetime, authTime, reason, actor)
resp, err := o.command.AddUserToken(setContextUserSystem(ctx), userOrgID, userAgentID, applicationID, "", req.GetSubject(), req.GetAudience(), req.GetScopes(), amr, accessTokenLifetime, authTime, reason, actor)
if err != nil {
return "", time.Time{}, err
}
@@ -249,7 +249,7 @@ func (o *OPStorage) CreateAccessAndRefreshTokens(ctx context.Context, req op.Tok
case *AuthRequestV2:
// trigger activity log for authentication for user
activity.Trigger(ctx, "", tokenReq.GetSubject(), activity.OIDCRefreshToken, o.eventstore.FilterToQueryReducer)
return o.command.AddOIDCSessionRefreshAndAccessToken(setContextUserSystem(ctx), tokenReq.GetID())
return o.command.AddOIDCSessionRefreshAndAccessToken(setContextUserSystem(ctx), tokenReq.GetID(), "")
case *RefreshTokenRequestV2:
// trigger activity log for authentication for user
activity.Trigger(ctx, "", tokenReq.GetSubject(), activity.OIDCRefreshToken, o.eventstore.FilterToQueryReducer)
@@ -270,7 +270,7 @@ func (o *OPStorage) CreateAccessAndRefreshTokens(ctx context.Context, req op.Tok
return "", "", time.Time{}, err
}
resp, token, err := o.command.AddAccessAndRefreshToken(setContextUserSystem(ctx), userOrgID, userAgentID, applicationID, req.GetSubject(),
resp, token, err := o.command.AddAccessAndRefreshToken(setContextUserSystem(ctx), userOrgID, userAgentID, applicationID, "", req.GetSubject(),
refreshToken, req.GetAudience(), scopes, authMethodsReferences, accessTokenLifetime,
refreshTokenIdleExpiration, refreshTokenExpiration, authTime, reason, actor) //PLANNED: lifetime from client
if err != nil {

View File

@@ -249,7 +249,7 @@ func (s *Server) createExchangeTokens(ctx context.Context, tokenType oidc.TokenT
resp.IssuedTokenType = oidc.JWTTokenType
case oidc.IDTokenType:
resp.AccessToken, resp.ExpiresIn, err = s.createExchangeIDToken(ctx, signingKey, client, subjectToken.userID, "", audience, userInfo, actorToken.authMethods, actorToken.authTime, reason, actor)
resp.AccessToken, resp.ExpiresIn, err = s.createExchangeIDToken(ctx, signingKey, client, subjectToken.userID, "", audience, userInfo, actorToken.authMethods, actorToken.authTime, actor)
resp.TokenType = TokenTypeNA
resp.IssuedTokenType = oidc.IDTokenType
case oidc.RefreshTokenType, UserIDTokenType:
@@ -262,7 +262,7 @@ func (s *Server) createExchangeTokens(ctx context.Context, tokenType oidc.TokenT
}
if slices.Contains(scopes, oidc.ScopeOpenID) && tokenType != oidc.IDTokenType {
resp.IDToken, _, err = s.createExchangeIDToken(ctx, signingKey, client, subjectToken.userID, resp.AccessToken, audience, userInfo, actorToken.authMethods, actorToken.authTime, reason, actor)
resp.IDToken, _, err = s.createExchangeIDToken(ctx, signingKey, client, subjectToken.userID, resp.AccessToken, audience, userInfo, actorToken.authMethods, actorToken.authTime, actor)
if err != nil {
return nil, err
}
@@ -306,7 +306,7 @@ func (s *Server) createExchangeJWT(ctx context.Context, signingKey op.SigningKey
return accessToken, refreshToken, timeToOIDCExpiresIn(expTime), nil
}
func (s *Server) createExchangeIDToken(ctx context.Context, signingKey op.SigningKey, client *Client, userID, accessToken string, audience []string, userInfo *oidc.UserInfo, authMethods []domain.UserAuthMethodType, authTime time.Time, reason domain.TokenReason, actor *domain.TokenActor) (idToken string, exp uint64, err error) {
func (s *Server) createExchangeIDToken(ctx context.Context, signingKey op.SigningKey, client *Client, userID, accessToken string, audience []string, userInfo *oidc.UserInfo, authMethods []domain.UserAuthMethodType, authTime time.Time, actor *domain.TokenActor) (idToken string, exp uint64, err error) {
expTime := time.Now().Add(client.IDTokenLifetime()).Add(client.ClockSkew())
claims := oidc.NewIDTokenClaims(op.IssuerFromContext(ctx), userID, audience, expTime, authTime, "", "", AuthMethodTypesToAMR(authMethods), client.GetID(), client.ClockSkew())
claims.Actor = actorDomainToClaims(actor)
@@ -333,15 +333,14 @@ func (s *Server) createAccessTokenCommands(ctx context.Context, client *Client,
settings := client.client.Settings
if slices.Contains(scopes, oidc.ScopeOfflineAccess) {
return s.command.AddAccessAndRefreshToken(
ctx, resourceOwner, "", client.GetID(), userID, "", audience, scopes, AuthMethodTypesToAMR(authMethods),
settings.AccessTokenLifetime, settings.RefreshTokenIdleExpiration, settings.RefreshTokenExpiration,
authTime, reason, actor,
ctx, resourceOwner, "", client.GetID(), client.client.ProjectID, userID, "", audience, scopes,
AuthMethodTypesToAMR(authMethods), settings.AccessTokenLifetime, settings.RefreshTokenIdleExpiration,
settings.RefreshTokenExpiration, authTime, reason, actor,
)
}
tokenInfo, err = s.command.AddUserToken(
ctx, resourceOwner, "", client.GetID(), userID, audience, scopes, AuthMethodTypesToAMR(authMethods),
settings.AccessTokenLifetime,
authTime, reason, actor,
ctx, resourceOwner, "", client.GetID(), client.client.ProjectID, userID, audience, scopes,
AuthMethodTypesToAMR(authMethods), settings.AccessTokenLifetime, authTime, reason, actor,
)
return tokenInfo, "", err
}

View File

@@ -41,7 +41,7 @@ func (s *Server) UserInfo(ctx context.Context, r *op.Request[oidc.UserInfoReques
if err != nil {
return nil, op.NewStatusError(oidc.ErrAccessDenied().WithDescription("access token invalid").WithParent(err), http.StatusUnauthorized)
}
userInfo, err := s.userInfo(ctx, token.userID, "", token.scope, token.audience)
userInfo, err := s.userInfo(ctx, token.userID, token.projectID, token.scope, token.audience)
if err != nil {
return nil, err
}

View File

@@ -30,13 +30,13 @@ const (
// AddOIDCSessionAccessToken creates a new OIDC Session, creates an access token and returns its id and expiration.
// If the underlying [AuthRequest] is a OIDC Auth Code Flow, it will set the code as exchanged.
func (c *Commands) AddOIDCSessionAccessToken(ctx context.Context, authRequestID string) (string, time.Time, error) {
func (c *Commands) AddOIDCSessionAccessToken(ctx context.Context, authRequestID, projectID string) (string, time.Time, error) {
cmd, err := c.newOIDCSessionAddEvents(ctx, authRequestID)
if err != nil {
return "", time.Time{}, err
}
cmd.AddSession(ctx)
if err = cmd.AddAccessToken(ctx, cmd.authRequestWriteModel.Scope, domain.TokenReasonAuthRequest, nil); err != nil {
cmd.AddSession(ctx, projectID)
if err = cmd.AddAccessToken(ctx, projectID, cmd.authRequestWriteModel.Scope, domain.TokenReasonAuthRequest, nil); err != nil {
return "", time.Time{}, err
}
cmd.SetAuthRequestSuccessful(ctx)
@@ -47,13 +47,13 @@ func (c *Commands) AddOIDCSessionAccessToken(ctx context.Context, authRequestID
// AddOIDCSessionRefreshAndAccessToken creates a new OIDC Session, creates an access token and refresh token.
// It returns the access token id, expiration and the refresh token.
// If the underlying [AuthRequest] is a OIDC Auth Code Flow, it will set the code as exchanged.
func (c *Commands) AddOIDCSessionRefreshAndAccessToken(ctx context.Context, authRequestID string) (tokenID, refreshToken string, tokenExpiration time.Time, err error) {
func (c *Commands) AddOIDCSessionRefreshAndAccessToken(ctx context.Context, authRequestID, projectID string) (tokenID, refreshToken string, tokenExpiration time.Time, err error) {
cmd, err := c.newOIDCSessionAddEvents(ctx, authRequestID)
if err != nil {
return "", "", time.Time{}, err
}
cmd.AddSession(ctx)
if err = cmd.AddAccessToken(ctx, cmd.authRequestWriteModel.Scope, domain.TokenReasonAuthRequest, nil); err != nil {
cmd.AddSession(ctx, projectID)
if err = cmd.AddAccessToken(ctx, projectID, cmd.authRequestWriteModel.Scope, domain.TokenReasonAuthRequest, nil); err != nil {
return "", "", time.Time{}, err
}
if err = cmd.AddRefreshToken(ctx); err != nil {
@@ -70,7 +70,7 @@ func (c *Commands) ExchangeOIDCSessionRefreshAndAccessToken(ctx context.Context,
if err != nil {
return "", "", time.Time{}, err
}
if err = cmd.AddAccessToken(ctx, scope, domain.TokenReasonRefresh, nil); err != nil {
if err = cmd.AddAccessToken(ctx, cmd.oidcSessionWriteModel.ProjectID, scope, domain.TokenReasonRefresh, nil); err != nil {
return "", "", time.Time{}, err
}
if err = cmd.RenewRefreshToken(ctx); err != nil {
@@ -273,7 +273,7 @@ type OIDCSessionEvents struct {
refreshToken string
}
func (c *OIDCSessionEvents) AddSession(ctx context.Context) {
func (c *OIDCSessionEvents) AddSession(ctx context.Context, projectID string) {
c.events = append(c.events, oidcsession.NewAddedEvent(
ctx,
c.oidcSessionWriteModel.aggregate,
@@ -291,13 +291,13 @@ func (c *OIDCSessionEvents) SetAuthRequestSuccessful(ctx context.Context) {
c.events = append(c.events, authrequest.NewSucceededEvent(ctx, c.authRequestWriteModel.aggregate))
}
func (c *OIDCSessionEvents) AddAccessToken(ctx context.Context, scope []string, reason domain.TokenReason, actor *domain.TokenActor) error {
func (c *OIDCSessionEvents) AddAccessToken(ctx context.Context, projectID string, scope []string, reason domain.TokenReason, actor *domain.TokenActor) error {
accessTokenID, err := c.idGenerator.Next()
if err != nil {
return err
}
c.accessTokenID = AccessTokenPrefix + accessTokenID
c.events = append(c.events, oidcsession.NewAccessTokenAddedEvent(ctx, c.oidcSessionWriteModel.aggregate, c.accessTokenID, scope, c.accessTokenLifetime, reason, actor))
c.events = append(c.events, oidcsession.NewAccessTokenAddedEvent(ctx, c.oidcSessionWriteModel.aggregate, c.accessTokenID, projectID, scope, c.accessTokenLifetime, reason, actor))
return nil
}

View File

@@ -15,6 +15,7 @@ type OIDCSessionWriteModel struct {
UserID string
SessionID string
ClientID string
ProjectID string
Audience []string
Scope []string
AuthMethods []domain.UserAuthMethodType
@@ -101,6 +102,7 @@ func (wm *OIDCSessionWriteModel) reduceAdded(e *oidcsession.AddedEvent) {
func (wm *OIDCSessionWriteModel) reduceAccessTokenAdded(e *oidcsession.AccessTokenAddedEvent) {
wm.AccessTokenID = e.ID
wm.ProjectID = e.ProjectID
wm.AccessTokenExpiration = e.CreationDate().Add(e.Lifetime)
wm.AccessTokenReason = e.Reason
wm.AccessTokenActor = e.Actor

View File

@@ -196,7 +196,7 @@ func TestCommands_AddOIDCSessionAccessToken(t *testing.T) {
oidcsession.NewAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"userID", "sessionID", "clientID", []string{"audience"}, []string{"openid"}, []domain.UserAuthMethodType{domain.UserAuthMethodTypePassword}, testNow),
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"at_accessTokenID", "projectID", []string{"openid"}, time.Hour, domain.TokenReasonAuthRequest, nil),
authrequest.NewSucceededEvent(context.Background(), &authrequest.NewAggregate("V2_authRequestID", "instanceID").Aggregate),
),
),
@@ -223,7 +223,7 @@ func TestCommands_AddOIDCSessionAccessToken(t *testing.T) {
defaultRefreshTokenIdleLifetime: tt.fields.defaultRefreshTokenIdleLifetime,
keyAlgorithm: tt.fields.keyAlgorithm,
}
gotID, gotExpiration, err := c.AddOIDCSessionAccessToken(tt.args.ctx, tt.args.authRequestID)
gotID, gotExpiration, err := c.AddOIDCSessionAccessToken(tt.args.ctx, tt.args.authRequestID, "projectID")
assert.Equal(t, tt.res.id, gotID)
assert.Equal(t, tt.res.expiration, gotExpiration)
assert.ErrorIs(t, err, tt.res.err)
@@ -397,7 +397,7 @@ func TestCommands_AddOIDCSessionRefreshAndAccessToken(t *testing.T) {
oidcsession.NewAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"userID", "sessionID", "clientID", []string{"audience"}, []string{"openid", "offline_access"}, []domain.UserAuthMethodType{domain.UserAuthMethodTypePassword}, testNow),
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"at_accessTokenID", "projectID", []string{"openid", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
oidcsession.NewRefreshTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"rt_refreshTokenID", 7*24*time.Hour, 24*time.Hour),
authrequest.NewSucceededEvent(context.Background(), &authrequest.NewAggregate("V2_authRequestID", "instanceID").Aggregate),
@@ -430,7 +430,7 @@ func TestCommands_AddOIDCSessionRefreshAndAccessToken(t *testing.T) {
defaultRefreshTokenIdleLifetime: tt.fields.defaultRefreshTokenIdleLifetime,
keyAlgorithm: tt.fields.keyAlgorithm,
}
gotID, gotRefreshToken, gotExpiration, err := c.AddOIDCSessionRefreshAndAccessToken(tt.args.ctx, tt.args.authRequestID)
gotID, gotRefreshToken, gotExpiration, err := c.AddOIDCSessionRefreshAndAccessToken(tt.args.ctx, tt.args.authRequestID, "projectID")
assert.Equal(t, tt.res.id, gotID)
assert.Equal(t, tt.res.refreshToken, gotRefreshToken)
assert.Equal(t, tt.res.expiration, gotExpiration)
@@ -509,7 +509,7 @@ func TestCommands_ExchangeOIDCSessionRefreshAndAccessToken(t *testing.T) {
),
eventFromEventPusher(
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"accessTokenID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"accessTokenID", "projectID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
),
),
),
@@ -535,7 +535,7 @@ func TestCommands_ExchangeOIDCSessionRefreshAndAccessToken(t *testing.T) {
),
eventFromEventPusher(
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"at_accessTokenID", "projectID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
),
eventFromEventPusher(
oidcsession.NewRefreshTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
@@ -565,7 +565,7 @@ func TestCommands_ExchangeOIDCSessionRefreshAndAccessToken(t *testing.T) {
),
eventFromEventPusherWithCreationDateNow(
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"at_accessTokenID", "projectID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
),
eventFromEventPusherWithCreationDateNow(
oidcsession.NewRefreshTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
@@ -575,7 +575,7 @@ func TestCommands_ExchangeOIDCSessionRefreshAndAccessToken(t *testing.T) {
expectFilter(), // token lifetime
expectPush(
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid", "offline_access"}, time.Hour, domain.TokenReasonRefresh, nil),
"at_accessTokenID", "projectID", []string{"openid", "offline_access"}, time.Hour, domain.TokenReasonRefresh, nil),
oidcsession.NewRefreshTokenRenewedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"rt_refreshTokenID2", 24*time.Hour),
),
@@ -682,7 +682,7 @@ func TestCommands_OIDCSessionByRefreshToken(t *testing.T) {
),
eventFromEventPusher(
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"at_accessTokenID", "projectID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
),
),
),
@@ -707,7 +707,7 @@ func TestCommands_OIDCSessionByRefreshToken(t *testing.T) {
),
eventFromEventPusher(
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"at_accessTokenID", "projectID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
),
eventFromEventPusher(
oidcsession.NewRefreshTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
@@ -736,7 +736,7 @@ func TestCommands_OIDCSessionByRefreshToken(t *testing.T) {
),
eventFromEventPusherWithCreationDateNow(
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"at_accessTokenID", "projectID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
),
eventFromEventPusherWithCreationDateNow(
oidcsession.NewRefreshTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
@@ -892,7 +892,7 @@ func TestCommands_RevokeOIDCSessionToken(t *testing.T) {
),
eventFromEventPusherWithCreationDateNow(
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"at_accessTokenID", "projectID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
),
eventFromEventPusherWithCreationDateNow(
oidcsession.NewRefreshTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
@@ -969,7 +969,7 @@ func TestCommands_RevokeOIDCSessionToken(t *testing.T) {
),
eventFromEventPusherWithCreationDateNow(
oidcsession.NewAccessTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
"at_accessTokenID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
"at_accessTokenID", "projectID", []string{"openid", "profile", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest, nil),
),
eventFromEventPusherWithCreationDateNow(
oidcsession.NewRefreshTokenAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,

View File

@@ -237,6 +237,7 @@ func (c *Commands) AddUserToken(
orgID,
agentID,
clientID,
projectID,
userID string,
audience,
scopes,
@@ -250,7 +251,7 @@ func (c *Commands) AddUserToken(
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-Dbge4", "Errors.IDMissing")
}
userWriteModel := NewUserWriteModel(userID, orgID)
cmds, accessToken, err := c.addUserToken(ctx, userWriteModel, agentID, clientID, "", audience, scopes, authMethodsReferences, lifetime, authTime, reason, actor)
cmds, accessToken, err := c.addUserToken(ctx, userWriteModel, agentID, clientID, projectID, "", audience, scopes, authMethodsReferences, lifetime, authTime, reason, actor)
if err != nil {
return nil, err
}
@@ -277,7 +278,7 @@ func (c *Commands) RevokeAccessToken(ctx context.Context, userID, orgID, tokenID
return writeModelToObjectDetails(&accessTokenWriteModel.WriteModel), nil
}
func (c *Commands) addUserToken(ctx context.Context, userWriteModel *UserWriteModel, agentID, clientID, refreshTokenID string, audience, scopes, authMethodsReferences []string, lifetime time.Duration, authTime time.Time, reason domain.TokenReason, actor *domain.TokenActor) ([]eventstore.Command, *domain.Token, error) {
func (c *Commands) addUserToken(ctx context.Context, userWriteModel *UserWriteModel, agentID, clientID, projectID, refreshTokenID string, audience, scopes, authMethodsReferences []string, lifetime time.Duration, authTime time.Time, reason domain.TokenReason, actor *domain.TokenActor) ([]eventstore.Command, *domain.Token, error) {
err := c.eventstore.FilterToQueryReducer(ctx, userWriteModel)
if err != nil {
return nil, nil, err
@@ -312,7 +313,7 @@ func (c *Commands) addUserToken(ctx context.Context, userWriteModel *UserWriteMo
}
cmds = append(cmds,
user.NewUserTokenAddedEvent(ctx, userAgg, tokenID, clientID, agentID, preferredLanguage, refreshTokenID, audience, scopes, authMethodsReferences, authTime, expiration, reason, actor),
user.NewUserTokenAddedEvent(ctx, userAgg, tokenID, clientID, projectID, agentID, preferredLanguage, refreshTokenID, audience, scopes, authMethodsReferences, authTime, expiration, reason, actor),
)
return cmds, &domain.Token{

View File

@@ -13,6 +13,7 @@ type UserAccessTokenWriteModel struct {
TokenID string
ApplicationID string
ProjectID string
UserAgentID string
Audience []string
Scopes []string
@@ -66,6 +67,7 @@ func (wm *UserAccessTokenWriteModel) Reduce() error {
case *user.UserTokenAddedEvent:
wm.TokenID = e.TokenID
wm.ApplicationID = e.ApplicationID
wm.ProjectID = e.ProjectID
wm.UserAgentID = e.UserAgentID
wm.Audience = e.Audience
wm.Scopes = e.Scopes

View File

@@ -15,6 +15,7 @@ func (c *Commands) AddAccessAndRefreshToken(
orgID,
agentID,
clientID,
projectID,
userID,
refreshToken string,
audience,
@@ -28,9 +29,9 @@ func (c *Commands) AddAccessAndRefreshToken(
actor *domain.TokenActor,
) (accessToken *domain.Token, newRefreshToken string, err error) {
if refreshToken == "" {
return c.AddNewRefreshTokenAndAccessToken(ctx, userID, orgID, agentID, clientID, audience, scopes, authMethodsReferences, refreshExpiration, accessLifetime, refreshIdleExpiration, authTime, reason, actor)
return c.AddNewRefreshTokenAndAccessToken(ctx, userID, orgID, agentID, clientID, projectID, audience, scopes, authMethodsReferences, refreshExpiration, accessLifetime, refreshIdleExpiration, authTime, reason, actor)
}
return c.RenewRefreshTokenAndAccessToken(ctx, userID, orgID, refreshToken, agentID, clientID, audience, scopes, refreshIdleExpiration, accessLifetime, actor)
return c.RenewRefreshTokenAndAccessToken(ctx, userID, orgID, refreshToken, agentID, clientID, projectID, audience, scopes, refreshIdleExpiration, accessLifetime, actor)
}
func (c *Commands) AddNewRefreshTokenAndAccessToken(
@@ -38,7 +39,8 @@ func (c *Commands) AddNewRefreshTokenAndAccessToken(
userID,
orgID,
agentID,
clientID string,
clientID,
projectID string,
audience,
scopes,
authMethodsReferences []string,
@@ -57,7 +59,7 @@ func (c *Commands) AddNewRefreshTokenAndAccessToken(
if err != nil {
return nil, "", err
}
cmds, accessToken, err := c.addUserToken(ctx, userWriteModel, agentID, clientID, refreshTokenID, audience, scopes, authMethodsReferences, accessLifetime, authTime, reason, actor)
cmds, accessToken, err := c.addUserToken(ctx, userWriteModel, agentID, clientID, projectID, refreshTokenID, audience, scopes, authMethodsReferences, accessLifetime, authTime, reason, actor)
if err != nil {
return nil, "", err
}
@@ -79,7 +81,8 @@ func (c *Commands) RenewRefreshTokenAndAccessToken(
orgID,
refreshToken,
agentID,
clientID string,
clientID,
projectID string,
audience,
scopes []string,
idleExpiration,
@@ -91,7 +94,7 @@ func (c *Commands) RenewRefreshTokenAndAccessToken(
return nil, "", err
}
userWriteModel := NewUserWriteModel(userID, orgID)
cmds, accessToken, err := c.addUserToken(ctx, userWriteModel, agentID, clientID, renewed.tokenID, audience, scopes, renewed.authMethodsReferences, accessLifetime, renewed.authTime, domain.TokenReasonRefresh, actor)
cmds, accessToken, err := c.addUserToken(ctx, userWriteModel, agentID, clientID, projectID, renewed.tokenID, audience, scopes, renewed.authMethodsReferences, accessLifetime, renewed.authTime, domain.TokenReasonRefresh, actor)
if err != nil {
return nil, "", err
}

View File

@@ -296,7 +296,7 @@ func TestCommands_AddAccessAndRefreshToken(t *testing.T) {
idGenerator: tt.fields.idGenerator,
keyAlgorithm: tt.fields.keyAlgorithm,
}
got, gotRefresh, err := c.AddAccessAndRefreshToken(tt.args.ctx, tt.args.orgID, tt.args.agentID, tt.args.clientID, tt.args.userID, tt.args.refreshToken,
got, gotRefresh, err := c.AddAccessAndRefreshToken(tt.args.ctx, tt.args.orgID, tt.args.agentID, tt.args.clientID, "projectID", tt.args.userID, tt.args.refreshToken,
tt.args.audience, tt.args.scopes, tt.args.authMethodsReferences, tt.args.lifetime, tt.args.refreshIdleExpiration, tt.args.refreshExpiration, tt.args.authTime, tt.args.reason, tt.args.actor)
if tt.res.err == nil {
assert.NoError(t, err)

View File

@@ -1504,7 +1504,7 @@ func TestCommandSide_AddUserToken(t *testing.T) {
eventstore: tt.fields.eventstore,
idGenerator: tt.fields.idGenerator,
}
got, err := r.AddUserToken(tt.args.ctx, tt.args.orgID, tt.args.agentID, tt.args.clientID, tt.args.userID, tt.args.audience, tt.args.scopes, tt.args.authMethodsReferences, tt.args.lifetime, tt.args.authTime, tt.args.reason, tt.args.actor)
got, err := r.AddUserToken(tt.args.ctx, tt.args.orgID, tt.args.agentID, tt.args.clientID, "projectID", tt.args.userID, tt.args.audience, tt.args.scopes, tt.args.authMethodsReferences, tt.args.lifetime, tt.args.authTime, tt.args.reason, tt.args.actor)
if tt.res.err == nil {
assert.NoError(t, err)
}
@@ -1564,6 +1564,7 @@ func TestCommands_RevokeAccessToken(t *testing.T) {
&user.NewAggregate("userID", "orgID").Aggregate,
"tokenID",
"clientID",
"projectID",
"agentID",
"de",
"refreshTokenID",
@@ -1600,6 +1601,7 @@ func TestCommands_RevokeAccessToken(t *testing.T) {
&user.NewAggregate("userID", "orgID").Aggregate,
"tokenID",
"clientID",
"projectID",
"agentID",
"de",
"refreshTokenID",

View File

@@ -20,6 +20,7 @@ type OIDCSessionAccessTokenReadModel struct {
UserID string
SessionID string
ClientID string
ProjectID string
Audience []string
Scope []string
AuthMethods []domain.UserAuthMethodType
@@ -84,6 +85,7 @@ func (wm *OIDCSessionAccessTokenReadModel) reduceAdded(e *oidcsession.AddedEvent
func (wm *OIDCSessionAccessTokenReadModel) reduceAccessTokenAdded(e *oidcsession.AccessTokenAddedEvent) {
wm.AccessTokenID = e.ID
wm.ProjectID = e.ProjectID
wm.AccessTokenCreation = e.CreationDate()
wm.AccessTokenExpiration = e.CreationDate().Add(e.Lifetime)
wm.Reason = e.Reason

View File

@@ -24,6 +24,7 @@ type AddedEvent struct {
LoginClient string `json:"login_client"`
ClientID string `json:"client_id"`
ProjectID string `json:"project_id"`
RedirectURI string `json:"redirect_uri"`
State string `json:"state,omitempty"`
Nonce string `json:"nonce,omitempty"`

View File

@@ -22,7 +22,7 @@ type AddedEvent struct {
eventstore.BaseEvent `json:"-"`
UserID string `json:"userID"`
SessionID string `json:"sessionID"`
SessionID string `json:"sessionID,omitempty"`
ClientID string `json:"clientID"`
Audience []string `json:"audience"`
Scope []string `json:"scope"`
@@ -71,11 +71,12 @@ func NewAddedEvent(ctx context.Context,
type AccessTokenAddedEvent struct {
eventstore.BaseEvent `json:"-"`
ID string `json:"id,omitempty"`
Scope []string `json:"scope,omitempty"`
Lifetime time.Duration `json:"lifetime,omitempty"`
Reason domain.TokenReason `json:"reason,omitempty"`
Actor *domain.TokenActor `json:"actor,omitempty"`
ID string `json:"id,omitempty"`
ProjectID string `json:"project_id,omitempty"`
Scope []string `json:"scope,omitempty"`
Lifetime time.Duration `json:"lifetime,omitempty"`
Reason domain.TokenReason `json:"reason,omitempty"`
Actor *domain.TokenActor `json:"actor,omitempty"`
}
func (e *AccessTokenAddedEvent) Payload() interface{} {
@@ -93,7 +94,8 @@ func (e *AccessTokenAddedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
func NewAccessTokenAddedEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
id string,
id,
projectID string,
scope []string,
lifetime time.Duration,
reason domain.TokenReason,
@@ -105,11 +107,12 @@ func NewAccessTokenAddedEvent(
aggregate,
AccessTokenAddedType,
),
ID: id,
Scope: scope,
Lifetime: lifetime,
Reason: reason,
Actor: actor,
ID: id,
ProjectID: projectID,
Scope: scope,
Lifetime: lifetime,
Reason: reason,
Actor: actor,
}
}

View File

@@ -212,6 +212,7 @@ type UserTokenAddedEvent struct {
TokenID string `json:"tokenId,omitempty"`
ApplicationID string `json:"applicationId,omitempty"`
ProjectID string `json:"projectID,omitempty"`
UserAgentID string `json:"userAgentId,omitempty"`
RefreshTokenID string `json:"refreshTokenID,omitempty"`
Audience []string `json:"audience,omitempty"`
@@ -237,6 +238,7 @@ func NewUserTokenAddedEvent(
aggregate *eventstore.Aggregate,
tokenID,
applicationID,
projectID,
userAgentID,
preferredLanguage,
refreshTokenID string,
@@ -256,6 +258,7 @@ func NewUserTokenAddedEvent(
),
TokenID: tokenID,
ApplicationID: applicationID,
ProjectID: projectID,
UserAgentID: userAgentID,
RefreshTokenID: refreshTokenID,
Audience: audience,

View File

@@ -14,6 +14,7 @@ type TokenView struct {
ResourceOwner string
UserID string
ApplicationID string
ProjectID string
UserAgentID string
Audience []string
Expiration time.Time

View File

@@ -33,6 +33,7 @@ type TokenView struct {
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
UserID string `json:"-" gorm:"column:user_id"`
ApplicationID string `json:"applicationId" gorm:"column:application_id"`
ProjectID string `json:"projectID" gorm:"column:project_id"`
UserAgentID string `json:"userAgentId" gorm:"column:user_agent_id"`
Audience database.TextArray[string] `json:"audience" gorm:"column:audience"`
Scopes database.TextArray[string] `json:"scopes" gorm:"column:scopes"`
@@ -87,6 +88,7 @@ func TokenViewToModel(token *TokenView) *usr_model.TokenView {
ResourceOwner: token.ResourceOwner,
UserID: token.UserID,
ApplicationID: token.ApplicationID,
ProjectID: token.ProjectID,
UserAgentID: token.UserAgentID,
Audience: token.Audience,
Scopes: token.Scopes,