From 64971f88e65934fe51f3b8a598aaee5aefecd634 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 6 Oct 2018 21:21:37 +0000 Subject: [PATCH] make password and captcha optional for external registration --- modules/auth/user_form.go | 3 +- modules/setting/setting.go | 4 ++ routers/user/auth.go | 55 ++++++++++++++++++++------- templates/user/auth/signin_inner.tmpl | 2 + templates/user/auth/signup_inner.tmpl | 18 +++++---- 5 files changed, 59 insertions(+), 23 deletions(-) diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index 43ddb29c7..e6f3c22dd 100644 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -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 } diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 882f56541..08f01bef7 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -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("") diff --git a/routers/user/auth.go b/routers/user/auth.go index a4a0ee3e6..35cc8ac0c 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -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 @@ -675,9 +680,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 @@ -743,9 +750,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 @@ -769,13 +778,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 @@ -784,15 +793,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) @@ -884,6 +907,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) @@ -900,6 +925,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) diff --git a/templates/user/auth/signin_inner.tmpl b/templates/user/auth/signin_inner.tmpl index 019bda570..136251cbe 100644 --- a/templates/user/auth/signin_inner.tmpl +++ b/templates/user/auth/signin_inner.tmpl @@ -11,10 +11,12 @@ + {{if .AllowPassword}}
+ {{end}} {{if not .LinkAccountMode}}
diff --git a/templates/user/auth/signup_inner.tmpl b/templates/user/auth/signup_inner.tmpl index cd969276b..6024892c4 100644 --- a/templates/user/auth/signup_inner.tmpl +++ b/templates/user/auth/signup_inner.tmpl @@ -21,14 +21,16 @@
-
- - -
-
- - -
+ {{if .AllowPassword}} +
+ + +
+
+ + +
+ {{end}} {{if and .EnableCaptcha (eq .CaptchaType "image")}}