feat: Extend oidc idp with oauth endpoints (#1980)

* feat: add oauth attributes to oidc idp configuration

* feat: return idpconfig id on create idp

* feat: tests

* feat: descriptions

* feat: docs

* feat: tests
This commit is contained in:
Fabi 2021-07-06 16:39:48 +02:00 committed by GitHub
parent 5349d96ce4
commit ff9af1704f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 419 additions and 156 deletions

View File

@ -1072,10 +1072,12 @@ This is an empty request
| styling_type | zitadel.idp.v1.IDPStylingType | - | enum.defined_only: true<br /> |
| client_id | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| client_secret | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| issuer | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| issuer | string | Fill the issuer if the identity provider is oidc discovery compliant If the identity provider is only oauth2 compliant or does not serve a openid configuration, fill the authorization and token endpoint instead | string.max_len: 200<br /> |
| scopes | repeated string | - | |
| display_name_mapping | zitadel.idp.v1.OIDCMappingField | - | enum.defined_only: true<br /> |
| username_mapping | zitadel.idp.v1.OIDCMappingField | - | enum.defined_only: true<br /> |
| authorization_endpoint | string | If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer | string.max_len: 500<br /> |
| token_endpoint | string | If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer | string.max_len: 500<br /> |
@ -2498,12 +2500,14 @@ This is an empty request
| Field | Type | Description | Validation |
| ----- | ---- | ----------- | ----------- |
| idp_id | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| issuer | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| issuer | string | Fill the issuer if the identity provider is oidc discovery compliant If the identity provider is only oauth2 compliant or does not serve a openid configuration, fill the authorization and token endpoint instead | string.min_len: 1<br /> string.max_len: 200<br /> |
| client_id | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| client_secret | string | - | string.max_len: 200<br /> |
| scopes | repeated string | - | |
| display_name_mapping | zitadel.idp.v1.OIDCMappingField | - | enum.defined_only: true<br /> |
| username_mapping | zitadel.idp.v1.OIDCMappingField | - | enum.defined_only: true<br /> |
| authorization_endpoint | string | If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer | string.max_len: 500<br /> |
| token_endpoint | string | If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer | string.max_len: 500<br /> |

View File

@ -100,6 +100,8 @@ title: zitadel/idp.proto
| scopes | repeated string | - | |
| display_name_mapping | OIDCMappingField | - | |
| username_mapping | OIDCMappingField | - | |
| authorization_endpoint | string | - | string.max_len: 500<br /> |
| token_endpoint | string | - | string.max_len: 500<br /> |

View File

@ -3007,10 +3007,12 @@ This is an empty request
| styling_type | zitadel.idp.v1.IDPStylingType | - | enum.defined_only: true<br /> |
| client_id | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| client_secret | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| issuer | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| issuer | string | Fill the issuer if the identity provider is oidc discovery compliant If the identity provider is only oauth2 compliant or does not serve a openid configuration, fill the authorization and token endpoint instead | string.max_len: 200<br /> |
| scopes | repeated string | - | |
| display_name_mapping | zitadel.idp.v1.OIDCMappingField | - | enum.defined_only: true<br /> |
| username_mapping | zitadel.idp.v1.OIDCMappingField | - | enum.defined_only: true<br /> |
| authorization_endpoint | string | If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer | string.max_len: 500<br /> |
| token_endpoint | string | If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer | string.max_len: 500<br /> |
@ -6901,10 +6903,12 @@ This is an empty request
| idp_id | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| client_id | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| client_secret | string | - | string.max_len: 200<br /> |
| issuer | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
| issuer | string | Fill the issuer if the identity provider is oidc discovery compliant If the identity provider is only oauth2 compliant or does not serve a openid configuration, fill the authorization and token endpoint instead | string.min_len: 1<br /> string.max_len: 200<br /> |
| scopes | repeated string | - | |
| display_name_mapping | zitadel.idp.v1.OIDCMappingField | - | enum.defined_only: true<br /> |
| username_mapping | zitadel.idp.v1.OIDCMappingField | - | enum.defined_only: true<br /> |
| authorization_endpoint | string | If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer | string.max_len: 500<br /> |
| token_endpoint | string | If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer | string.max_len: 500<br /> |

1
go.mod
View File

@ -69,6 +69,7 @@ require (
go.opentelemetry.io/otel/exporters/stdout v0.13.0
go.opentelemetry.io/otel/sdk v0.13.0
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/oauth2 v0.0.0-20210201163806-010130855d6c
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/text v0.3.6
golang.org/x/tools v0.1.1

1
go.sum
View File

@ -240,7 +240,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.1 h1:4CF52PCseTFt4bE+Yk3dIpdVi7XWuPVMhPtm4FaIJPM=
github.com/envoyproxy/protoc-gen-validate v0.6.1/go.mod h1:txg5va2Qkip90uYoSKH+nkAAmXrb2j3iq4FLwdrCbXQ=

View File

@ -33,7 +33,7 @@ func (s *Server) AddOIDCIDP(ctx context.Context, req *admin_pb.AddOIDCIDPRequest
return nil, err
}
return &admin_pb.AddOIDCIDPResponse{
IdpId: config.AggregateID,
IdpId: config.IDPConfigID,
Details: object_pb.AddToDetailsPb(
config.Sequence,
config.ChangeDate,

View File

@ -24,6 +24,8 @@ func addOIDCIDPRequestToDomainOIDCIDPConfig(req *admin_pb.AddOIDCIDPRequest) *do
ClientID: req.ClientId,
ClientSecretString: req.ClientSecret,
Issuer: req.Issuer,
AuthorizationEndpoint: req.AuthorizationEndpoint,
TokenEndpoint: req.TokenEndpoint,
Scopes: req.Scopes,
IDPDisplayNameMapping: idp_grpc.MappingFieldToDomain(req.DisplayNameMapping),
UsernameMapping: idp_grpc.MappingFieldToDomain(req.UsernameMapping),
@ -44,6 +46,8 @@ func updateOIDCConfigToDomain(req *admin_pb.UpdateIDPOIDCConfigRequest) *domain.
ClientID: req.ClientId,
ClientSecretString: req.ClientSecret,
Issuer: req.Issuer,
AuthorizationEndpoint: req.AuthorizationEndpoint,
TokenEndpoint: req.TokenEndpoint,
Scopes: req.Scopes,
IDPDisplayNameMapping: idp_grpc.MappingFieldToDomain(req.DisplayNameMapping),
UsernameMapping: idp_grpc.MappingFieldToDomain(req.UsernameMapping),

View File

@ -20,14 +20,16 @@ func Test_addOIDCIDPRequestToDomain(t *testing.T) {
name: "all fields filled",
args: args{
req: &admin_pb.AddOIDCIDPRequest{
Name: "ZITADEL",
StylingType: idp.IDPStylingType_STYLING_TYPE_GOOGLE,
ClientId: "test1234",
ClientSecret: "test4321",
Issuer: "zitadel.ch",
Scopes: []string{"email", "profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
Name: "ZITADEL",
StylingType: idp.IDPStylingType_STYLING_TYPE_GOOGLE,
ClientId: "test1234",
ClientSecret: "test4321",
Issuer: "zitadel.ch",
AuthorizationEndpoint: "https://accounts.zitadel.ch/oauth/v2/authorize",
TokenEndpoint: "https://api.zitadel.ch/oauth/v2/token",
Scopes: []string{"email", "profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
},
},
},
@ -60,12 +62,14 @@ func Test_addOIDCIDPRequestToDomainOIDCIDPConfig(t *testing.T) {
name: "all fields filled",
args: args{
req: &admin_pb.AddOIDCIDPRequest{
ClientId: "test1234",
ClientSecret: "test4321",
Issuer: "zitadel.ch",
Scopes: []string{"email", "profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
ClientId: "test1234",
ClientSecret: "test4321",
Issuer: "zitadel.ch",
AuthorizationEndpoint: "https://accounts.zitadel.ch/oauth/v2/authorize",
TokenEndpoint: "https://api.zitadel.ch/oauth/v2/token",
Scopes: []string{"email", "profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
},
},
},
@ -126,13 +130,15 @@ func Test_updateOIDCConfigToDomain(t *testing.T) {
name: "all fields filled",
args: args{
req: &admin_pb.UpdateIDPOIDCConfigRequest{
IdpId: "4208",
Issuer: "zitadel.ch",
ClientId: "ZITEADEL",
ClientSecret: "i'm so secret",
Scopes: []string{"profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
IdpId: "4208",
Issuer: "zitadel.ch",
AuthorizationEndpoint: "https://accounts.zitadel.ch/oauth/v2/authorize",
TokenEndpoint: "https://api.zitadel.ch/oauth/v2/token",
ClientId: "ZITEADEL",
ClientSecret: "i'm so secret",
Scopes: []string{"profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
},
},
},

View File

@ -133,11 +133,13 @@ func IDPStylingTypeToPb(stylingType domain.IDPConfigStylingType) idp_pb.IDPStyli
func ModelIDPViewToConfigPb(config *iam_model.IDPConfigView) *idp_pb.IDP_OidcConfig {
return &idp_pb.IDP_OidcConfig{
OidcConfig: &idp_pb.OIDCConfig{
ClientId: config.OIDCClientID,
Issuer: config.OIDCIssuer,
Scopes: config.OIDCScopes,
DisplayNameMapping: ModelMappingFieldToPb(config.OIDCIDPDisplayNameMapping),
UsernameMapping: ModelMappingFieldToPb(config.OIDCUsernameMapping),
ClientId: config.OIDCClientID,
Issuer: config.OIDCIssuer,
Scopes: config.OIDCScopes,
DisplayNameMapping: ModelMappingFieldToPb(config.OIDCIDPDisplayNameMapping),
UsernameMapping: ModelMappingFieldToPb(config.OIDCUsernameMapping),
AuthorizationEndpoint: config.OAuthAuthorizationEndpoint,
TokenEndpoint: config.OAuthTokenEndpoint,
},
}
}
@ -145,23 +147,13 @@ func ModelIDPViewToConfigPb(config *iam_model.IDPConfigView) *idp_pb.IDP_OidcCon
func IDPViewToConfigPb(config *domain.IDPConfigView) *idp_pb.IDP_OidcConfig {
return &idp_pb.IDP_OidcConfig{
OidcConfig: &idp_pb.OIDCConfig{
ClientId: config.OIDCClientID,
Issuer: config.OIDCIssuer,
Scopes: config.OIDCScopes,
DisplayNameMapping: MappingFieldToPb(config.OIDCIDPDisplayNameMapping),
UsernameMapping: MappingFieldToPb(config.OIDCUsernameMapping),
},
}
}
func OIDCConfigToPb(config *domain.OIDCIDPConfig) *idp_pb.IDP_OidcConfig {
return &idp_pb.IDP_OidcConfig{
OidcConfig: &idp_pb.OIDCConfig{
ClientId: config.ClientID,
Issuer: config.Issuer,
Scopes: config.Scopes,
DisplayNameMapping: MappingFieldToPb(config.IDPDisplayNameMapping),
UsernameMapping: MappingFieldToPb(config.UsernameMapping),
ClientId: config.OIDCClientID,
Issuer: config.OIDCIssuer,
AuthorizationEndpoint: config.OAuthAuthorizationEndpoint,
TokenEndpoint: config.OAuthTokenEndpoint,
Scopes: config.OIDCScopes,
DisplayNameMapping: MappingFieldToPb(config.OIDCIDPDisplayNameMapping),
UsernameMapping: MappingFieldToPb(config.OIDCUsernameMapping),
},
}
}

View File

@ -32,7 +32,7 @@ func (s *Server) AddOrgOIDCIDP(ctx context.Context, req *mgmt_pb.AddOrgOIDCIDPRe
return nil, err
}
return &mgmt_pb.AddOrgOIDCIDPResponse{
IdpId: config.AggregateID,
IdpId: config.IDPConfigID,
Details: object_pb.AddToDetailsPb(
config.Sequence,
config.ChangeDate,

View File

@ -24,6 +24,8 @@ func addOIDCIDPRequestToDomainOIDCIDPConfig(req *mgmt_pb.AddOrgOIDCIDPRequest) *
ClientID: req.ClientId,
ClientSecretString: req.ClientSecret,
Issuer: req.Issuer,
AuthorizationEndpoint: req.AuthorizationEndpoint,
TokenEndpoint: req.TokenEndpoint,
Scopes: req.Scopes,
IDPDisplayNameMapping: idp_grpc.MappingFieldToDomain(req.DisplayNameMapping),
UsernameMapping: idp_grpc.MappingFieldToDomain(req.UsernameMapping),
@ -44,6 +46,8 @@ func updateOIDCConfigToDomain(req *mgmt_pb.UpdateOrgIDPOIDCConfigRequest) *domai
ClientID: req.ClientId,
ClientSecretString: req.ClientSecret,
Issuer: req.Issuer,
AuthorizationEndpoint: req.AuthorizationEndpoint,
TokenEndpoint: req.TokenEndpoint,
Scopes: req.Scopes,
IDPDisplayNameMapping: idp_grpc.MappingFieldToDomain(req.DisplayNameMapping),
UsernameMapping: idp_grpc.MappingFieldToDomain(req.UsernameMapping),

View File

@ -20,14 +20,16 @@ func Test_addOIDCIDPRequestToDomain(t *testing.T) {
name: "all fields filled",
args: args{
req: &mgmt_pb.AddOrgOIDCIDPRequest{
Name: "ZITADEL",
StylingType: idp.IDPStylingType_STYLING_TYPE_GOOGLE,
ClientId: "test1234",
ClientSecret: "test4321",
Issuer: "zitadel.ch",
Scopes: []string{"email", "profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
Name: "ZITADEL",
StylingType: idp.IDPStylingType_STYLING_TYPE_GOOGLE,
ClientId: "test1234",
ClientSecret: "test4321",
Issuer: "zitadel.ch",
AuthorizationEndpoint: "https://accounts.zitadel.ch/oauth/v2/authorize",
TokenEndpoint: "https://api.zitadel.ch/oauth/v2/token",
Scopes: []string{"email", "profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
},
},
},
@ -60,12 +62,14 @@ func Test_addOIDCIDPRequestToDomainOIDCIDPConfig(t *testing.T) {
name: "all fields filled",
args: args{
req: &mgmt_pb.AddOrgOIDCIDPRequest{
ClientId: "test1234",
ClientSecret: "test4321",
Issuer: "zitadel.ch",
Scopes: []string{"email", "profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
ClientId: "test1234",
ClientSecret: "test4321",
Issuer: "zitadel.ch",
AuthorizationEndpoint: "https://accounts.zitadel.ch/oauth/v2/authorize",
TokenEndpoint: "https://api.zitadel.ch/oauth/v2/token",
Scopes: []string{"email", "profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
},
},
},
@ -126,13 +130,15 @@ func Test_updateOIDCConfigToDomain(t *testing.T) {
name: "all fields filled",
args: args{
req: &mgmt_pb.UpdateOrgIDPOIDCConfigRequest{
IdpId: "4208",
Issuer: "zitadel.ch",
ClientId: "ZITEADEL",
ClientSecret: "i'm so secret",
Scopes: []string{"profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
IdpId: "4208",
Issuer: "zitadel.ch",
AuthorizationEndpoint: "https://accounts.zitadel.ch/oauth/v2/authorize",
TokenEndpoint: "https://api.zitadel.ch/oauth/v2/token",
ClientId: "ZITEADEL",
ClientSecret: "i'm so secret",
Scopes: []string{"profile"},
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
},
},
},

View File

@ -145,6 +145,8 @@ func writeModelToIDPOIDCConfig(wm *OIDCConfigWriteModel) *domain.OIDCIDPConfig {
IDPConfigID: wm.IDPConfigID,
IDPDisplayNameMapping: wm.IDPDisplayNameMapping,
Issuer: wm.Issuer,
AuthorizationEndpoint: wm.AuthorizationEndpoint,
TokenEndpoint: wm.TokenEndpoint,
Scopes: wm.Scopes,
UsernameMapping: wm.UserNameMapping,
}

View File

@ -44,6 +44,8 @@ func (c *Commands) AddDefaultIDPConfig(ctx context.Context, config *domain.IDPCo
config.OIDCConfig.ClientID,
idpConfigID,
config.OIDCConfig.Issuer,
config.OIDCConfig.AuthorizationEndpoint,
config.OIDCConfig.TokenEndpoint,
clientSecret,
config.OIDCConfig.IDPDisplayNameMapping,
config.OIDCConfig.UsernameMapping,

View File

@ -76,6 +76,8 @@ func TestCommandSide_AddDefaultIDPConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -102,6 +104,8 @@ func TestCommandSide_AddDefaultIDPConfig(t *testing.T) {
OIDCConfig: &domain.OIDCIDPConfig{
ClientID: "clientid1",
Issuer: "issuer",
AuthorizationEndpoint: "authorization-endpoint",
TokenEndpoint: "token-endpoint",
ClientSecretString: "secret",
Scopes: []string{"scope"},
IDPDisplayNameMapping: domain.OIDCMappingFieldEmail,
@ -216,6 +220,8 @@ func TestCommandSide_ChangeDefaultIDPConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",

View File

@ -27,6 +27,8 @@ func (c *Commands) ChangeDefaultIDPOIDCConfig(ctx context.Context, config *domai
config.IDPConfigID,
config.ClientID,
config.Issuer,
config.AuthorizationEndpoint,
config.TokenEndpoint,
config.ClientSecretString,
c.idpConfigSecretCrypto,
config.IDPDisplayNameMapping,

View File

@ -90,6 +90,8 @@ func (wm *IAMIDPOIDCConfigWriteModel) NewChangedEvent(
idpConfigID,
clientID,
issuer,
authorizationEndpoint,
tokenEndpoint,
clientSecretString string,
secretCrypto crypto.Crypto,
idpDisplayNameMapping,
@ -113,6 +115,12 @@ func (wm *IAMIDPOIDCConfigWriteModel) NewChangedEvent(
if wm.Issuer != issuer {
changes = append(changes, idpconfig.ChangeIssuer(issuer))
}
if wm.AuthorizationEndpoint != authorizationEndpoint {
changes = append(changes, idpconfig.ChangeAuthorizationEndpoint(authorizationEndpoint))
}
if wm.TokenEndpoint != tokenEndpoint {
changes = append(changes, idpconfig.ChangeTokenEndpoint(tokenEndpoint))
}
if idpDisplayNameMapping.Valid() && wm.IDPDisplayNameMapping != idpDisplayNameMapping {
changes = append(changes, idpconfig.ChangeIDPDisplayNameMapping(idpDisplayNameMapping))
}

View File

@ -92,6 +92,8 @@ func TestCommandSide_ChangeDefaultIDPOIDCConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -144,6 +146,8 @@ func TestCommandSide_ChangeDefaultIDPOIDCConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -165,6 +169,8 @@ func TestCommandSide_ChangeDefaultIDPOIDCConfig(t *testing.T) {
IDPConfigID: "config1",
ClientID: "clientid1",
Issuer: "issuer",
AuthorizationEndpoint: "authorization-endpoint",
TokenEndpoint: "token-endpoint",
Scopes: []string{"scope"},
IDPDisplayNameMapping: domain.OIDCMappingFieldEmail,
UsernameMapping: domain.OIDCMappingFieldEmail,
@ -195,6 +201,8 @@ func TestCommandSide_ChangeDefaultIDPOIDCConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -214,6 +222,8 @@ func TestCommandSide_ChangeDefaultIDPOIDCConfig(t *testing.T) {
"config1",
"clientid-changed",
"issuer-changed",
"authorization-endpoint-changed",
"token-endpoint-changed",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -236,6 +246,8 @@ func TestCommandSide_ChangeDefaultIDPOIDCConfig(t *testing.T) {
IDPConfigID: "config1",
ClientID: "clientid-changed",
Issuer: "issuer-changed",
AuthorizationEndpoint: "authorization-endpoint-changed",
TokenEndpoint: "token-endpoint-changed",
ClientSecretString: "secret-changed",
Scopes: []string{"scope", "scope2"},
IDPDisplayNameMapping: domain.OIDCMappingFieldPreferredLoginName,
@ -251,6 +263,8 @@ func TestCommandSide_ChangeDefaultIDPOIDCConfig(t *testing.T) {
IDPConfigID: "config1",
ClientID: "clientid-changed",
Issuer: "issuer-changed",
AuthorizationEndpoint: "authorization-endpoint-changed",
TokenEndpoint: "token-endpoint-changed",
Scopes: []string{"scope", "scope2"},
IDPDisplayNameMapping: domain.OIDCMappingFieldPreferredLoginName,
UsernameMapping: domain.OIDCMappingFieldPreferredLoginName,
@ -278,13 +292,15 @@ func TestCommandSide_ChangeDefaultIDPOIDCConfig(t *testing.T) {
}
}
func newDefaultIDPOIDCConfigChangedEvent(ctx context.Context, configID, clientID, issuer string, secret *crypto.CryptoValue, displayMapping, usernameMapping domain.OIDCMappingField, scopes []string) *iam.IDPOIDCConfigChangedEvent {
func newDefaultIDPOIDCConfigChangedEvent(ctx context.Context, configID, clientID, issuer, authorizationEndpoint, tokenEndpoint string, secret *crypto.CryptoValue, displayMapping, usernameMapping domain.OIDCMappingField, scopes []string) *iam.IDPOIDCConfigChangedEvent {
event, _ := iam.NewIDPOIDCConfigChangedEvent(ctx,
&iam.NewAggregate().Aggregate,
configID,
[]idpconfig.OIDCConfigChanges{
idpconfig.ChangeClientID(clientID),
idpconfig.ChangeIssuer(issuer),
idpconfig.ChangeAuthorizationEndpoint(authorizationEndpoint),
idpconfig.ChangeTokenEndpoint(tokenEndpoint),
idpconfig.ChangeClientSecret(secret),
idpconfig.ChangeIDPDisplayNameMapping(displayMapping),
idpconfig.ChangeUserNameMapping(usernameMapping),

View File

@ -10,11 +10,13 @@ import (
type OIDCConfigWriteModel struct {
eventstore.WriteModel
IDPConfigID string
ClientID string
ClientSecret *crypto.CryptoValue
Issuer string
Scopes []string
IDPConfigID string
ClientID string
ClientSecret *crypto.CryptoValue
Issuer string
AuthorizationEndpoint string
TokenEndpoint string
Scopes []string
IDPDisplayNameMapping domain.OIDCMappingField
UserNameMapping domain.OIDCMappingField
@ -45,6 +47,8 @@ func (wm *OIDCConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.OIDCConfigAd
wm.ClientID = e.ClientID
wm.ClientSecret = e.ClientSecret
wm.Issuer = e.Issuer
wm.AuthorizationEndpoint = e.AuthorizationEndpoint
wm.TokenEndpoint = e.TokenEndpoint
wm.Scopes = e.Scopes
wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping
wm.UserNameMapping = e.UserNameMapping
@ -58,6 +62,12 @@ func (wm *OIDCConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.OIDCConfig
if e.Issuer != nil {
wm.Issuer = *e.Issuer
}
if e.AuthorizationEndpoint != nil {
wm.AuthorizationEndpoint = *e.AuthorizationEndpoint
}
if e.TokenEndpoint != nil {
wm.TokenEndpoint = *e.TokenEndpoint
}
if len(e.Scopes) > 0 {
wm.Scopes = e.Scopes
}

View File

@ -47,6 +47,8 @@ func (c *Commands) AddIDPConfig(ctx context.Context, config *domain.IDPConfig, r
config.OIDCConfig.ClientID,
idpConfigID,
config.OIDCConfig.Issuer,
config.OIDCConfig.AuthorizationEndpoint,
config.OIDCConfig.TokenEndpoint,
clientSecret,
config.OIDCConfig.IDPDisplayNameMapping,
config.OIDCConfig.UsernameMapping,

View File

@ -104,6 +104,8 @@ func TestCommandSide_AddIDPConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -131,6 +133,8 @@ func TestCommandSide_AddIDPConfig(t *testing.T) {
OIDCConfig: &domain.OIDCIDPConfig{
ClientID: "clientid1",
Issuer: "issuer",
AuthorizationEndpoint: "authorization-endpoint",
TokenEndpoint: "token-endpoint",
ClientSecretString: "secret",
Scopes: []string{"scope"},
IDPDisplayNameMapping: domain.OIDCMappingFieldEmail,
@ -264,6 +268,8 @@ func TestCommandSide_ChangeIDPConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",

View File

@ -30,6 +30,8 @@ func (c *Commands) ChangeIDPOIDCConfig(ctx context.Context, config *domain.OIDCI
config.IDPConfigID,
config.ClientID,
config.Issuer,
config.AuthorizationEndpoint,
config.TokenEndpoint,
config.ClientSecretString,
c.idpConfigSecretCrypto,
config.IDPDisplayNameMapping,

View File

@ -90,6 +90,8 @@ func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
idpConfigID,
clientID,
issuer,
authorizationEndpoint,
tokenEndpoint,
clientSecretString string,
secretCrypto crypto.Crypto,
idpDisplayNameMapping,
@ -113,6 +115,12 @@ func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
if wm.Issuer != issuer {
changes = append(changes, idpconfig.ChangeIssuer(issuer))
}
if wm.AuthorizationEndpoint != authorizationEndpoint {
changes = append(changes, idpconfig.ChangeAuthorizationEndpoint(authorizationEndpoint))
}
if wm.TokenEndpoint != tokenEndpoint {
changes = append(changes, idpconfig.ChangeTokenEndpoint(tokenEndpoint))
}
if idpDisplayNameMapping.Valid() && wm.IDPDisplayNameMapping != idpDisplayNameMapping {
changes = append(changes, idpconfig.ChangeIDPDisplayNameMapping(idpDisplayNameMapping))
}

View File

@ -112,6 +112,8 @@ func TestCommandSide_ChangeIDPOIDCConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -165,6 +167,8 @@ func TestCommandSide_ChangeIDPOIDCConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -186,6 +190,8 @@ func TestCommandSide_ChangeIDPOIDCConfig(t *testing.T) {
IDPConfigID: "config1",
ClientID: "clientid1",
Issuer: "issuer",
AuthorizationEndpoint: "authorization-endpoint",
TokenEndpoint: "token-endpoint",
Scopes: []string{"scope"},
IDPDisplayNameMapping: domain.OIDCMappingFieldEmail,
UsernameMapping: domain.OIDCMappingFieldEmail,
@ -217,6 +223,8 @@ func TestCommandSide_ChangeIDPOIDCConfig(t *testing.T) {
"clientid1",
"config1",
"issuer",
"authorization-endpoint",
"token-endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -237,6 +245,8 @@ func TestCommandSide_ChangeIDPOIDCConfig(t *testing.T) {
"config1",
"clientid-changed",
"issuer-changed",
"authorization-endpoint-changed",
"token-endpoint-changed",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@ -259,6 +269,8 @@ func TestCommandSide_ChangeIDPOIDCConfig(t *testing.T) {
IDPConfigID: "config1",
ClientID: "clientid-changed",
Issuer: "issuer-changed",
AuthorizationEndpoint: "authorization-endpoint-changed",
TokenEndpoint: "token-endpoint-changed",
ClientSecretString: "secret-changed",
Scopes: []string{"scope", "scope2"},
IDPDisplayNameMapping: domain.OIDCMappingFieldPreferredLoginName,
@ -275,6 +287,8 @@ func TestCommandSide_ChangeIDPOIDCConfig(t *testing.T) {
IDPConfigID: "config1",
ClientID: "clientid-changed",
Issuer: "issuer-changed",
AuthorizationEndpoint: "authorization-endpoint-changed",
TokenEndpoint: "token-endpoint-changed",
Scopes: []string{"scope", "scope2"},
IDPDisplayNameMapping: domain.OIDCMappingFieldPreferredLoginName,
UsernameMapping: domain.OIDCMappingFieldPreferredLoginName,
@ -302,13 +316,15 @@ func TestCommandSide_ChangeIDPOIDCConfig(t *testing.T) {
}
}
func newIDPOIDCConfigChangedEvent(ctx context.Context, orgID, configID, clientID, issuer string, secret *crypto.CryptoValue, displayMapping, usernameMapping domain.OIDCMappingField, scopes []string) *org.IDPOIDCConfigChangedEvent {
func newIDPOIDCConfigChangedEvent(ctx context.Context, orgID, configID, clientID, issuer, authorizationEndpoint, tokenEndpoint string, secret *crypto.CryptoValue, displayMapping, usernameMapping domain.OIDCMappingField, scopes []string) *org.IDPOIDCConfigChangedEvent {
event, _ := org.NewIDPOIDCConfigChangedEvent(ctx,
&org.NewAggregate(orgID, orgID).Aggregate,
configID,
[]idpconfig.OIDCConfigChanges{
idpconfig.ChangeClientID(clientID),
idpconfig.ChangeIssuer(issuer),
idpconfig.ChangeAuthorizationEndpoint(authorizationEndpoint),
idpconfig.ChangeTokenEndpoint(tokenEndpoint),
idpconfig.ChangeClientSecret(secret),
idpconfig.ChangeIDPDisplayNameMapping(displayMapping),
idpconfig.ChangeUserNameMapping(usernameMapping),

View File

@ -1,9 +1,10 @@
package domain
import (
"time"
"github.com/caos/zitadel/internal/crypto"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"time"
)
type IDPConfig struct {
@ -27,13 +28,15 @@ type IDPConfigView struct {
Sequence uint64
IDPProviderType IdentityProviderType
IsOIDC bool
OIDCClientID string
OIDCClientSecret *crypto.CryptoValue
OIDCIssuer string
OIDCScopes []string
OIDCIDPDisplayNameMapping OIDCMappingField
OIDCUsernameMapping OIDCMappingField
IsOIDC bool
OIDCClientID string
OIDCClientSecret *crypto.CryptoValue
OIDCIssuer string
OIDCScopes []string
OIDCIDPDisplayNameMapping OIDCMappingField
OIDCUsernameMapping OIDCMappingField
OAuthAuthorizationEndpoint string
OAuthTokenEndpoint string
}
type OIDCIDPConfig struct {
@ -43,6 +46,8 @@ type OIDCIDPConfig struct {
ClientSecret *crypto.CryptoValue
ClientSecretString string
Issuer string
AuthorizationEndpoint string
TokenEndpoint string
Scopes []string
IDPDisplayNameMapping OIDCMappingField
UsernameMapping OIDCMappingField

View File

@ -19,13 +19,15 @@ type IDPConfigView struct {
Sequence uint64
IDPProviderType IDPProviderType
IsOIDC bool
OIDCClientID string
OIDCClientSecret *crypto.CryptoValue
OIDCIssuer string
OIDCScopes []string
OIDCIDPDisplayNameMapping OIDCMappingField
OIDCUsernameMapping OIDCMappingField
IsOIDC bool
OIDCClientID string
OIDCClientSecret *crypto.CryptoValue
OIDCIssuer string
OIDCScopes []string
OIDCIDPDisplayNameMapping OIDCMappingField
OIDCUsernameMapping OIDCMappingField
OAuthAuthorizationEndpoint string
OAuthTokenEndpoint string
}
type IDPConfigSearchRequest struct {

View File

@ -2,17 +2,19 @@ package model
import (
"encoding/json"
"github.com/caos/zitadel/internal/crypto"
"time"
"github.com/caos/zitadel/internal/crypto"
es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/logging"
"github.com/lib/pq"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/model"
"github.com/lib/pq"
)
const (
@ -32,56 +34,39 @@ type IDPConfigView struct {
IDPState int32 `json:"-" gorm:"column:idp_state"`
IDPProviderType int32 `json:"-" gorm:"column:idp_provider_type"`
IsOIDC bool `json:"-" gorm:"column:is_oidc"`
OIDCClientID string `json:"clientId" gorm:"column:oidc_client_id"`
OIDCClientSecret *crypto.CryptoValue `json:"clientSecret" gorm:"column:oidc_client_secret"`
OIDCIssuer string `json:"issuer" gorm:"column:oidc_issuer"`
OIDCScopes pq.StringArray `json:"scopes" gorm:"column:oidc_scopes"`
OIDCIDPDisplayNameMapping int32 `json:"idpDisplayNameMapping" gorm:"column:oidc_idp_display_name_mapping"`
OIDCUsernameMapping int32 `json:"usernameMapping" gorm:"column:oidc_idp_username_mapping"`
IsOIDC bool `json:"-" gorm:"column:is_oidc"`
OIDCClientID string `json:"clientId" gorm:"column:oidc_client_id"`
OIDCClientSecret *crypto.CryptoValue `json:"clientSecret" gorm:"column:oidc_client_secret"`
OIDCIssuer string `json:"issuer" gorm:"column:oidc_issuer"`
OIDCScopes pq.StringArray `json:"scopes" gorm:"column:oidc_scopes"`
OIDCIDPDisplayNameMapping int32 `json:"idpDisplayNameMapping" gorm:"column:oidc_idp_display_name_mapping"`
OIDCUsernameMapping int32 `json:"usernameMapping" gorm:"column:oidc_idp_username_mapping"`
OAuthAuthorizationEndpoint string `json:"authorizationEndpoint" gorm:"column:oauth_authorization_endpoint"`
OAuthTokenEndpoint string `json:"tokenEndpoint" gorm:"column:oauth_token_endpoint"`
Sequence uint64 `json:"-" gorm:"column:sequence"`
}
func IDPConfigViewFromModel(idp *model.IDPConfigView) *IDPConfigView {
return &IDPConfigView{
IDPConfigID: idp.IDPConfigID,
AggregateID: idp.AggregateID,
IDPState: int32(idp.State),
Name: idp.Name,
StylingType: int32(idp.StylingType),
Sequence: idp.Sequence,
CreationDate: idp.CreationDate,
ChangeDate: idp.ChangeDate,
IDPProviderType: int32(idp.IDPProviderType),
IsOIDC: idp.IsOIDC,
OIDCClientID: idp.OIDCClientID,
OIDCClientSecret: idp.OIDCClientSecret,
OIDCIssuer: idp.OIDCIssuer,
OIDCScopes: idp.OIDCScopes,
OIDCIDPDisplayNameMapping: int32(idp.OIDCIDPDisplayNameMapping),
OIDCUsernameMapping: int32(idp.OIDCUsernameMapping),
}
}
func IDPConfigViewToModel(idp *IDPConfigView) *model.IDPConfigView {
return &model.IDPConfigView{
IDPConfigID: idp.IDPConfigID,
AggregateID: idp.AggregateID,
State: model.IDPConfigState(idp.IDPState),
Name: idp.Name,
StylingType: model.IDPStylingType(idp.StylingType),
Sequence: idp.Sequence,
CreationDate: idp.CreationDate,
ChangeDate: idp.ChangeDate,
IDPProviderType: model.IDPProviderType(idp.IDPProviderType),
IsOIDC: idp.IsOIDC,
OIDCClientID: idp.OIDCClientID,
OIDCClientSecret: idp.OIDCClientSecret,
OIDCIssuer: idp.OIDCIssuer,
OIDCScopes: idp.OIDCScopes,
OIDCIDPDisplayNameMapping: model.OIDCMappingField(idp.OIDCIDPDisplayNameMapping),
OIDCUsernameMapping: model.OIDCMappingField(idp.OIDCUsernameMapping),
IDPConfigID: idp.IDPConfigID,
AggregateID: idp.AggregateID,
State: model.IDPConfigState(idp.IDPState),
Name: idp.Name,
StylingType: model.IDPStylingType(idp.StylingType),
Sequence: idp.Sequence,
CreationDate: idp.CreationDate,
ChangeDate: idp.ChangeDate,
IDPProviderType: model.IDPProviderType(idp.IDPProviderType),
IsOIDC: idp.IsOIDC,
OIDCClientID: idp.OIDCClientID,
OIDCClientSecret: idp.OIDCClientSecret,
OIDCIssuer: idp.OIDCIssuer,
OIDCScopes: idp.OIDCScopes,
OIDCIDPDisplayNameMapping: model.OIDCMappingField(idp.OIDCIDPDisplayNameMapping),
OIDCUsernameMapping: model.OIDCMappingField(idp.OIDCUsernameMapping),
OAuthAuthorizationEndpoint: idp.OAuthAuthorizationEndpoint,
OAuthTokenEndpoint: idp.OAuthTokenEndpoint,
}
}

View File

@ -45,6 +45,8 @@ func readModelToIDPConfigView(rm *IAMIDPConfigReadModel) *domain.IDPConfigView {
converted.OIDCIssuer = rm.OIDCConfig.Issuer
converted.OIDCScopes = rm.OIDCConfig.Scopes
converted.OIDCUsernameMapping = rm.OIDCConfig.UserNameMapping
converted.OAuthAuthorizationEndpoint = rm.OIDCConfig.AuthorizationEndpoint
converted.OAuthTokenEndpoint = rm.OIDCConfig.TokenEndpoint
}
return converted
}

View File

@ -14,6 +14,8 @@ type OIDCConfigReadModel struct {
ClientID string
ClientSecret *crypto.CryptoValue
Issuer string
AuthorizationEndpoint string
TokenEndpoint string
Scopes []string
IDPDisplayNameMapping domain.OIDCMappingField
UserNameMapping domain.OIDCMappingField
@ -37,6 +39,8 @@ func (rm *OIDCConfigReadModel) reduceConfigAddedEvent(e *idpconfig.OIDCConfigAdd
rm.ClientID = e.ClientID
rm.ClientSecret = e.ClientSecret
rm.Issuer = e.Issuer
rm.AuthorizationEndpoint = e.AuthorizationEndpoint
rm.TokenEndpoint = e.TokenEndpoint
rm.Scopes = e.Scopes
rm.IDPDisplayNameMapping = e.IDPDisplayNameMapping
rm.UserNameMapping = e.UserNameMapping
@ -49,6 +53,12 @@ func (rm *OIDCConfigReadModel) reduceConfigChangedEvent(e *idpconfig.OIDCConfigC
if e.Issuer != nil {
rm.Issuer = *e.Issuer
}
if e.AuthorizationEndpoint != nil {
rm.AuthorizationEndpoint = *e.AuthorizationEndpoint
}
if e.TokenEndpoint != nil {
rm.TokenEndpoint = *e.TokenEndpoint
}
if len(e.Scopes) > 0 {
rm.Scopes = e.Scopes
}

View File

@ -24,7 +24,9 @@ func NewIDPOIDCConfigAddedEvent(
aggregate *eventstore.Aggregate,
clientID,
idpConfigID,
issuer string,
issuer,
authorizationEndpoint,
tokenEndpoint string,
clientSecret *crypto.CryptoValue,
idpDisplayNameMapping,
userNameMapping domain.OIDCMappingField,
@ -41,6 +43,8 @@ func NewIDPOIDCConfigAddedEvent(
clientID,
idpConfigID,
issuer,
authorizationEndpoint,
tokenEndpoint,
clientSecret,
idpDisplayNameMapping,
userNameMapping,

View File

@ -18,11 +18,13 @@ const (
type OIDCConfigAddedEvent struct {
eventstore.BaseEvent `json:"-"`
IDPConfigID string `json:"idpConfigId"`
ClientID string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
Issuer string `json:"issuer,omitempty"`
Scopes []string `json:"scopes,omitempty"`
IDPConfigID string `json:"idpConfigId"`
ClientID string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
Issuer string `json:"issuer,omitempty"`
AuthorizationEndpoint string `json:"authorizationEndpoint,omitempty"`
TokenEndpoint string `json:"tokenEndpoint,omitempty"`
Scopes []string `json:"scopes,omitempty"`
IDPDisplayNameMapping domain.OIDCMappingField `json:"idpDisplayNameMapping,omitempty"`
UserNameMapping domain.OIDCMappingField `json:"usernameMapping,omitempty"`
@ -40,7 +42,9 @@ func NewOIDCConfigAddedEvent(
base *eventstore.BaseEvent,
clientID,
idpConfigID,
issuer string,
issuer,
authorizationEndpoint,
tokenEndpoint string,
clientSecret *crypto.CryptoValue,
idpDisplayNameMapping,
userNameMapping domain.OIDCMappingField,
@ -53,6 +57,8 @@ func NewOIDCConfigAddedEvent(
ClientID: clientID,
ClientSecret: clientSecret,
Issuer: issuer,
AuthorizationEndpoint: authorizationEndpoint,
TokenEndpoint: tokenEndpoint,
Scopes: scopes,
IDPDisplayNameMapping: idpDisplayNameMapping,
UserNameMapping: userNameMapping,
@ -77,10 +83,12 @@ type OIDCConfigChangedEvent struct {
IDPConfigID string `json:"idpConfigId"`
ClientID *string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
Issuer *string `json:"issuer,omitempty"`
Scopes []string `json:"scopes,omitempty"`
ClientID *string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
Issuer *string `json:"issuer,omitempty"`
AuthorizationEndpoint *string `json:"authorizationEndpoint,omitempty"`
TokenEndpoint *string `json:"tokenEndpoint,omitempty"`
Scopes []string `json:"scopes,omitempty"`
IDPDisplayNameMapping *domain.OIDCMappingField `json:"idpDisplayNameMapping,omitempty"`
UserNameMapping *domain.OIDCMappingField `json:"usernameMapping,omitempty"`
@ -132,6 +140,18 @@ func ChangeIssuer(issuer string) func(*OIDCConfigChangedEvent) {
}
}
func ChangeAuthorizationEndpoint(authorizationEndpoint string) func(*OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.AuthorizationEndpoint = &authorizationEndpoint
}
}
func ChangeTokenEndpoint(tokenEndpoint string) func(*OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.TokenEndpoint = &tokenEndpoint
}
}
func ChangeIDPDisplayNameMapping(idpDisplayNameMapping domain.OIDCMappingField) func(*OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.IDPDisplayNameMapping = &idpDisplayNameMapping

View File

@ -24,7 +24,9 @@ func NewIDPOIDCConfigAddedEvent(
aggregate *eventstore.Aggregate,
clientID,
idpConfigID,
issuer string,
issuer,
authorizationEndpoint,
tokenEndpoint string,
clientSecret *crypto.CryptoValue,
idpDisplayNameMapping,
userNameMapping domain.OIDCMappingField,
@ -41,6 +43,8 @@ func NewIDPOIDCConfigAddedEvent(
clientID,
idpConfigID,
issuer,
authorizationEndpoint,
tokenEndpoint,
clientSecret,
idpDisplayNameMapping,
userNameMapping,

View File

@ -3,6 +3,8 @@ package handler
import (
"github.com/caos/oidc/pkg/client/rp"
"github.com/caos/oidc/pkg/oidc"
"golang.org/x/oauth2"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/domain"
@ -119,7 +121,29 @@ func (l *Login) getRPConfig(w http.ResponseWriter, r *http.Request, authReq *dom
l.renderError(w, r, authReq, err)
return nil
}
provider, err := rp.NewRelyingPartyOIDC(idpConfig.OIDCIssuer, idpConfig.OIDCClientID, oidcClientSecret, l.baseURL+callbackEndpoint, idpConfig.OIDCScopes, rp.WithVerifierOpts(rp.WithIssuedAtOffset(3*time.Second)))
if idpConfig.OIDCIssuer != "" {
provider, err := rp.NewRelyingPartyOIDC(idpConfig.OIDCIssuer, idpConfig.OIDCClientID, oidcClientSecret, l.baseURL+callbackEndpoint, idpConfig.OIDCScopes, rp.WithVerifierOpts(rp.WithIssuedAtOffset(3*time.Second)))
if err != nil {
l.renderError(w, r, authReq, err)
return nil
}
return provider
}
if idpConfig.OAuthAuthorizationEndpoint == "" || idpConfig.OAuthTokenEndpoint == "" {
l.renderError(w, r, authReq, caos_errors.ThrowPreconditionFailed(nil, "RP-4n0fs", "Errors.IdentityProvider.InvalidConfig"))
return nil
}
oauth2Config := &oauth2.Config{
ClientID: idpConfig.OIDCClientID,
ClientSecret: oidcClientSecret,
Endpoint: oauth2.Endpoint{
AuthURL: idpConfig.OAuthAuthorizationEndpoint,
TokenURL: idpConfig.OAuthTokenEndpoint,
},
RedirectURL: l.baseURL + callbackEndpoint,
Scopes: idpConfig.OIDCScopes,
}
provider, err := rp.NewRelyingPartyOAuth(oauth2Config, rp.WithVerifierOpts(rp.WithIssuedAtOffset(3*time.Second)))
if err != nil {
l.renderError(w, r, authReq, err)
return nil

View File

@ -296,5 +296,7 @@ Errors:
IDPTypeNotImplemented: IDP Typ ist nicht implementiert
NotAllowed: Externer Login Provider ist nicht erlaubt
GrantRequired: Der Login an diese Applikation ist nicht möglich. Der Benutzer benötigt mindestens eine Berechtigung an der Applikation. Bitte melde dich bei deinem Administrator.
IdentityProvider:
InvalidConfig: Identitäts Provider Konfiguration ist ungültig
optional: (optional)

View File

@ -295,6 +295,7 @@ Errors:
IDPTypeNotImplemented: IDP Type is not implemented
NotAllowed: External Login Provider not allowed
GrantRequired: Login not possible. The user is required to have at least one grant on the application. Please contact your administrator.
IdentityProvider:
InvalidConfig: Identity Provider configuration is invalid
optional: (optional)

View File

@ -0,0 +1,7 @@
ALTER TABLE auth.idp_configs ADD COLUMN oauth_authorization_endpoint TEXT;
ALTER TABLE adminapi.idp_configs ADD COLUMN oauth_authorization_endpoint TEXT;
ALTER TABLE management.idp_configs ADD COLUMN oauth_authorization_endpoint TEXT;
ALTER TABLE auth.idp_configs ADD COLUMN oauth_token_endpoint TEXT;
ALTER TABLE adminapi.idp_configs ADD COLUMN oauth_token_endpoint TEXT;
ALTER TABLE management.idp_configs ADD COLUMN oauth_token_endpoint TEXT;

View File

@ -2281,12 +2281,13 @@ message AddOIDCIDPRequest {
max_length: 200;
}
];
// Fill the issuer if the identity provider is oidc discovery compliant
// If the identity provider is only oauth2 compliant or does not serve a openid configuration, fill the authorization and token endpoint instead
string issuer = 5 [
(validate.rules).string = {min_len: 1, max_len: 200},
(validate.rules).string = {max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
description: "the oidc issuer of the identity provider";
min_length: 1;
max_length: 200;
}
];
@ -2308,6 +2309,24 @@ message AddOIDCIDPRequest {
description: "definition which field is mapped to the email of the user";
}
];
// If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer
string authorization_endpoint = 9 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/o/oauth2/v2/auth\"";
description: "the oauth2 authorization endpoint of the identity provider";
max_length: 500;
}
];
// If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer
string token_endpoint = 10 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://oauth2.googleapis.com/token\"";
description: "the oauth2 token endpoint of the identity provider";
max_length: 500;
}
];
}
message AddOIDCIDPResponse {
@ -2420,6 +2439,8 @@ message UpdateIDPOIDCConfigRequest {
max_length: 200;
}
];
// Fill the issuer if the identity provider is oidc discovery compliant
// If the identity provider is only oauth2 compliant or does not serve a openid configuration, fill the authorization and token endpoint instead
string issuer = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
@ -2462,6 +2483,24 @@ message UpdateIDPOIDCConfigRequest {
description: "definition which field is mapped to the email of the user";
}
];
// If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer
string authorization_endpoint = 8 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/o/oauth2/v2/auth\"";
description: "the oauth2 authorization endpoint of the identity provider";
max_length: 500;
}
];
// If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer
string token_endpoint = 9 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://oauth2.googleapis.com/token\"";
description: "the oauth2 token endpoint of the identity provider";
max_length: 500;
}
];
}
message UpdateIDPOIDCConfigResponse {

View File

@ -153,6 +153,22 @@ message OIDCConfig {
description: "definition which field is mapped to the email of the user";
}
];
string authorization_endpoint = 6 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/o/oauth2/v2/auth\"";
description: "the oauth2 authorization endpoint of the identity provider";
max_length: 500;
}
];
string token_endpoint = 7 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://oauth2.googleapis.com/token\"";
description: "the oauth2 token endpoint of the identity provider";
max_length: 500;
}
];
}
enum OIDCMappingField {

View File

@ -4585,8 +4585,10 @@ message AddOrgOIDCIDPRequest {
description: "client secret generated by the identity provider";
}
];
// Fill the issuer if the identity provider is oidc discovery compliant
// If the identity provider is only oauth2 compliant or does not serve a openid configuration, fill the authorization and token endpoint instead
string issuer = 5 [
(validate.rules).string = {min_len: 1, max_len: 200},
(validate.rules).string = {max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
description: "the oidc issuer of the identity provider";
@ -4610,6 +4612,24 @@ message AddOrgOIDCIDPRequest {
description: "definition which field is mapped to the email of the user";
}
];
// If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer
string authorization_endpoint = 9 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/o/oauth2/v2/auth\"";
description: "the oauth2 authorization endpoint of the identity provider";
max_length: 500;
}
];
// If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer
string token_endpoint = 10 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://oauth2.googleapis.com/token\"";
description: "the oauth2 token endpoint of the identity provider";
max_length: 500;
}
];
}
message AddOrgOIDCIDPResponse {
@ -4680,6 +4700,8 @@ message UpdateOrgIDPOIDCConfigRequest {
description: "client secret generated by the identity provider. If empty the secret is not overwritten";
}
];
// Fill the issuer if the identity provider is oidc discovery compliant
// If the identity provider is only oauth2 compliant or does not serve a openid configuration, fill the authorization and token endpoint instead
string issuer = 4 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
@ -4705,6 +4727,24 @@ message UpdateOrgIDPOIDCConfigRequest {
description: "definition which field is mapped to the email of the user";
}
];
// If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer
string authorization_endpoint = 8 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/o/oauth2/v2/auth\"";
description: "the oauth2 authorization endpoint of the identity provider";
max_length: 500;
}
];
// If the identity provider does not serve an openid configuration, fill the authorization and token endpoint instead of the issuer
string token_endpoint = 9 [
(validate.rules).string = {max_len: 500},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://oauth2.googleapis.com/token\"";
description: "the oauth2 token endpoint of the identity provider";
max_length: 500;
}
];
}
message UpdateOrgIDPOIDCConfigResponse {