fix: show registration overview (#3002)

* fix: show registration overview

* fix: render error page to avoid possible loop
This commit is contained in:
Fabi 2022-01-18 08:46:31 +01:00 committed by GitHub
parent 7ea618121e
commit 456d32dd0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 152 additions and 15 deletions

View File

@ -35,6 +35,7 @@ type externalIDPCallbackData struct {
}
type externalNotFoundOptionFormData struct {
externalRegisterFormData
Link bool `schema:"linkbutton"`
AutoRegister bool `schema:"autoregisterbutton"`
ResetLinking bool `schema:"resetlinking"`
@ -43,6 +44,16 @@ type externalNotFoundOptionFormData struct {
type externalNotFoundOptionData struct {
baseData
externalNotFoundOptionFormData
ExternalIDPID string
ExternalIDPUserID string
ExternalIDPUserDisplayName string
ShowUsername bool
OrgRegister bool
ExternalEmail string
ExternalEmailVerified bool
ExternalPhone string
ExternalPhoneVerified bool
}
func (l *Login) handleExternalLoginStep(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, selectedIDPConfigID string) {
@ -186,18 +197,38 @@ func (l *Login) handleExternalUserAuthenticated(w http.ResponseWriter, r *http.R
l.renderError(w, r, authReq, err)
return
}
err = l.authRepo.CheckExternalUserLogin(r.Context(), authReq.ID, userAgentID, externalUser, domain.BrowserInfoFromRequest(r))
if err != nil {
if errors.IsNotFound(err) {
err = nil
}
iam, err := l.authRepo.GetIAM(r.Context())
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
return
}
resourceOwner := iam.GlobalOrgID
if authReq.RequestedOrgID != "" && authReq.RequestedOrgID != iam.GlobalOrgID {
resourceOwner = authReq.RequestedOrgID
}
orgIAMPolicy, err := l.getOrgIamPolicy(r, resourceOwner)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
return
}
human, idpLinking, _ := l.mapExternalUserToLoginUser(orgIAMPolicy, externalUser, idpConfig)
if !idpConfig.AutoRegister {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, iam, orgIAMPolicy, human, idpLinking, err)
return
}
authReq, err = l.authRepo.AuthRequestByID(r.Context(), authReq.ID, userAgentID)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, iam, orgIAMPolicy, human, idpLinking, err)
return
}
l.handleAutoRegister(w, r, authReq)
@ -217,13 +248,65 @@ func (l *Login) handleExternalUserAuthenticated(w http.ResponseWriter, r *http.R
l.renderNextStep(w, r, authReq)
}
func (l *Login) renderExternalNotFoundOption(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, err error) {
func (l *Login) renderExternalNotFoundOption(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, iam *iam_model.IAM, orgIAMPolicy *query.OrgIAMPolicy, human *domain.Human, externalIDP *domain.UserIDPLink, err error) {
var errID, errMessage string
if err != nil {
errID, errMessage = l.getErrorMessage(r, err)
}
if orgIAMPolicy == nil {
iam, err = l.authRepo.GetIAM(r.Context())
if err != nil {
l.renderError(w, r, authReq, err)
return
}
resourceOwner := iam.GlobalOrgID
if authReq.RequestedOrgID != "" && authReq.RequestedOrgID != iam.GlobalOrgID {
resourceOwner = authReq.RequestedOrgID
}
orgIAMPolicy, err = l.getOrgIamPolicy(r, resourceOwner)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
}
if human == nil || externalIDP == nil {
idpConfig, err := l.authRepo.GetIDPConfigByID(r.Context(), authReq.SelectedIDPConfigID)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
linkingUser := authReq.LinkingUsers[len(authReq.LinkingUsers)-1]
human, externalIDP, _ = l.mapExternalUserToLoginUser(orgIAMPolicy, linkingUser, idpConfig)
}
data := externalNotFoundOptionData{
baseData: l.getBaseData(r, authReq, "ExternalNotFoundOption", errID, errMessage),
externalNotFoundOptionFormData: externalNotFoundOptionFormData{
externalRegisterFormData: externalRegisterFormData{
Email: human.EmailAddress,
Username: human.Username,
Firstname: human.FirstName,
Lastname: human.LastName,
Nickname: human.NickName,
Language: human.PreferredLanguage.String(),
},
},
ExternalIDPID: externalIDP.IDPConfigID,
ExternalIDPUserID: externalIDP.ExternalUserID,
ExternalIDPUserDisplayName: externalIDP.DisplayName,
ExternalEmail: human.EmailAddress,
ExternalEmailVerified: human.IsEmailVerified,
ShowUsername: orgIAMPolicy.UserLoginMustBeDomain,
OrgRegister: orgIAMPolicy.UserLoginMustBeDomain,
}
if human.Phone != nil {
data.Phone = human.PhoneNumber
data.ExternalPhone = human.PhoneNumber
data.ExternalPhoneVerified = human.IsPhoneVerified
}
translator := l.getTranslator(authReq)
l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplExternalNotFoundOption], data, nil)
@ -233,7 +316,7 @@ func (l *Login) handleExternalNotFoundOptionCheck(w http.ResponseWriter, r *http
data := new(externalNotFoundOptionFormData)
authReq, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
return
}
if data.Link {
@ -243,7 +326,7 @@ func (l *Login) handleExternalNotFoundOptionCheck(w http.ResponseWriter, r *http
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
err = l.authRepo.ResetLinkingUsers(r.Context(), authReq.ID, userAgentID)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
}
l.handleLogin(w, r)
return
@ -254,7 +337,7 @@ func (l *Login) handleExternalNotFoundOptionCheck(w http.ResponseWriter, r *http
func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) {
iam, err := l.authRepo.GetIAM(r.Context())
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
return
}
@ -268,13 +351,13 @@ func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authR
orgIamPolicy, err := l.getOrgIamPolicy(r, resourceOwner)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
return
}
idpConfig, err := l.authRepo.GetIDPConfigByID(r.Context(), authReq.SelectedIDPConfigID)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, iam, orgIamPolicy, nil, nil, err)
return
}
@ -287,12 +370,12 @@ func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authR
user, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, linkingUser, idpConfig)
user, metadata, err = l.customExternalUserToLoginUserMapping(user, nil, authReq, idpConfig, metadata, resourceOwner)
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, iam, orgIamPolicy, nil, nil, err)
return
}
err = l.authRepo.AutoRegisterExternalUser(setContext(r.Context(), resourceOwner), user, externalIDP, memberRoles, authReq.ID, userAgentID, resourceOwner, metadata, domain.BrowserInfoFromRequest(r))
if err != nil {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, iam, orgIamPolicy, user, externalIDP, err)
return
}
authReq, err = l.authRepo.AuthRequestByID(r.Context(), authReq.ID, authReq.AgentID)

View File

@ -112,7 +112,7 @@ func (l *Login) jwtExtractionUserNotFound(w http.ResponseWriter, r *http.Request
err = nil
}
if !idpConfig.AutoRegister {
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
return
}
authReq, err = l.authRepo.AuthRequestByID(r.Context(), authReq.ID, authReq.AgentID)

View File

@ -294,7 +294,7 @@ func (l *Login) chooseNextStep(w http.ResponseWriter, r *http.Request, authReq *
case *domain.LinkUsersStep:
l.linkUsers(w, r, authReq, err)
case *domain.ExternalNotFoundOptionStep:
l.renderExternalNotFoundOption(w, r, authReq, err)
l.renderExternalNotFoundOption(w, r, authReq, nil, nil, nil, nil, err)
case *domain.ExternalLoginStep:
l.handleExternalLoginStep(w, r, authReq, step.SelectedIDPConfigID)
case *domain.GrantRequiredStep:

View File

@ -280,7 +280,7 @@ ExternalNotFoundOption:
Title: Externer Benutzer
Description: Externer Benutzer konnte nicht gefunden werden. Willst du deinen Benutzer mit einem bestehenden verlinken oder diesen als neuen Benutzer registrieren.
LinkButtonText: Verlinken
AutoRegisterButtonText: Automatisches registrieren
AutoRegisterButtonText: registrieren
TosAndPrivacyLabel: Allgemeine Geschäftsbedingungen und Datenschutz
TosConfirm: Ich akzeptiere die
TosLinkText: AGBs

View File

@ -281,7 +281,7 @@ ExternalNotFoundOption:
Title: External User
Description: External user not found. Do you want to link your user or auto register a new one.
LinkButtonText: Link
AutoRegisterButtonText: Auto register
AutoRegisterButtonText: register
TosAndPrivacyLabel: Terms and conditions
TosConfirm: I accept the
TosLinkText: TOS

View File

@ -281,7 +281,7 @@ ExternalNotFoundOption:
Title: Utente esterno
Description: Utente esterno non trovato. Vuoi collegare il tuo utente o registrarne uno nuovo automaticamente.
LinkButtonText: Link
AutoRegisterButtonText: Registra automaticamente
AutoRegisterButtonText: Registra
TosAndPrivacyLabel: Termini di servizio
TosConfirm: Accetto i
TosLinkText: Termini di servizio

View File

@ -12,8 +12,62 @@
{{ .CSRF }}
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
<input type="hidden" id="external-idp-config-id" name="external-idp-config-id" value="{{ .ExternalIDPID }}" />
<input type="hidden" id="external-idp-ext-user-id" name="external-idp-ext-user-id" value="{{ .ExternalIDPUserID }}" />
<input type="hidden" id="external-idp-display-name" name="external-idp-display-name" value="{{ .ExternalIDPUserDisplayName }}" />
<input type="hidden" id="external-email" name="external-email" value="{{ .ExternalEmail }}" />
<input type="hidden" id="external-email-verified" name="external-email-verified" value="{{ .ExternalEmailVerified }}" />
<input type="hidden" id="external-phone" name="external-phone" value="{{ .ExternalPhone }}" />
<input type="hidden" id="external-phone-verified" name="external-phone-verified" value="{{ .ExternalPhoneVerified }}" />
<div class="lgn-register">
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="firstname">{{t "ExternalRegistrationUserOverview.FirstnameLabel"}}</label>
<input class="lgn-input" type="text" id="firstname" name="firstname" autocomplete="given-name"
value="{{ .Firstname }}" autofocus required>
</div>
<div class="lgn-field">
<label class="lgn-label" for="lastname">{{t "ExternalRegistrationUserOverview.LastnameLabel"}}</label>
<input class="lgn-input" type="text" id="lastname" name="lastname" autocomplete="family-name"
value="{{ .Lastname }}" required>
</div>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="username">{{t "ExternalRegistrationUserOverview.UsernameLabel"}}</label>
<div class="lgn-suffix-wrapper">
<input class="lgn-input lgn-suffix-input" type="text" id="username" name="username"
value="{{ .Username }}" required>
{{if .DisplayLoginNameSuffix}}
<span id="default-login-suffix" lgnsuffix class="loginname-suffix">@{{.PrimaryDomain}}</span>
{{end}}
</div>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="email">{{t "ExternalRegistrationUserOverview.EmailLabel"}}</label>
<input class="lgn-input" type="text" id="email" name="email" autocomplete="email" value="{{ .Email }}" required>
</div>
<div class="lgn-field double">
<label class="lgn-label" for="phone">{{t "ExternalRegistrationUserOverview.PhoneLabel"}}</label>
<input class="lgn-input" type="text" id="phone" name="phone" autocomplete="tel" value="{{ .Phone }}">
</div>
<div class="double-col">
<div class="lgn-field">
<label class="lgn-label" for="languages">{{t "ExternalRegistrationUserOverview.LanguageLabel"}}</label>
<select id="languages" name="language">
<option value=""></option>
<option value="de" id="de" {{if (selectedLanguage "de")}} selected {{end}}>{{t "ExternalNotFoundOption.German"}}
</option>
<option value="en" id="en" {{if (selectedLanguage "en")}} selected {{end}}>{{t "ExternalNotFoundOption.English"}}
</option>
</select>
</div>
</div>
{{ if or .TOSLink .PrivacyLink }}
<div class="lgn-field">
<label class="lgn-label">{{t "ExternalNotFoundOption.TosAndPrivacyLabel"}}</label>