mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:17:32 +00:00
feat: allow domain discovery for unknown usernames (#4484)
* fix: wait for projection initialization to be done * feat: allow domain discovery for unknown usernames * fix linting * Update console/src/assets/i18n/de.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update console/src/assets/i18n/en.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update console/src/assets/i18n/it.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update console/src/assets/i18n/fr.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * fix zh i18n text * fix projection table name Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com>
This commit is contained in:
@@ -93,7 +93,7 @@ type userCommandProvider interface {
|
||||
|
||||
type orgViewProvider interface {
|
||||
OrgByID(context.Context, bool, string) (*query.Org, error)
|
||||
OrgByDomainGlobal(context.Context, string) (*query.Org, error)
|
||||
OrgByPrimaryDomain(context.Context, string) (*query.Org, error)
|
||||
}
|
||||
|
||||
type userGrantProvider interface {
|
||||
@@ -651,23 +651,57 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain
|
||||
}
|
||||
}
|
||||
}
|
||||
if request.LoginPolicy != nil && request.LoginPolicy.IgnoreUnknownUsernames {
|
||||
if errors.IsNotFound(err) || (user != nil && user.State == int32(domain.UserStateInactive)) {
|
||||
if request.LabelPolicy != nil && request.LabelPolicy.HideLoginNameSuffix {
|
||||
preferredLoginName = loginName
|
||||
}
|
||||
request.SetUserInfo(unknownUserID, preferredLoginName, preferredLoginName, preferredLoginName, "", request.RequestedOrgID)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
// return any error apart from not found ones directly
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if user.State == int32(domain.UserStateInactive) {
|
||||
// if there's an active user, let's use it
|
||||
if user != nil && user.State == int32(domain.UserStateActive) {
|
||||
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", "", user.ResourceOwner)
|
||||
return nil
|
||||
}
|
||||
// the user was either not found or not active
|
||||
// so check if the loginname suffix matches a verified org domain
|
||||
if repo.checkDomainDiscovery(ctx, request, loginName) {
|
||||
return nil
|
||||
}
|
||||
// let's just check for if unknown usernames are ignored
|
||||
if request.LoginPolicy != nil && request.LoginPolicy.IgnoreUnknownUsernames {
|
||||
if request.LabelPolicy != nil && request.LabelPolicy.HideLoginNameSuffix {
|
||||
preferredLoginName = loginName
|
||||
}
|
||||
request.SetUserInfo(unknownUserID, preferredLoginName, preferredLoginName, preferredLoginName, "", request.RequestedOrgID)
|
||||
return nil
|
||||
}
|
||||
// there was no policy that allowed unknown loginnames in any case
|
||||
// let's once again check if the user was just inactive
|
||||
if user != nil && user.State == int32(domain.UserStateInactive) {
|
||||
return errors.ThrowPreconditionFailed(nil, "AUTH-2n8fs", "Errors.User.Inactive")
|
||||
}
|
||||
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", "", user.ResourceOwner)
|
||||
return nil
|
||||
// user was not found
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkDomainDiscovery(ctx context.Context, request *domain.AuthRequest, loginName string) bool {
|
||||
// check if there's a suffix in the loginname
|
||||
split := strings.Split(loginName, "@")
|
||||
if len(split) < 2 {
|
||||
return false
|
||||
}
|
||||
// check if the suffix matches a verified domain
|
||||
org, err := repo.Query.OrgByVerifiedDomain(ctx, split[len(split)-1])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// and if the login policy allows domain discovery
|
||||
policy, err := repo.Query.LoginPolicyByID(ctx, true, org.ID)
|
||||
if err != nil || !policy.AllowDomainDiscovery {
|
||||
return false
|
||||
}
|
||||
// discovery was allowed, so set the org as requested org
|
||||
request.SetOrgInformation(org.ID, org.Name, org.Domain, false)
|
||||
request.Prompt = append(request.Prompt, domain.PromptCreate)
|
||||
return true
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkLoginPolicyWithResourceOwner(ctx context.Context, request *domain.AuthRequest, user *user_view_model.UserView) error {
|
||||
@@ -1075,9 +1109,7 @@ func setOrgID(ctx context.Context, orgViewProvider orgViewProvider, request *dom
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.RequestedOrgID = org.ID
|
||||
request.RequestedOrgName = org.Name
|
||||
request.RequestedPrimaryDomain = org.Domain
|
||||
request.SetOrgInformation(org.ID, org.Name, org.Domain, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1086,14 +1118,11 @@ func setOrgID(ctx context.Context, orgViewProvider orgViewProvider, request *dom
|
||||
return nil
|
||||
}
|
||||
|
||||
org, err := orgViewProvider.OrgByDomainGlobal(ctx, primaryDomain)
|
||||
org, err := orgViewProvider.OrgByPrimaryDomain(ctx, primaryDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.RequestedOrgID = org.ID
|
||||
request.RequestedOrgName = org.Name
|
||||
request.RequestedPrimaryDomain = primaryDomain
|
||||
request.RequestedOrgDomain = true
|
||||
request.SetOrgInformation(org.ID, org.Name, primaryDomain, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -174,7 +174,7 @@ func (m *mockViewOrg) OrgByID(context.Context, bool, string) (*query.Org, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mockViewOrg) OrgByDomainGlobal(context.Context, string) (*query.Org, error) {
|
||||
func (m *mockViewOrg) OrgByPrimaryDomain(context.Context, string) (*query.Org, error) {
|
||||
return &query.Org{
|
||||
State: m.State,
|
||||
}, nil
|
||||
@@ -186,7 +186,7 @@ func (m *mockViewErrOrg) OrgByID(context.Context, bool, string) (*query.Org, err
|
||||
return nil, errors.ThrowInternal(nil, "id", "internal error")
|
||||
}
|
||||
|
||||
func (m *mockViewErrOrg) OrgByDomainGlobal(context.Context, string) (*query.Org, error) {
|
||||
func (m *mockViewErrOrg) OrgByPrimaryDomain(context.Context, string) (*query.Org, error) {
|
||||
return nil, errors.ThrowInternal(nil, "id", "internal error")
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user