mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 19:17:32 +00:00
feat(oidc): token exchange impersonation (#7516)
* add token exchange feature flag * allow setting reason and actor to access tokens * impersonation * set token types and scopes in response * upgrade oidc to working draft state * fix tests * audience and scope validation * id toke and jwt as input * return id tokens * add grant type token exchange to app config * add integration tests * check and deny actors in api calls * fix instance setting tests by triggering projection on write and cleanup * insert sleep statements again * solve linting issues * add translations * pin oidc v3.15.0 * resolve comments, add event translation * fix refreshtoken test * use ValidateAuthReqScopes from oidc * apparently the linter can't make up its mind * persist actor thru refresh tokens and check in tests * remove unneeded triggers
This commit is contained in:
@@ -42,6 +42,7 @@ func init() {
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, UserReactivatedType, UserReactivatedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, UserRemovedType, UserRemovedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, UserTokenAddedType, UserTokenAddedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, UserImpersonatedType, eventstore.GenericEventMapper[UserImpersonatedEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, UserTokenRemovedType, UserTokenRemovedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, UserDomainClaimedType, DomainClaimedEventMapper)
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, UserDomainClaimedSentType, DomainClaimedSentEventMapper)
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@@ -18,16 +19,17 @@ const (
|
||||
type HumanRefreshTokenAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
TokenID string `json:"tokenId"`
|
||||
ClientID string `json:"clientId"`
|
||||
UserAgentID string `json:"userAgentId"`
|
||||
Audience []string `json:"audience"`
|
||||
Scopes []string `json:"scopes"`
|
||||
AuthMethodsReferences []string `json:"authMethodReferences"`
|
||||
AuthTime time.Time `json:"authTime"`
|
||||
IdleExpiration time.Duration `json:"idleExpiration"`
|
||||
Expiration time.Duration `json:"expiration"`
|
||||
PreferredLanguage string `json:"preferredLanguage"`
|
||||
TokenID string `json:"tokenId"`
|
||||
ClientID string `json:"clientId"`
|
||||
UserAgentID string `json:"userAgentId"`
|
||||
Audience []string `json:"audience"`
|
||||
Scopes []string `json:"scopes"`
|
||||
AuthMethodsReferences []string `json:"authMethodReferences"`
|
||||
AuthTime time.Time `json:"authTime"`
|
||||
IdleExpiration time.Duration `json:"idleExpiration"`
|
||||
Expiration time.Duration `json:"expiration"`
|
||||
PreferredLanguage string `json:"preferredLanguage"`
|
||||
Actor *domain.TokenActor `json:"actor,omitempty"`
|
||||
}
|
||||
|
||||
func (e *HumanRefreshTokenAddedEvent) Payload() interface{} {
|
||||
@@ -55,6 +57,7 @@ func NewHumanRefreshTokenAddedEvent(
|
||||
authTime time.Time,
|
||||
idleExpiration,
|
||||
expiration time.Duration,
|
||||
actor *domain.TokenActor,
|
||||
) *HumanRefreshTokenAddedEvent {
|
||||
return &HumanRefreshTokenAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
@@ -72,6 +75,7 @@ func NewHumanRefreshTokenAddedEvent(
|
||||
IdleExpiration: idleExpiration,
|
||||
Expiration: expiration,
|
||||
PreferredLanguage: preferredLanguage,
|
||||
Actor: actor,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,7 @@ const (
|
||||
UserRemovedType = userEventTypePrefix + "removed"
|
||||
UserTokenAddedType = userEventTypePrefix + "token.added"
|
||||
UserTokenRemovedType = userEventTypePrefix + "token.removed"
|
||||
UserImpersonatedType = userEventTypePrefix + "impersonated"
|
||||
UserDomainClaimedType = userEventTypePrefix + "domain.claimed"
|
||||
UserDomainClaimedSentType = userEventTypePrefix + "domain.claimed.sent"
|
||||
UserUserNameChangedType = userEventTypePrefix + "username.changed"
|
||||
@@ -209,14 +210,18 @@ func UserRemovedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
type UserTokenAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
TokenID string `json:"tokenId"`
|
||||
ApplicationID string `json:"applicationId"`
|
||||
UserAgentID string `json:"userAgentId"`
|
||||
RefreshTokenID string `json:"refreshTokenID,omitempty"`
|
||||
Audience []string `json:"audience"`
|
||||
Scopes []string `json:"scopes"`
|
||||
Expiration time.Time `json:"expiration"`
|
||||
PreferredLanguage string `json:"preferredLanguage"`
|
||||
TokenID string `json:"tokenId,omitempty"`
|
||||
ApplicationID string `json:"applicationId,omitempty"`
|
||||
UserAgentID string `json:"userAgentId,omitempty"`
|
||||
RefreshTokenID string `json:"refreshTokenID,omitempty"`
|
||||
Audience []string `json:"audience,omitempty"`
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
AuthMethodsReferences []string `json:"authMethodsReferences,omitempty"`
|
||||
AuthTime time.Time `json:"authTime,omitempty"`
|
||||
Expiration time.Time `json:"expiration,omitempty"`
|
||||
PreferredLanguage string `json:"preferredLanguage,omitempty"`
|
||||
Reason domain.TokenReason `json:"reason,omitempty"`
|
||||
Actor *domain.TokenActor `json:"actor,omitempty"`
|
||||
}
|
||||
|
||||
func (e *UserTokenAddedEvent) Payload() interface{} {
|
||||
@@ -236,8 +241,12 @@ func NewUserTokenAddedEvent(
|
||||
preferredLanguage,
|
||||
refreshTokenID string,
|
||||
audience,
|
||||
scopes []string,
|
||||
scopes,
|
||||
authMethodsReferences []string,
|
||||
authTime,
|
||||
expiration time.Time,
|
||||
reason domain.TokenReason,
|
||||
actor *domain.TokenActor,
|
||||
) *UserTokenAddedEvent {
|
||||
return &UserTokenAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
@@ -253,6 +262,8 @@ func NewUserTokenAddedEvent(
|
||||
Scopes: scopes,
|
||||
Expiration: expiration,
|
||||
PreferredLanguage: preferredLanguage,
|
||||
Reason: reason,
|
||||
Actor: actor,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +279,42 @@ func UserTokenAddedEventMapper(event eventstore.Event) (eventstore.Event, error)
|
||||
return tokenAdded, nil
|
||||
}
|
||||
|
||||
type UserImpersonatedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
ApplicationID string `json:"applicationId,omitempty"`
|
||||
Actor *domain.TokenActor `json:"actor,omitempty"`
|
||||
}
|
||||
|
||||
func (e *UserImpersonatedEvent) Payload() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *UserImpersonatedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *UserImpersonatedEvent) SetBaseEvent(base *eventstore.BaseEvent) {
|
||||
e.BaseEvent = *base
|
||||
}
|
||||
|
||||
func NewUserImpersonatedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
applicationID string,
|
||||
actor *domain.TokenActor,
|
||||
) *UserTokenAddedEvent {
|
||||
return &UserTokenAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
UserImpersonatedType,
|
||||
),
|
||||
ApplicationID: applicationID,
|
||||
Actor: actor,
|
||||
}
|
||||
}
|
||||
|
||||
type UserTokenRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
|
Reference in New Issue
Block a user