make password and captcha optional for external registration

This commit is contained in:
AJ ONeal 2018-10-06 21:21:37 +00:00
parent 455de4e6b5
commit 2dd4a9b487
5 changed files with 59 additions and 23 deletions

View File

@ -74,7 +74,7 @@ func (f *InstallForm) Validate(ctx *macaron.Context, errs binding.Errors) bindin
type RegisterForm struct {
UserName string `binding:"Required;AlphaDashDot;MaxSize(35)"`
Email string `binding:"Required;Email;MaxSize(254)"`
Password string `binding:"Required;MaxSize(255)"`
Password string `binding:"MaxSize(255)"`
Retype string
GRecaptchaResponse string `form:"g-recaptcha-response"`
}
@ -99,6 +99,7 @@ func (f *MustChangePasswordForm) Validate(ctx *macaron.Context, errs binding.Err
// SignInForm form for signing in with user/password
type SignInForm struct {
UserName string `binding:"Required;MaxSize(254)"`
// TODO remove required from password for SecondFactorAuthentication
Password string `binding:"Required;MaxSize(255)"`
Remember bool
}

View File

@ -1208,6 +1208,8 @@ var Service struct {
EnableReverseProxyAuth bool
EnableReverseProxyAutoRegister bool
EnableCaptcha bool
RequireExternalRegistrationCaptcha bool
RequireExternalRegistrationPassword bool
CaptchaType string
RecaptchaSecret string
RecaptchaSitekey string
@ -1237,6 +1239,8 @@ func newService() {
Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false)
Service.RequireExternalRegistrationCaptcha = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA").MustBool()
Service.RequireExternalRegistrationPassword = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_PASSWORD").MustBool()
Service.CaptchaType = sec.Key("CAPTCHA_TYPE").MustString(ImageCaptcha)
Service.RecaptchaSecret = sec.Key("RECAPTCHA_SECRET").MustString("")
Service.RecaptchaSitekey = sec.Key("RECAPTCHA_SITEKEY").MustString("")

View File

@ -6,6 +6,8 @@
package user
import (
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"net/http"
@ -126,6 +128,7 @@ func SignIn(ctx *context.Context) {
ctx.Data["OAuth2Providers"] = oauth2Providers
ctx.Data["Title"] = ctx.Tr("sign_in")
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
ctx.Data["AllowPassword"] = true
ctx.Data["PageIsSignIn"] = true
ctx.Data["PageIsLogin"] = true
@ -145,6 +148,7 @@ func SignInPost(ctx *context.Context, form auth.SignInForm) {
ctx.Data["OAuth2Providers"] = oauth2Providers
ctx.Data["Title"] = ctx.Tr("sign_in")
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
ctx.Data["AllowPassword"] = true
ctx.Data["PageIsSignIn"] = true
ctx.Data["PageIsLogin"] = true
@ -648,9 +652,10 @@ func oAuth2UserLoginCallback(loginSource *models.LoginSource, request *http.Requ
func LinkAccount(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("link_account")
ctx.Data["LinkAccountMode"] = true
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
ctx.Data["EnableCaptcha"] = setting.Service.RequireExternalRegistrationCaptcha
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["AllowPassword"] = setting.Service.RequireExternalRegistrationPassword && !setting.Service.AllowOnlyExternalRegistration
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
ctx.Data["ShowRegistrationButton"] = false
@ -697,9 +702,11 @@ func LinkAccountPostSignIn(ctx *context.Context, signInForm auth.SignInForm) {
ctx.Data["Title"] = ctx.Tr("link_account")
ctx.Data["LinkAccountMode"] = true
ctx.Data["LinkAccountModeSignIn"] = true
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
ctx.Data["EnableCaptcha"] = setting.Service.RequireExternalRegistrationCaptcha
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
// Only allow a password if local login is enabled (TODO) except if SecondFactorAuthentication is enabled
ctx.Data["AllowPassword"] = !setting.Service.AllowOnlyExternalRegistration
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
ctx.Data["ShowRegistrationButton"] = false
@ -765,9 +772,11 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au
ctx.Data["Title"] = ctx.Tr("link_account")
ctx.Data["LinkAccountMode"] = true
ctx.Data["LinkAccountModeRegister"] = true
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
ctx.Data["EnableCaptcha"] = setting.Service.RequireExternalRegistrationCaptcha
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
// TODO implement the same for local accounts, once email-based Second Factor Auth is available
ctx.Data["AllowPassword"] = setting.Service.RequireExternalRegistrationPassword && !setting.Service.AllowOnlyExternalRegistration
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
ctx.Data["ShowRegistrationButton"] = false
@ -791,13 +800,13 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au
return
}
if setting.Service.EnableCaptcha && setting.Service.CaptchaType == setting.ImageCaptcha && !cpt.VerifyReq(ctx.Req) {
if setting.Service.RequireExternalRegistrationCaptcha && setting.Service.CaptchaType == setting.ImageCaptcha && !cpt.VerifyReq(ctx.Req) {
ctx.Data["Err_Captcha"] = true
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplLinkAccount, &form)
return
}
if setting.Service.EnableCaptcha && setting.Service.CaptchaType == setting.ReCaptcha {
if setting.Service.RequireExternalRegistrationCaptcha && setting.Service.CaptchaType == setting.ReCaptcha {
valid, _ := recaptcha.Verify(form.GRecaptchaResponse)
if !valid {
ctx.Data["Err_Captcha"] = true
@ -806,15 +815,29 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au
}
}
if (len(strings.TrimSpace(form.Password)) > 0 || len(strings.TrimSpace(form.Retype)) > 0) && form.Password != form.Retype {
ctx.Data["Err_Password"] = true
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplLinkAccount, &form)
return
}
if len(strings.TrimSpace(form.Password)) > 0 && len(form.Password) < setting.MinPasswordLength {
ctx.Data["Err_Password"] = true
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplLinkAccount, &form)
return
if setting.Service.AllowOnlyExternalRegistration || !setting.Service.RequireExternalRegistrationPassword {
// Generating a random password a stop-gap shim to get around the password requirement
// Eventually the database should be changed to indicate "Second Factor" enabled accounts
// that do not introduce the security vulnerabilities of a password
bytes := make([]byte, 16)
_, err := rand.Read(bytes)
if nil != err {
ctx.ServerError("CreateUser", err)
return
}
form.Password = hex.EncodeToString(bytes)
} else {
// TODO Retype password should move to frontend JavaScript, not be required by server
if (len(strings.TrimSpace(form.Password)) > 0 || len(strings.TrimSpace(form.Retype)) > 0) && form.Password != form.Retype {
ctx.Data["Err_Password"] = true
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplLinkAccount, &form)
return
}
if len(strings.TrimSpace(form.Password)) > 0 && len(form.Password) < setting.MinPasswordLength {
ctx.Data["Err_Password"] = true
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplLinkAccount, &form)
return
}
}
loginSource, err := models.GetActiveOAuth2LoginSourceByName(gothUser.(goth.User).Provider)
@ -906,6 +929,8 @@ func SignUp(ctx *context.Context) {
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["AllowPassword"] = true
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
ctx.HTML(200, tplSignUp)
@ -922,6 +947,8 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["AllowPassword"] = true
//Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true
if !setting.Service.ShowRegistrationButton {
ctx.Error(403)

View File

@ -15,10 +15,12 @@
<label for="user_name">{{.i18n.Tr "home.uname_holder"}}</label>
<input id="user_name" name="user_name" value="{{.user_name}}" autofocus required>
</div>
{{if .AllowPassword}}
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
<label for="password">{{.i18n.Tr "password"}}</label>
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
</div>
{{end}}
{{if not .LinkAccountMode}}
<div class="inline field">
<label></label>

View File

@ -25,14 +25,16 @@
<label for="email">{{.i18n.Tr "email"}}</label>
<input id="email" name="email" type="email" value="{{.email}}" required>
</div>
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
<label for="password">{{.i18n.Tr "password"}}</label>
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
</div>
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
<label for="retype">{{.i18n.Tr "re_type"}}</label>
<input id="retype" name="retype" type="password" value="{{.retype}}" autocomplete="off" required>
</div>
{{if .AllowPassword}}
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
<label for="password">{{.i18n.Tr "password"}}</label>
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
</div>
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
<label for="retype">{{.i18n.Tr "re_type"}}</label>
<input id="retype" name="retype" type="password" value="{{.retype}}" autocomplete="off" required>
</div>
{{end}}
{{if and .EnableCaptcha (eq .CaptchaType "image")}}
<div class="inline field">
<label></label>