Merge commit from fork

* feat(jwt idp): manage and validate audience

* translations

* fix tests

* address comments

* update migration version

* fix merge
This commit is contained in:
Livio Spring
2026-06-15 15:27:47 +02:00
committed by GitHub
parent fad02c6d9f
commit d184e976fc
57 changed files with 379 additions and 55 deletions
+12 -10
View File
@@ -265,22 +265,24 @@ func updateGenericOIDCProviderToCommand(req *admin_pb.UpdateGenericOIDCProviderR
func addJWTProviderToCommand(req *admin_pb.AddJWTProviderRequest) command.JWTProvider {
return command.JWTProvider{
Name: req.Name,
Issuer: req.Issuer,
JWTEndpoint: req.JwtEndpoint,
KeyEndpoint: req.KeysEndpoint,
HeaderName: req.HeaderName,
Name: req.GetName(),
Issuer: req.GetIssuer(),
JWTEndpoint: req.GetJwtEndpoint(),
KeyEndpoint: req.GetKeysEndpoint(),
HeaderName: req.GetHeaderName(),
Audience: req.GetAudience(),
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
}
}
func updateJWTProviderToCommand(req *admin_pb.UpdateJWTProviderRequest) command.JWTProvider {
return command.JWTProvider{
Name: req.Name,
Issuer: req.Issuer,
JWTEndpoint: req.JwtEndpoint,
KeyEndpoint: req.KeysEndpoint,
HeaderName: req.HeaderName,
Name: req.GetName(),
Issuer: req.GetIssuer(),
JWTEndpoint: req.GetJwtEndpoint(),
KeyEndpoint: req.GetKeysEndpoint(),
HeaderName: req.GetHeaderName(),
Audience: req.GetAudience(),
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
}
}
+1
View File
@@ -529,6 +529,7 @@ func jwtConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.JWTIDP
Issuer: template.Issuer,
KeysEndpoint: template.KeysEndpoint,
HeaderName: template.HeaderName,
Audience: template.Audience,
},
}
}
+1
View File
@@ -197,6 +197,7 @@ func jwtConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.JWTIDPTemplate)
Issuer: template.Issuer,
KeysEndpoint: template.KeysEndpoint,
HeaderName: template.HeaderName,
Audience: template.Audience,
},
}
}
+12 -10
View File
@@ -258,22 +258,24 @@ func updateGenericOIDCProviderToCommand(req *mgmt_pb.UpdateGenericOIDCProviderRe
func addJWTProviderToCommand(req *mgmt_pb.AddJWTProviderRequest) command.JWTProvider {
return command.JWTProvider{
Name: req.Name,
Issuer: req.Issuer,
JWTEndpoint: req.JwtEndpoint,
KeyEndpoint: req.KeysEndpoint,
HeaderName: req.HeaderName,
Name: req.GetName(),
Issuer: req.GetIssuer(),
JWTEndpoint: req.GetJwtEndpoint(),
KeyEndpoint: req.GetKeysEndpoint(),
HeaderName: req.GetHeaderName(),
Audience: req.GetAudience(),
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
}
}
func updateJWTProviderToCommand(req *mgmt_pb.UpdateJWTProviderRequest) command.JWTProvider {
return command.JWTProvider{
Name: req.Name,
Issuer: req.Issuer,
JWTEndpoint: req.JwtEndpoint,
KeyEndpoint: req.KeysEndpoint,
HeaderName: req.HeaderName,
Name: req.GetName(),
Issuer: req.GetIssuer(),
JWTEndpoint: req.GetJwtEndpoint(),
KeyEndpoint: req.GetKeysEndpoint(),
HeaderName: req.GetHeaderName(),
Audience: req.GetAudience(),
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
}
}
@@ -1090,6 +1090,7 @@ func (l *Login) jwtProvider(identityProvider *query.IDPTemplate) (*jwt.Provider,
identityProvider.JWTIDPTemplate.Endpoint,
identityProvider.JWTIDPTemplate.KeysEndpoint,
identityProvider.JWTIDPTemplate.HeaderName,
identityProvider.JWTIDPTemplate.Audience,
l.idpConfigAlg,
)
}
+1
View File
@@ -41,6 +41,7 @@ type JWTProvider struct {
JWTEndpoint string
KeyEndpoint string
HeaderName string
Audience string
IDPOptions idp.Options
}
+11 -1
View File
@@ -430,6 +430,7 @@ type JWTIDPWriteModel struct {
JWTEndpoint string
KeysEndpoint string
HeaderName string
Audience string
idp.Options
State domain.IDPState
@@ -465,6 +466,7 @@ func (wm *JWTIDPWriteModel) reduceAddedEvent(e *idp.JWTIDPAddedEvent) {
wm.JWTEndpoint = e.JWTEndpoint
wm.KeysEndpoint = e.KeysEndpoint
wm.HeaderName = e.HeaderName
wm.Audience = e.Audience
wm.Options = e.Options
wm.State = domain.IDPStateActive
}
@@ -485,6 +487,9 @@ func (wm *JWTIDPWriteModel) reduceChangedEvent(e *idp.JWTIDPChangedEvent) {
if e.HeaderName != nil {
wm.HeaderName = *e.HeaderName
}
if e.Audience != nil {
wm.Audience = *e.Audience
}
wm.Options.ReduceChanges(e.OptionChanges)
}
@@ -493,7 +498,8 @@ func (wm *JWTIDPWriteModel) NewChanges(
issuer,
jwtEndpoint,
keysEndpoint,
headerName string,
headerName,
audience string,
options idp.Options,
) ([]idp.JWTIDPChanges, error) {
changes := make([]idp.JWTIDPChanges, 0)
@@ -512,6 +518,9 @@ func (wm *JWTIDPWriteModel) NewChanges(
if wm.HeaderName != headerName {
changes = append(changes, idp.ChangeJWTHeaderName(headerName))
}
if wm.Audience != audience {
changes = append(changes, idp.ChangeJWTAudience(audience))
}
opts := wm.Options.Changes(options)
if !opts.IsZero() {
changes = append(changes, idp.ChangeJWTOptions(opts))
@@ -583,6 +592,7 @@ func (wm *JWTIDPWriteModel) ToProvider(callbackURL string, idpAlg crypto.Encrypt
wm.JWTEndpoint,
wm.KeysEndpoint,
wm.HeaderName,
wm.Audience,
idpAlg,
opts...,
)
+2
View File
@@ -940,6 +940,7 @@ func (c *Commands) prepareAddInstanceJWTProvider(a *instance.Aggregate, writeMod
provider.JWTEndpoint,
provider.KeyEndpoint,
provider.HeaderName,
provider.Audience,
provider.IDPOptions,
),
}, nil
@@ -988,6 +989,7 @@ func (c *Commands) prepareUpdateInstanceJWTProvider(a *instance.Aggregate, write
provider.JWTEndpoint,
provider.KeyEndpoint,
provider.HeaderName,
provider.Audience,
provider.IDPOptions,
)
if err != nil || event == nil {
+3 -1
View File
@@ -274,7 +274,8 @@ func (wm *InstanceJWTIDPWriteModel) NewChangedEvent(
issuer,
jwtEndpoint,
keysEndpoint,
headerName string,
headerName,
audience string,
options idp.Options,
) (*instance.JWTIDPChangedEvent, error) {
@@ -284,6 +285,7 @@ func (wm *InstanceJWTIDPWriteModel) NewChangedEvent(
jwtEndpoint,
keysEndpoint,
headerName,
audience,
options,
)
if err != nil || len(changes) == 0 {
+2
View File
@@ -911,6 +911,7 @@ func (c *Commands) prepareAddOrgJWTProvider(a *org.Aggregate, writeModel *OrgJWT
provider.JWTEndpoint,
provider.KeyEndpoint,
provider.HeaderName,
provider.Audience,
provider.IDPOptions,
),
}, nil
@@ -959,6 +960,7 @@ func (c *Commands) prepareUpdateOrgJWTProvider(a *org.Aggregate, writeModel *Org
provider.JWTEndpoint,
provider.KeyEndpoint,
provider.HeaderName,
provider.Audience,
provider.IDPOptions,
)
if err != nil || event == nil {
+3 -1
View File
@@ -276,7 +276,8 @@ func (wm *OrgJWTIDPWriteModel) NewChangedEvent(
issuer,
jwtEndpoint,
keysEndpoint,
headerName string,
headerName,
audience string,
options idp.Options,
) (*org.JWTIDPChangedEvent, error) {
@@ -286,6 +287,7 @@ func (wm *OrgJWTIDPWriteModel) NewChangedEvent(
jwtEndpoint,
keysEndpoint,
headerName,
audience,
options,
)
if err != nil || len(changes) == 0 {
+3 -1
View File
@@ -28,6 +28,7 @@ type Provider struct {
issuer string
jwtEndpoint string
keysEndpoint string
audience string
isLinkingAllowed bool
isCreationAllowed bool
isAutoCreation bool
@@ -67,13 +68,14 @@ func WithAutoUpdate() ProviderOpts {
}
// New creates a JWT provider
func New(name, issuer, jwtEndpoint, keysEndpoint, headerName string, encryptionAlg crypto.EncryptionAlgorithm, options ...ProviderOpts) (*Provider, error) {
func New(name, issuer, jwtEndpoint, keysEndpoint, headerName, audience string, encryptionAlg crypto.EncryptionAlgorithm, options ...ProviderOpts) (*Provider, error) {
provider := &Provider{
name: name,
issuer: issuer,
jwtEndpoint: jwtEndpoint,
keysEndpoint: keysEndpoint,
headerName: headerName,
audience: audience,
encryptionAlg: encryptionAlg,
}
for _, option := range options {
+9
View File
@@ -20,6 +20,7 @@ func TestProvider_BeginAuth(t *testing.T) {
jwtEndpoint string
keysEndpoint string
headerName string
audience string
encryptionAlg func(t *testing.T) crypto.EncryptionAlgorithm
}
type args struct {
@@ -43,6 +44,7 @@ func TestProvider_BeginAuth(t *testing.T) {
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "audience",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
@@ -64,6 +66,7 @@ func TestProvider_BeginAuth(t *testing.T) {
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "audience",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
@@ -83,6 +86,7 @@ func TestProvider_BeginAuth(t *testing.T) {
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "audience",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
@@ -108,6 +112,7 @@ func TestProvider_BeginAuth(t *testing.T) {
tt.fields.jwtEndpoint,
tt.fields.keysEndpoint,
tt.fields.headerName,
tt.fields.audience,
tt.fields.encryptionAlg(t),
)
require.NoError(t, err)
@@ -135,6 +140,7 @@ func TestProvider_Options(t *testing.T) {
jwtEndpoint string
keysEndpoint string
headerName string
audience string
encryptionAlg func(t *testing.T) crypto.EncryptionAlgorithm
opts []ProviderOpts
}
@@ -159,6 +165,7 @@ func TestProvider_Options(t *testing.T) {
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "audience",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
@@ -181,6 +188,7 @@ func TestProvider_Options(t *testing.T) {
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "audience",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
@@ -211,6 +219,7 @@ func TestProvider_Options(t *testing.T) {
tt.fields.jwtEndpoint,
tt.fields.keysEndpoint,
tt.fields.headerName,
tt.fields.audience,
tt.fields.encryptionAlg(t),
tt.fields.opts...,
)
+5
View File
@@ -100,6 +100,11 @@ func (s *Session) validateToken(ctx context.Context, token string) (*oidc.IDToke
return nil, fmt.Errorf("%w: %v", ErrInvalidToken, err)
}
if s.Provider.audience != "" {
if err = oidc.CheckAudience(claims, s.Provider.audience); err != nil {
return nil, fmt.Errorf("%w: %v", ErrInvalidToken, err)
}
}
return claims, nil
}
@@ -27,6 +27,7 @@ func TestSession_FetchUser(t *testing.T) {
jwtEndpoint string
keysEndpoint string
headerName string
audience string
encryptionAlg func(t *testing.T) crypto.EncryptionAlgorithm
httpMock func(issuer string)
authURL string
@@ -60,6 +61,7 @@ func TestSession_FetchUser(t *testing.T) {
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
@@ -83,6 +85,36 @@ func TestSession_FetchUser(t *testing.T) {
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
httpMock: func(issuer string) {
gock.New(issuer).
Get("/keys").
Reply(200).
JSON(keys(t))
},
authURL: "https://auth.com/jwt?authRequestID=testState",
tokens: &oidc.Tokens[*oidc.IDTokenClaims]{
Token: &oauth2.Token{},
IDToken: "invalidToken",
},
},
want: want{
err: func(err error) bool {
return errors.Is(err, ErrInvalidToken)
},
},
},
{
name: "invalid token (audience)",
fields: fields{
issuer: "https://jwt.com",
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "audience",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
@@ -214,6 +246,69 @@ func TestSession_FetchUser(t *testing.T) {
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "clientID",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
httpMock: func(issuer string) {
gock.New(issuer).
Get("/keys").
Reply(200).
JSON(keys(t))
},
authURL: "https://auth.com/jwt?authRequestID=testState",
tokens: &oidc.Tokens[*oidc.IDTokenClaims]{
Token: &oauth2.Token{},
IDToken: idToken(t, "https://jwt.com", time.Now().Add(time.Hour), 0),
IDTokenClaims: &oidc.IDTokenClaims{
TokenClaims: oidc.TokenClaims{
Subject: "sub",
},
UserInfoProfile: oidc.UserInfoProfile{
Picture: "picture",
Name: "firstname lastname",
GivenName: "firstname",
FamilyName: "lastname",
Nickname: "nickname",
PreferredUsername: "username",
Profile: "profile",
Locale: oidc.NewLocale(language.English),
},
UserInfoEmail: oidc.UserInfoEmail{
Email: "email",
EmailVerified: oidc.Bool(true),
},
UserInfoPhone: oidc.UserInfoPhone{
PhoneNumber: "phone",
PhoneNumberVerified: true,
},
},
},
},
want: want{
id: "sub",
firstName: "firstname",
lastName: "lastname",
displayName: "firstname lastname",
nickName: "nickname",
preferredUsername: "username",
email: "email",
isEmailVerified: true,
phone: "phone",
isPhoneVerified: true,
preferredLanguage: language.English,
avatarURL: "picture",
profile: "profile",
},
},
{
name: "successful fetch (no audience check)",
fields: fields{
issuer: "https://jwt.com",
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
audience: "",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
@@ -281,6 +376,7 @@ func TestSession_FetchUser(t *testing.T) {
tt.fields.jwtEndpoint,
tt.fields.keysEndpoint,
tt.fields.headerName,
tt.fields.audience,
tt.fields.encryptionAlg(t),
)
require.NoError(t, err)
+13
View File
@@ -82,6 +82,7 @@ type JWTIDPTemplate struct {
KeysEndpoint string
HeaderName string
Endpoint string
Audience string
}
type AzureADIDPTemplate struct {
@@ -355,6 +356,10 @@ var (
name: projection.JWTHeaderNameCol,
table: jwtIdpTemplateTable,
}
JWTAudienceCol = Column{
name: projection.JWTAudienceCol,
table: jwtIdpTemplateTable,
}
)
var (
@@ -913,6 +918,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
JWTEndpointCol.identifier(),
JWTKeysEndpointCol.identifier(),
JWTHeaderNameCol.identifier(),
JWTAudienceCol.identifier(),
// azure
AzureADIDCol.identifier(),
AzureADClientIDCol.identifier(),
@@ -1034,6 +1040,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
jwtEndpoint := sql.NullString{}
jwtKeysEndpoint := sql.NullString{}
jwtHeaderName := sql.NullString{}
jwtAudience := sql.NullString{}
azureadID := sql.NullString{}
azureadClientID := sql.NullString{}
@@ -1153,6 +1160,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
&jwtEndpoint,
&jwtKeysEndpoint,
&jwtHeaderName,
&jwtAudience,
// azure
&azureadID,
&azureadClientID,
@@ -1273,6 +1281,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
KeysEndpoint: jwtKeysEndpoint.String,
HeaderName: jwtHeaderName.String,
Endpoint: jwtEndpoint.String,
Audience: jwtAudience.String,
}
}
if azureadID.Valid {
@@ -1429,6 +1438,7 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
JWTEndpointCol.identifier(),
JWTKeysEndpointCol.identifier(),
JWTHeaderNameCol.identifier(),
JWTAudienceCol.identifier(),
// azure
AzureADIDCol.identifier(),
AzureADClientIDCol.identifier(),
@@ -1555,6 +1565,7 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
jwtEndpoint := sql.NullString{}
jwtKeysEndpoint := sql.NullString{}
jwtHeaderName := sql.NullString{}
jwtAudience := sql.NullString{}
azureadID := sql.NullString{}
azureadClientID := sql.NullString{}
@@ -1674,6 +1685,7 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
&jwtEndpoint,
&jwtKeysEndpoint,
&jwtHeaderName,
&jwtAudience,
// azure
&azureadID,
&azureadClientID,
@@ -1793,6 +1805,7 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
KeysEndpoint: jwtKeysEndpoint.String,
HeaderName: jwtHeaderName.String,
Endpoint: jwtEndpoint.String,
Audience: jwtAudience.String,
}
}
if azureadID.Valid {
+25
View File
@@ -54,6 +54,7 @@ var (
` projections.idp_templates6_jwt.jwt_endpoint,` +
` projections.idp_templates6_jwt.keys_endpoint,` +
` projections.idp_templates6_jwt.header_name,` +
` projections.idp_templates6_jwt.audience,` +
// azure
` projections.idp_templates6_azure.idp_id,` +
` projections.idp_templates6_azure.client_id,` +
@@ -185,6 +186,7 @@ var (
"jwt_endpoint",
"keys_endpoint",
"header_name",
"audience",
// azure
"idp_id",
"client_id",
@@ -303,6 +305,7 @@ var (
` projections.idp_templates6_jwt.jwt_endpoint,` +
` projections.idp_templates6_jwt.keys_endpoint,` +
` projections.idp_templates6_jwt.header_name,` +
` projections.idp_templates6_jwt.audience,` +
// azure
` projections.idp_templates6_azure.idp_id,` +
` projections.idp_templates6_azure.client_id,` +
@@ -435,6 +438,7 @@ var (
"jwt_endpoint",
"keys_endpoint",
"header_name",
"audience",
// azure
"idp_id",
"client_id",
@@ -593,6 +597,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -749,6 +754,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -903,6 +909,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
"jwt",
"keys",
"header",
"audience",
// azure
nil,
nil,
@@ -1006,6 +1013,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
Endpoint: "jwt",
KeysEndpoint: "keys",
HeaderName: "header",
Audience: "audience",
},
},
},
@@ -1055,6 +1063,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -1206,6 +1215,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -1357,6 +1367,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -1509,6 +1520,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -1660,6 +1672,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -1817,6 +1830,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -1989,6 +2003,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -2142,6 +2157,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -2323,6 +2339,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -2504,6 +2521,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -2658,6 +2676,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -2777,6 +2796,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -2896,6 +2916,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -3015,6 +3036,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -3134,6 +3156,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// azure
nil,
nil,
@@ -3253,6 +3276,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
"jwt",
"keys",
"header",
"audience",
// azure
nil,
nil,
@@ -3508,6 +3532,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
Endpoint: "jwt",
KeysEndpoint: "keys",
HeaderName: "header",
Audience: "audience",
},
},
},
@@ -221,5 +221,9 @@ func (p *relationalTablesProjection) reduceJWTIDPChangedColumns(payload *domain.
payloadChanged = true
payload.Issuer = *idpEvent.Issuer
}
if idpEvent.Audience != nil && *idpEvent.Audience != payload.Audience {
payloadChanged = true
payload.Audience = *idpEvent.Audience
}
return payloadChanged
}
@@ -89,6 +89,7 @@ const (
JWTEndpointCol = "jwt_endpoint"
JWTKeysEndpointCol = "keys_endpoint"
JWTHeaderNameCol = "header_name"
JWTAudienceCol = "audience"
AzureADIDCol = "idp_id"
AzureADInstanceIDCol = "instance_id"
@@ -258,6 +259,7 @@ func (*idpTemplateProjection) Init() *old_handler.Check {
handler.NewColumn(JWTEndpointCol, handler.ColumnTypeText),
handler.NewColumn(JWTKeysEndpointCol, handler.ColumnTypeText),
handler.NewColumn(JWTHeaderNameCol, handler.ColumnTypeText, handler.Nullable()),
handler.NewColumn(JWTAudienceCol, handler.ColumnTypeText, handler.Nullable()),
},
handler.NewPrimaryKey(JWTInstanceIDCol, JWTIDCol),
IDPTemplateJWTSuffix,
@@ -1046,6 +1048,7 @@ func (p *idpTemplateProjection) reduceJWTIDPAdded(event eventstore.Event) (*hand
handler.NewCol(JWTEndpointCol, idpEvent.JWTEndpoint),
handler.NewCol(JWTKeysEndpointCol, idpEvent.KeysEndpoint),
handler.NewCol(JWTHeaderNameCol, idpEvent.HeaderName),
handler.NewCol(JWTAudienceCol, idpEvent.Audience),
},
handler.WithTableSuffix(IDPTemplateJWTSuffix),
),
@@ -2340,6 +2343,9 @@ func reduceJWTIDPChangedColumns(idpEvent idp.JWTIDPChangedEvent) []handler.Colum
if idpEvent.Issuer != nil {
jwtCols = append(jwtCols, handler.NewCol(JWTIssuerCol, *idpEvent.Issuer))
}
if idpEvent.Audience != nil {
jwtCols = append(jwtCols, handler.NewCol(JWTAudienceCol, *idpEvent.Audience))
}
return jwtCols
}
+11 -5
View File
@@ -4280,7 +4280,8 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
"isLinkingAllowed": true,
"isAutoCreation": true,
"isAutoUpdate": true,
"autoLinkingOption": 1
"autoLinkingOption": 1,
"audience": "audience"
}`),
), instance.JWTIDPAddedEventMapper),
},
@@ -4311,7 +4312,7 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.idp_templates6_jwt (idp_id, instance_id, issuer, jwt_endpoint, keys_endpoint, header_name) VALUES ($1, $2, $3, $4, $5, $6)",
expectedStmt: "INSERT INTO projections.idp_templates6_jwt (idp_id, instance_id, issuer, jwt_endpoint, keys_endpoint, header_name, audience) VALUES ($1, $2, $3, $4, $5, $6, $7)",
expectedArgs: []interface{}{
"idp-id",
"instance-id",
@@ -4319,6 +4320,7 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
"jwt",
"keys",
"header",
"audience",
},
},
},
@@ -4342,7 +4344,8 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
"isLinkingAllowed": true,
"isAutoCreation": true,
"isAutoUpdate": true,
"autoLinkingOption": 1
"autoLinkingOption": 1,
"audience": "audience"
}`),
), org.JWTIDPAddedEventMapper),
},
@@ -4373,7 +4376,7 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.idp_templates6_jwt (idp_id, instance_id, issuer, jwt_endpoint, keys_endpoint, header_name) VALUES ($1, $2, $3, $4, $5, $6)",
expectedStmt: "INSERT INTO projections.idp_templates6_jwt (idp_id, instance_id, issuer, jwt_endpoint, keys_endpoint, header_name, audience) VALUES ($1, $2, $3, $4, $5, $6, $7)",
expectedArgs: []interface{}{
"idp-id",
"instance-id",
@@ -4381,6 +4384,7 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
"jwt",
"keys",
"header",
"audience",
},
},
},
@@ -4442,6 +4446,7 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
"jwtEndpoint": "jwt",
"keysEndpoint": "keys",
"headerName": "header",
"audience": "audience",
"isCreationAllowed": true,
"isLinkingAllowed": true,
"isAutoCreation": true,
@@ -4471,12 +4476,13 @@ func TestIDPTemplateProjection_reducesJWT(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.idp_templates6_jwt SET (jwt_endpoint, keys_endpoint, header_name, issuer) = ($1, $2, $3, $4) WHERE (idp_id = $5) AND (instance_id = $6)",
expectedStmt: "UPDATE projections.idp_templates6_jwt SET (jwt_endpoint, keys_endpoint, header_name, issuer, audience) = ($1, $2, $3, $4, $5) WHERE (idp_id = $6) AND (instance_id = $7)",
expectedArgs: []interface{}{
"jwt",
"keys",
"header",
"issuer",
"audience",
"idp-id",
"instance-id",
},
+11 -1
View File
@@ -14,6 +14,7 @@ type JWTIDPAddedEvent struct {
JWTEndpoint string `json:"jwtEndpoint,omitempty"`
KeysEndpoint string `json:"keysEndpoint,omitempty"`
HeaderName string `json:"headerName,omitempty"`
Audience string `json:"audience,omitempty"`
Options
}
@@ -24,7 +25,8 @@ func NewJWTIDPAddedEvent(
issuer,
jwtEndpoint,
keysEndpoint,
headerName string,
headerName,
audience string,
options Options,
) *JWTIDPAddedEvent {
return &JWTIDPAddedEvent{
@@ -35,6 +37,7 @@ func NewJWTIDPAddedEvent(
JWTEndpoint: jwtEndpoint,
KeysEndpoint: keysEndpoint,
HeaderName: headerName,
Audience: audience,
Options: options,
}
}
@@ -69,6 +72,7 @@ type JWTIDPChangedEvent struct {
JWTEndpoint *string `json:"jwtEndpoint,omitempty"`
KeysEndpoint *string `json:"keysEndpoint,omitempty"`
HeaderName *string `json:"headerName,omitempty"`
Audience *string `json:"audience,omitempty"`
OptionChanges
}
@@ -122,6 +126,12 @@ func ChangeJWTHeaderName(headerName string) func(*JWTIDPChangedEvent) {
}
}
func ChangeJWTAudience(audience string) func(*JWTIDPChangedEvent) {
return func(e *JWTIDPChangedEvent) {
e.Audience = &audience
}
}
func ChangeJWTOptions(options OptionChanges) func(*JWTIDPChangedEvent) {
return func(e *JWTIDPChangedEvent) {
e.OptionChanges = options
+3 -1
View File
@@ -304,7 +304,8 @@ func NewJWTIDPAddedEvent(
issuer,
jwtEndpoint,
keysEndpoint,
headerName string,
headerName,
audience string,
options idp.Options,
) *JWTIDPAddedEvent {
@@ -321,6 +322,7 @@ func NewJWTIDPAddedEvent(
jwtEndpoint,
keysEndpoint,
headerName,
audience,
options,
),
}
+3 -1
View File
@@ -304,7 +304,8 @@ func NewJWTIDPAddedEvent(
issuer,
jwtEndpoint,
keysEndpoint,
headerName string,
headerName,
audience string,
options idp.Options,
) *JWTIDPAddedEvent {
@@ -321,6 +322,7 @@ func NewJWTIDPAddedEvent(
jwtEndpoint,
keysEndpoint,
headerName,
audience,
options,
),
}