mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 00:27:31 +00:00
fix: use of generic oauth provider (#5345)
Adds a id_attribute to the GenericOAuthProvider, which is used to map the external User. Further mapping can be done in actions by using the `rawInfo` of the new `ctx.v1.providerInfo` field.
This commit is contained in:
@@ -16,6 +16,7 @@ type GenericOAuthProvider struct {
|
||||
TokenEndpoint string
|
||||
UserEndpoint string
|
||||
Scopes []string
|
||||
IDAttribute string
|
||||
IDPOptions idp.Options
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,7 @@ type OAuthIDPWriteModel struct {
|
||||
TokenEndpoint string
|
||||
UserEndpoint string
|
||||
Scopes []string
|
||||
IDAttribute string
|
||||
idp.Options
|
||||
|
||||
State domain.IDPState
|
||||
@@ -48,6 +49,7 @@ func (wm *OAuthIDPWriteModel) reduceAddedEvent(e *idp.OAuthIDPAddedEvent) {
|
||||
wm.TokenEndpoint = e.TokenEndpoint
|
||||
wm.UserEndpoint = e.UserEndpoint
|
||||
wm.Scopes = e.Scopes
|
||||
wm.IDAttribute = e.IDAttribute
|
||||
wm.State = domain.IDPStateActive
|
||||
}
|
||||
|
||||
@@ -73,6 +75,9 @@ func (wm *OAuthIDPWriteModel) reduceChangedEvent(e *idp.OAuthIDPChangedEvent) {
|
||||
if e.Scopes != nil {
|
||||
wm.Scopes = e.Scopes
|
||||
}
|
||||
if e.IDAttribute != nil {
|
||||
wm.IDAttribute = *e.IDAttribute
|
||||
}
|
||||
wm.Options.ReduceChanges(e.OptionChanges)
|
||||
}
|
||||
|
||||
@@ -83,7 +88,8 @@ func (wm *OAuthIDPWriteModel) NewChanges(
|
||||
secretCrypto crypto.Crypto,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint string,
|
||||
userEndpoint,
|
||||
idAttribute string,
|
||||
scopes []string,
|
||||
options idp.Options,
|
||||
) ([]idp.OAuthIDPChanges, error) {
|
||||
@@ -115,6 +121,9 @@ func (wm *OAuthIDPWriteModel) NewChanges(
|
||||
if !reflect.DeepEqual(wm.Scopes, scopes) {
|
||||
changes = append(changes, idp.ChangeOAuthScopes(scopes))
|
||||
}
|
||||
if wm.IDAttribute != idAttribute {
|
||||
changes = append(changes, idp.ChangeOAuthIDAttribute(idAttribute))
|
||||
}
|
||||
opts := wm.Options.Changes(options)
|
||||
if !opts.IsZero() {
|
||||
changes = append(changes, idp.ChangeOAuthOptions(opts))
|
||||
|
@@ -273,6 +273,9 @@ func (c *Commands) prepareAddInstanceOAuthProvider(a *instance.Aggregate, writeM
|
||||
if provider.UserEndpoint = strings.TrimSpace(provider.UserEndpoint); provider.UserEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Fb8jk", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.IDAttribute = strings.TrimSpace(provider.IDAttribute); provider.IDAttribute == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-sdf3f", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
@@ -297,6 +300,7 @@ func (c *Commands) prepareAddInstanceOAuthProvider(a *instance.Aggregate, writeM
|
||||
provider.AuthorizationEndpoint,
|
||||
provider.TokenEndpoint,
|
||||
provider.UserEndpoint,
|
||||
provider.IDAttribute,
|
||||
provider.Scopes,
|
||||
provider.IDPOptions,
|
||||
),
|
||||
@@ -322,6 +326,9 @@ func (c *Commands) prepareUpdateInstanceOAuthProvider(a *instance.Aggregate, wri
|
||||
if provider.UserEndpoint = strings.TrimSpace(provider.UserEndpoint); provider.UserEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Fb8jk", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.IDAttribute = strings.TrimSpace(provider.IDAttribute); provider.IDAttribute == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-asf3fs", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
@@ -345,6 +352,7 @@ func (c *Commands) prepareUpdateInstanceOAuthProvider(a *instance.Aggregate, wri
|
||||
provider.AuthorizationEndpoint,
|
||||
provider.TokenEndpoint,
|
||||
provider.UserEndpoint,
|
||||
provider.IDAttribute,
|
||||
provider.Scopes,
|
||||
provider.IDPOptions,
|
||||
)
|
||||
|
@@ -67,7 +67,8 @@ func (wm *InstanceOAuthIDPWriteModel) NewChangedEvent(
|
||||
secretCrypto crypto.Crypto,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint string,
|
||||
userEndpoint,
|
||||
idAttribute string,
|
||||
scopes []string,
|
||||
options idp.Options,
|
||||
) (*instance.OAuthIDPChangedEvent, error) {
|
||||
@@ -80,6 +81,7 @@ func (wm *InstanceOAuthIDPWriteModel) NewChangedEvent(
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint,
|
||||
idAttribute,
|
||||
scopes,
|
||||
options,
|
||||
)
|
||||
|
@@ -145,6 +145,27 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid id attribute",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ok",
|
||||
fields: fields{
|
||||
@@ -167,6 +188,7 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
"idAttribute",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
@@ -185,6 +207,7 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
IDAttribute: "idAttribute",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -214,6 +237,7 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
"idAttribute",
|
||||
[]string{"user"},
|
||||
idp.Options{
|
||||
IsCreationAllowed: true,
|
||||
@@ -238,6 +262,7 @@ func TestCommandSide_AddInstanceGenericOAuthIDP(t *testing.T) {
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
Scopes: []string{"user"},
|
||||
IDAttribute: "idAttribute",
|
||||
IDPOptions: idp.Options{
|
||||
IsCreationAllowed: true,
|
||||
IsLinkingAllowed: true,
|
||||
@@ -390,6 +415,26 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid id attribute",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
fields: fields{
|
||||
@@ -406,6 +451,7 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
IDAttribute: "idAttribute",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -431,6 +477,7 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
"idAttribute",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
@@ -446,6 +493,7 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
IDAttribute: "idAttribute",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -471,6 +519,7 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
"idAttribute",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
@@ -496,6 +545,7 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
||||
idp.ChangeOAuthTokenEndpoint("new token"),
|
||||
idp.ChangeOAuthUserEndpoint("new user"),
|
||||
idp.ChangeOAuthScopes([]string{"openid", "profile"}),
|
||||
idp.ChangeOAuthIDAttribute("newAttribute"),
|
||||
idp.ChangeOAuthOptions(idp.OptionChanges{
|
||||
IsCreationAllowed: &t,
|
||||
IsLinkingAllowed: &t,
|
||||
@@ -523,6 +573,7 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
||||
TokenEndpoint: "new token",
|
||||
UserEndpoint: "new user",
|
||||
Scopes: []string{"openid", "profile"},
|
||||
IDAttribute: "newAttribute",
|
||||
IDPOptions: idp.Options{
|
||||
IsCreationAllowed: true,
|
||||
IsLinkingAllowed: true,
|
||||
|
@@ -262,6 +262,9 @@ func (c *Commands) prepareAddOrgOAuthProvider(a *org.Aggregate, writeModel *OrgO
|
||||
if provider.UserEndpoint = strings.TrimSpace(provider.UserEndpoint); provider.UserEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-Fb8jk", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.IDAttribute = strings.TrimSpace(provider.IDAttribute); provider.IDAttribute == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-sadf3d", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
@@ -286,6 +289,7 @@ func (c *Commands) prepareAddOrgOAuthProvider(a *org.Aggregate, writeModel *OrgO
|
||||
provider.AuthorizationEndpoint,
|
||||
provider.TokenEndpoint,
|
||||
provider.UserEndpoint,
|
||||
provider.IDAttribute,
|
||||
provider.Scopes,
|
||||
provider.IDPOptions,
|
||||
),
|
||||
@@ -314,6 +318,9 @@ func (c *Commands) prepareUpdateOrgOAuthProvider(a *org.Aggregate, writeModel *O
|
||||
if provider.UserEndpoint = strings.TrimSpace(provider.UserEndpoint); provider.UserEndpoint == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-Fb8jk", "Errors.Invalid.Argument")
|
||||
}
|
||||
if provider.IDAttribute = strings.TrimSpace(provider.IDAttribute); provider.IDAttribute == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-SAe4gh", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
@@ -337,6 +344,7 @@ func (c *Commands) prepareUpdateOrgOAuthProvider(a *org.Aggregate, writeModel *O
|
||||
provider.AuthorizationEndpoint,
|
||||
provider.TokenEndpoint,
|
||||
provider.UserEndpoint,
|
||||
provider.IDAttribute,
|
||||
provider.Scopes,
|
||||
provider.IDPOptions,
|
||||
)
|
||||
|
@@ -69,7 +69,8 @@ func (wm *OrgOAuthIDPWriteModel) NewChangedEvent(
|
||||
secretCrypto crypto.Crypto,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint string,
|
||||
userEndpoint,
|
||||
idAttribute string,
|
||||
scopes []string,
|
||||
options idp.Options,
|
||||
) (*org.OAuthIDPChangedEvent, error) {
|
||||
@@ -82,6 +83,7 @@ func (wm *OrgOAuthIDPWriteModel) NewChangedEvent(
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
userEndpoint,
|
||||
idAttribute,
|
||||
scopes,
|
||||
options,
|
||||
)
|
||||
|
@@ -150,6 +150,28 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid id attribute",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
ClientSecret: "clientSecret",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ok",
|
||||
fields: fields{
|
||||
@@ -170,6 +192,7 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
"idAttribute",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
@@ -188,6 +211,7 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
IDAttribute: "idAttribute",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -215,6 +239,7 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
"idAttribute",
|
||||
[]string{"user"},
|
||||
idp.Options{
|
||||
IsCreationAllowed: true,
|
||||
@@ -239,6 +264,7 @@ func TestCommandSide_AddOrgGenericOAuthIDP(t *testing.T) {
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
Scopes: []string{"user"},
|
||||
IDAttribute: "idAttribute",
|
||||
IDPOptions: idp.Options{
|
||||
IsCreationAllowed: true,
|
||||
IsLinkingAllowed: true,
|
||||
@@ -398,6 +424,27 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid id attribute",
|
||||
fields{
|
||||
eventstore: eventstoreExpect(t),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: GenericOAuthProvider{
|
||||
Name: "name",
|
||||
ClientID: "clientID",
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: caos_errors.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
fields: fields{
|
||||
@@ -415,6 +462,7 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
IDAttribute: "idAttribute",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -440,6 +488,7 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
"idAttribute",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
@@ -456,6 +505,7 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
||||
AuthorizationEndpoint: "auth",
|
||||
TokenEndpoint: "token",
|
||||
UserEndpoint: "user",
|
||||
IDAttribute: "idAttribute",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -481,6 +531,7 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
||||
"auth",
|
||||
"token",
|
||||
"user",
|
||||
"idAttribute",
|
||||
nil,
|
||||
idp.Options{},
|
||||
)),
|
||||
@@ -504,6 +555,7 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
||||
idp.ChangeOAuthTokenEndpoint("new token"),
|
||||
idp.ChangeOAuthUserEndpoint("new user"),
|
||||
idp.ChangeOAuthScopes([]string{"openid", "profile"}),
|
||||
idp.ChangeOAuthIDAttribute("newAttribute"),
|
||||
idp.ChangeOAuthOptions(idp.OptionChanges{
|
||||
IsCreationAllowed: &t,
|
||||
IsLinkingAllowed: &t,
|
||||
@@ -531,6 +583,7 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
||||
TokenEndpoint: "new token",
|
||||
UserEndpoint: "new user",
|
||||
Scopes: []string{"openid", "profile"},
|
||||
IDAttribute: "newAttribute",
|
||||
IDPOptions: idp.Options{
|
||||
IsCreationAllowed: true,
|
||||
IsLinkingAllowed: true,
|
||||
|
Reference in New Issue
Block a user