mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 04:17:32 +00:00
feat(login): use new IDP templates (#5315)
The login uses the new template based IDPs with backwards compatibility for old IDPs
This commit is contained in:
@@ -15,9 +15,10 @@ import (
|
||||
)
|
||||
|
||||
type IDPLoginPolicyLink struct {
|
||||
IDPID string
|
||||
IDPName string
|
||||
IDPType domain.IDPConfigType
|
||||
IDPID string
|
||||
IDPName string
|
||||
IDPType domain.IDPType
|
||||
OwnerType domain.IdentityProviderType
|
||||
}
|
||||
|
||||
type IDPLoginPolicyLinks struct {
|
||||
@@ -113,25 +114,28 @@ func (q *Queries) IDPLoginPolicyLinks(ctx context.Context, resourceOwner string,
|
||||
func prepareIDPLoginPolicyLinksQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPLoginPolicyLinks, error)) {
|
||||
return sq.Select(
|
||||
IDPLoginPolicyLinkIDPIDCol.identifier(),
|
||||
IDPNameCol.identifier(),
|
||||
IDPTypeCol.identifier(),
|
||||
IDPTemplateNameCol.identifier(),
|
||||
IDPTemplateTypeCol.identifier(),
|
||||
IDPTemplateOwnerTypeCol.identifier(),
|
||||
countColumn.identifier()).
|
||||
From(idpLoginPolicyLinkTable.identifier()).
|
||||
LeftJoin(join(IDPIDCol, IDPLoginPolicyLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
|
||||
LeftJoin(join(IDPTemplateIDCol, IDPLoginPolicyLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(rows *sql.Rows) (*IDPLoginPolicyLinks, error) {
|
||||
links := make([]*IDPLoginPolicyLink, 0)
|
||||
var count uint64
|
||||
for rows.Next() {
|
||||
var (
|
||||
idpName = sql.NullString{}
|
||||
idpType = sql.NullInt16{}
|
||||
link = new(IDPLoginPolicyLink)
|
||||
idpName = sql.NullString{}
|
||||
idpType = sql.NullInt16{}
|
||||
idpOwnerType = sql.NullInt16{}
|
||||
link = new(IDPLoginPolicyLink)
|
||||
)
|
||||
err := rows.Scan(
|
||||
&link.IDPID,
|
||||
&idpName,
|
||||
&idpType,
|
||||
&idpOwnerType,
|
||||
&count,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -140,10 +144,11 @@ func prepareIDPLoginPolicyLinksQuery(ctx context.Context, db prepareDatabase) (s
|
||||
link.IDPName = idpName.String
|
||||
//IDPType 0 is oidc so we have to set unspecified manually
|
||||
if idpType.Valid {
|
||||
link.IDPType = domain.IDPConfigType(idpType.Int16)
|
||||
link.IDPType = domain.IDPType(idpType.Int16)
|
||||
} else {
|
||||
link.IDPType = domain.IDPConfigTypeUnspecified
|
||||
link.IDPType = domain.IDPTypeUnspecified
|
||||
}
|
||||
link.OwnerType = domain.IdentityProviderType(idpOwnerType.Int16)
|
||||
links = append(links, link)
|
||||
}
|
||||
|
||||
|
@@ -13,16 +13,18 @@ import (
|
||||
|
||||
var (
|
||||
loginPolicyIDPLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_login_policy_links4.idp_id,` +
|
||||
` projections.idps3.name,` +
|
||||
` projections.idps3.type,` +
|
||||
` projections.idp_templates2.name,` +
|
||||
` projections.idp_templates2.type,` +
|
||||
` projections.idp_templates2.owner_type,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.idp_login_policy_links4` +
|
||||
` LEFT JOIN projections.idps3 ON projections.idp_login_policy_links4.idp_id = projections.idps3.id AND projections.idp_login_policy_links4.instance_id = projections.idps3.instance_id` +
|
||||
` LEFT JOIN projections.idp_templates2 ON projections.idp_login_policy_links4.idp_id = projections.idp_templates2.id AND projections.idp_login_policy_links4.instance_id = projections.idp_templates2.instance_id` +
|
||||
` AS OF SYSTEM TIME '-1 ms'`)
|
||||
loginPolicyIDPLinksCols = []string{
|
||||
"idp_id",
|
||||
"name",
|
||||
"type",
|
||||
"owner_type",
|
||||
"count",
|
||||
}
|
||||
)
|
||||
@@ -49,7 +51,8 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
|
||||
{
|
||||
"idp-id",
|
||||
"idp-name",
|
||||
domain.IDPConfigTypeJWT,
|
||||
domain.IDPTypeJWT,
|
||||
domain.IdentityProviderTypeSystem,
|
||||
},
|
||||
},
|
||||
),
|
||||
@@ -60,9 +63,10 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
|
||||
},
|
||||
Links: []*IDPLoginPolicyLink{
|
||||
{
|
||||
IDPID: "idp-id",
|
||||
IDPName: "idp-name",
|
||||
IDPType: domain.IDPConfigTypeJWT,
|
||||
IDPID: "idp-id",
|
||||
IDPName: "idp-name",
|
||||
IDPType: domain.IDPTypeJWT,
|
||||
OwnerType: domain.IdentityProviderTypeSystem,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -79,6 +83,7 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
|
||||
"idp-id",
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
},
|
||||
),
|
||||
@@ -91,7 +96,7 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
|
||||
{
|
||||
IDPID: "idp-id",
|
||||
IDPName: "",
|
||||
IDPType: domain.IDPConfigTypeUnspecified,
|
||||
IDPType: domain.IDPTypeUnspecified,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@@ -386,8 +386,8 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// IDPTemplateByIDAndResourceOwner searches for the requested id in the context of the resource owner and IAM
|
||||
func (q *Queries) IDPTemplateByIDAndResourceOwner(ctx context.Context, shouldTriggerBulk bool, id, resourceOwner string, withOwnerRemoved bool) (_ *IDPTemplate, err error) {
|
||||
// IDPTemplateByID searches for the requested id
|
||||
func (q *Queries) IDPTemplateByID(ctx context.Context, shouldTriggerBulk bool, id string, withOwnerRemoved bool, queries ...SearchQuery) (_ *IDPTemplate, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
@@ -403,20 +403,16 @@ func (q *Queries) IDPTemplateByIDAndResourceOwner(ctx context.Context, shouldTri
|
||||
if !withOwnerRemoved {
|
||||
eq[IDPTemplateOwnerRemovedCol.identifier()] = false
|
||||
}
|
||||
where := sq.And{
|
||||
eq,
|
||||
sq.Or{
|
||||
sq.Eq{IDPTemplateResourceOwnerCol.identifier(): resourceOwner},
|
||||
sq.Eq{IDPTemplateResourceOwnerCol.identifier(): authz.GetInstance(ctx).InstanceID()},
|
||||
},
|
||||
query, scan := prepareIDPTemplateByIDQuery(ctx, q.client)
|
||||
for _, q := range queries {
|
||||
query = q.toQuery(query)
|
||||
}
|
||||
stmt, scan := prepareIDPTemplateByIDQuery(ctx, q.client)
|
||||
query, args, err := stmt.Where(where).ToSql()
|
||||
stmt, args, err := query.Where(eq).ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "QUERY-SFAew", "Errors.Query.SQLStatement")
|
||||
return nil, errors.ThrowInternal(err, "QUERY-SFefg", "Errors.Query.SQLStatement")
|
||||
}
|
||||
|
||||
row := q.client.QueryRowContext(ctx, query, args...)
|
||||
row := q.client.QueryRowContext(ctx, stmt, args...)
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
|
@@ -21,7 +21,7 @@ type IDPUserLink struct {
|
||||
ProvidedUserID string
|
||||
ProvidedUsername string
|
||||
ResourceOwner string
|
||||
IDPType domain.IDPConfigType
|
||||
IDPType domain.IDPType
|
||||
}
|
||||
|
||||
type IDPUserLinks struct {
|
||||
@@ -127,18 +127,22 @@ func NewIDPUserLinksResourceOwnerSearchQuery(value string) (SearchQuery, error)
|
||||
return NewTextQuery(IDPUserLinkResourceOwnerCol, value, TextEquals)
|
||||
}
|
||||
|
||||
func NewIDPUserLinksExternalIDSearchQuery(value string) (SearchQuery, error) {
|
||||
return NewTextQuery(IDPUserLinkExternalUserIDCol, value, TextEquals)
|
||||
}
|
||||
|
||||
func prepareIDPUserLinksQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLinks, error)) {
|
||||
return sq.Select(
|
||||
IDPUserLinkIDPIDCol.identifier(),
|
||||
IDPUserLinkUserIDCol.identifier(),
|
||||
IDPNameCol.identifier(),
|
||||
IDPTemplateNameCol.identifier(),
|
||||
IDPUserLinkExternalUserIDCol.identifier(),
|
||||
IDPUserLinkDisplayNameCol.identifier(),
|
||||
IDPTypeCol.identifier(),
|
||||
IDPTemplateTypeCol.identifier(),
|
||||
IDPUserLinkResourceOwnerCol.identifier(),
|
||||
countColumn.identifier()).
|
||||
From(idpUserLinkTable.identifier()).
|
||||
LeftJoin(join(IDPIDCol, IDPUserLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
|
||||
LeftJoin(join(IDPTemplateIDCol, IDPUserLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(rows *sql.Rows) (*IDPUserLinks, error) {
|
||||
idps := make([]*IDPUserLink, 0)
|
||||
@@ -165,9 +169,9 @@ func prepareIDPUserLinksQuery(ctx context.Context, db prepareDatabase) (sq.Selec
|
||||
idp.IDPName = idpName.String
|
||||
//IDPType 0 is oidc so we have to set unspecified manually
|
||||
if idpType.Valid {
|
||||
idp.IDPType = domain.IDPConfigType(idpType.Int16)
|
||||
idp.IDPType = domain.IDPType(idpType.Int16)
|
||||
} else {
|
||||
idp.IDPType = domain.IDPConfigTypeUnspecified
|
||||
idp.IDPType = domain.IDPTypeUnspecified
|
||||
}
|
||||
idps = append(idps, idp)
|
||||
}
|
||||
|
@@ -14,14 +14,14 @@ import (
|
||||
var (
|
||||
idpUserLinksQuery = regexp.QuoteMeta(`SELECT projections.idp_user_links3.idp_id,` +
|
||||
` projections.idp_user_links3.user_id,` +
|
||||
` projections.idps3.name,` +
|
||||
` projections.idp_templates2.name,` +
|
||||
` projections.idp_user_links3.external_user_id,` +
|
||||
` projections.idp_user_links3.display_name,` +
|
||||
` projections.idps3.type,` +
|
||||
` projections.idp_templates2.type,` +
|
||||
` projections.idp_user_links3.resource_owner,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.idp_user_links3` +
|
||||
` LEFT JOIN projections.idps3 ON projections.idp_user_links3.idp_id = projections.idps3.id AND projections.idp_user_links3.instance_id = projections.idps3.instance_id` +
|
||||
` LEFT JOIN projections.idp_templates2 ON projections.idp_user_links3.idp_id = projections.idp_templates2.id AND projections.idp_user_links3.instance_id = projections.idp_templates2.instance_id` +
|
||||
` AS OF SYSTEM TIME '-1 ms'`)
|
||||
idpUserLinksCols = []string{
|
||||
"idp_id",
|
||||
@@ -60,7 +60,7 @@ func Test_IDPUserLinkPrepares(t *testing.T) {
|
||||
"idp-name",
|
||||
"external-user-id",
|
||||
"display-name",
|
||||
domain.IDPConfigTypeJWT,
|
||||
domain.IDPTypeJWT,
|
||||
"ro",
|
||||
},
|
||||
},
|
||||
@@ -77,7 +77,7 @@ func Test_IDPUserLinkPrepares(t *testing.T) {
|
||||
IDPName: "idp-name",
|
||||
ProvidedUserID: "external-user-id",
|
||||
ProvidedUsername: "display-name",
|
||||
IDPType: domain.IDPConfigTypeJWT,
|
||||
IDPType: domain.IDPTypeJWT,
|
||||
ResourceOwner: "ro",
|
||||
},
|
||||
},
|
||||
@@ -114,7 +114,7 @@ func Test_IDPUserLinkPrepares(t *testing.T) {
|
||||
IDPName: "",
|
||||
ProvidedUserID: "external-user-id",
|
||||
ProvidedUsername: "display-name",
|
||||
IDPType: domain.IDPConfigTypeUnspecified,
|
||||
IDPType: domain.IDPTypeUnspecified,
|
||||
ResourceOwner: "ro",
|
||||
},
|
||||
},
|
||||
|
@@ -668,7 +668,7 @@ func (p *idpTemplateProjection) reduceOldConfigAdded(event eventstore.Event) (*h
|
||||
handler.NewCol(IDPTemplateStateCol, domain.IDPStateActive),
|
||||
handler.NewCol(IDPTemplateNameCol, idpEvent.Name),
|
||||
handler.NewCol(IDPTemplateOwnerTypeCol, idpOwnerType),
|
||||
handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeOIDC),
|
||||
handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeUnspecified),
|
||||
handler.NewCol(IDPTemplateIsCreationAllowedCol, true),
|
||||
handler.NewCol(IDPTemplateIsLinkingAllowedCol, true),
|
||||
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.AutoRegister),
|
||||
@@ -727,6 +727,7 @@ func (p *idpTemplateProjection) reduceOldOIDCConfigAdded(event eventstore.Event)
|
||||
[]handler.Column{
|
||||
handler.NewCol(IDPTemplateChangeDateCol, idpEvent.CreationDate()),
|
||||
handler.NewCol(IDPTemplateSequenceCol, idpEvent.Sequence()),
|
||||
handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeOIDC),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(IDPTemplateIDCol, idpEvent.IDPConfigID),
|
||||
@@ -820,6 +821,7 @@ func (p *idpTemplateProjection) reduceOldJWTConfigAdded(event eventstore.Event)
|
||||
[]handler.Column{
|
||||
handler.NewCol(IDPTemplateChangeDateCol, idpEvent.CreationDate()),
|
||||
handler.NewCol(IDPTemplateSequenceCol, idpEvent.Sequence()),
|
||||
handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeJWT),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(IDPTemplateIDCol, idpEvent.IDPConfigID),
|
||||
|
Reference in New Issue
Block a user