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:
Livio Spring
2022-10-06 13:30:14 +02:00
committed by GitHub
parent ce22961d8e
commit bffb10a4b4
46 changed files with 519 additions and 370 deletions

View File

@@ -17,6 +17,7 @@ func updateLoginPolicyToDomain(p *admin_pb.UpdateLoginPolicyRequest) *domain.Log
PasswordlessType: policy_grpc.PasswordlessTypeToDomain(p.PasswordlessType),
HidePasswordReset: p.HidePasswordReset,
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
AllowDomainDiscovery: p.AllowDomainDiscovery,
DefaultRedirectURI: p.DefaultRedirectUri,
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),

View File

@@ -26,7 +26,7 @@ func (s *Server) GetMyOrg(ctx context.Context, req *mgmt_pb.GetMyOrgRequest) (*m
}
func (s *Server) GetOrgByDomainGlobal(ctx context.Context, req *mgmt_pb.GetOrgByDomainGlobalRequest) (*mgmt_pb.GetOrgByDomainGlobalResponse, error) {
org, err := s.query.OrgByDomainGlobal(ctx, req.Domain)
org, err := s.query.OrgByPrimaryDomain(ctx, req.Domain)
if err != nil {
return nil, err
}

View File

@@ -18,6 +18,7 @@ func AddLoginPolicyToDomain(p *mgmt_pb.AddCustomLoginPolicyRequest) *domain.Logi
PasswordlessType: policy_grpc.PasswordlessTypeToDomain(p.PasswordlessType),
HidePasswordReset: p.HidePasswordReset,
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
AllowDomainDiscovery: p.AllowDomainDiscovery,
DefaultRedirectURI: p.DefaultRedirectUri,
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),
@@ -49,6 +50,7 @@ func updateLoginPolicyToDomain(p *mgmt_pb.UpdateCustomLoginPolicyRequest) *domai
PasswordlessType: policy_grpc.PasswordlessTypeToDomain(p.PasswordlessType),
HidePasswordReset: p.HidePasswordReset,
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
AllowDomainDiscovery: p.AllowDomainDiscovery,
DefaultRedirectURI: p.DefaultRedirectUri,
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),

View File

@@ -21,6 +21,7 @@ func ModelLoginPolicyToPb(policy *query.LoginPolicy) *policy_pb.LoginPolicy {
PasswordlessType: ModelPasswordlessTypeToPb(policy.PasswordlessType),
HidePasswordReset: policy.HidePasswordReset,
IgnoreUnknownUsernames: policy.IgnoreUnknownUsernames,
AllowDomainDiscovery: policy.AllowDomainDiscovery,
DefaultRedirectUri: policy.DefaultRedirectURI,
PasswordCheckLifetime: durationpb.New(policy.PasswordCheckLifetime),
ExternalLoginCheckLifetime: durationpb.New(policy.ExternalLoginCheckLifetime),

View File

@@ -91,7 +91,7 @@ func (o *OPStorage) ValidateJWTProfileScopes(ctx context.Context, subject string
scope := scopes[i]
if strings.HasPrefix(scope, domain.OrgDomainPrimaryScope) {
var orgID string
org, err := o.query.OrgByDomainGlobal(ctx, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
org, err := o.query.OrgByPrimaryDomain(ctx, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
if err == nil {
orgID = org.ID
}

View File

@@ -59,11 +59,15 @@ func (l *Login) handleExternalRegister(w http.ResponseWriter, r *http.Request) {
l.renderError(w, r, authReq, err)
return
}
l.handleExternalRegisterByConfigID(w, r, authReq, data.IDPConfigID)
}
func (l *Login) handleExternalRegisterByConfigID(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, configID string) {
if authReq == nil {
l.defaultRedirect(w, r)
return
}
idpConfig, err := l.getIDPConfigByID(r, data.IDPConfigID)
idpConfig, err := l.getIDPConfigByID(r, configID)
if err != nil {
l.renderError(w, r, authReq, err)
return

View File

@@ -33,12 +33,29 @@ func (l *Login) renderRegisterOption(w http.ResponseWriter, r *http.Request, aut
if err != nil {
errID, errMessage = l.getErrorMessage(r, err)
}
allowed := registrationAllowed(authReq)
externalAllowed := externalRegistrationAllowed(authReq)
if err == nil {
// if only external allowed with a single idp then use that
if !allowed && externalAllowed && len(authReq.AllowedExternalIDPs) == 1 {
l.handleExternalRegisterByConfigID(w, r, authReq, authReq.AllowedExternalIDPs[0].IDPConfigID)
return
}
// if only direct registration is allowed, show the form
if allowed && !externalAllowed {
l.renderRegister(w, r, authReq, nil, nil)
return
}
}
data := registerOptionData{
baseData: l.getBaseData(r, authReq, "RegisterOption", errID, errMessage),
}
funcs := map[string]interface{}{
"hasRegistration": func() bool {
return allowed
},
"hasExternalLogin": func() bool {
return authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0
return externalAllowed
},
}
translator := l.getTranslator(r.Context(), authReq)
@@ -58,3 +75,11 @@ func (l *Login) handleRegisterOptionCheck(w http.ResponseWriter, r *http.Request
}
l.handleRegisterOption(w, r)
}
func registrationAllowed(authReq *domain.AuthRequest) bool {
return authReq != nil && authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowRegister
}
func externalRegistrationAllowed(authReq *domain.AuthRequest) bool {
return authReq != nil && authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0
}

View File

@@ -17,7 +17,7 @@
</a>
</div>
<div class="lgn-register-options">
{{if .LoginPolicy.AllowUsernamePassword }}
{{if hasRegistration }}
<button class="lgn-raised-button lgn-primary" name="usernamepassword" value="true"
formnovalidate>{{t "RegisterOption.RegisterUsernamePasswordButtonText"}}</button>
{{end}}
@@ -42,4 +42,4 @@
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
{{template "main-bottom" .}}
{{template "main-bottom" .}}