do not require password for external registration

This commit is contained in:
AJ ONeal 2018-10-06 21:21:37 +00:00
parent ee0fa3e58f
commit e64ff60c13
5 changed files with 58 additions and 22 deletions

View File

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

View File

@ -1165,6 +1165,8 @@ var Service struct {
EnableReverseProxyAuth bool EnableReverseProxyAuth bool
EnableReverseProxyAutoRegister bool EnableReverseProxyAutoRegister bool
EnableCaptcha bool EnableCaptcha bool
RequireExternalRegistrationCaptcha bool
RequireExternalRegistrationPassword bool
DefaultKeepEmailPrivate bool DefaultKeepEmailPrivate bool
DefaultAllowCreateOrganization bool DefaultAllowCreateOrganization bool
EnableTimetracking bool EnableTimetracking bool
@ -1190,6 +1192,8 @@ func newService() {
Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool() Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool() Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool() Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool()
Service.RequireExternalRegistrationCaptcha = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA").MustBool()
Service.RequireExternalRegistrationPassword = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_PASSWORD").MustBool()
Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool() Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true) Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true) Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true)

View File

@ -6,6 +6,8 @@
package user package user
import ( import (
"crypto/rand"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
@ -123,6 +125,7 @@ func SignIn(ctx *context.Context) {
ctx.Data["OAuth2Providers"] = oauth2Providers ctx.Data["OAuth2Providers"] = oauth2Providers
ctx.Data["Title"] = ctx.Tr("sign_in") ctx.Data["Title"] = ctx.Tr("sign_in")
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
ctx.Data["AllowPassword"] = true
ctx.Data["PageIsSignIn"] = true ctx.Data["PageIsSignIn"] = true
ctx.Data["PageIsLogin"] = true ctx.Data["PageIsLogin"] = true
@ -142,6 +145,7 @@ func SignInPost(ctx *context.Context, form auth.SignInForm) {
ctx.Data["OAuth2Providers"] = oauth2Providers ctx.Data["OAuth2Providers"] = oauth2Providers
ctx.Data["Title"] = ctx.Tr("sign_in") ctx.Data["Title"] = ctx.Tr("sign_in")
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
ctx.Data["AllowPassword"] = true
ctx.Data["PageIsSignIn"] = true ctx.Data["PageIsSignIn"] = true
ctx.Data["PageIsLogin"] = true ctx.Data["PageIsLogin"] = true
@ -641,7 +645,8 @@ func oAuth2UserLoginCallback(loginSource *models.LoginSource, request *http.Requ
func LinkAccount(ctx *context.Context) { func LinkAccount(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("link_account") ctx.Data["Title"] = ctx.Tr("link_account")
ctx.Data["LinkAccountMode"] = true ctx.Data["LinkAccountMode"] = true
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha ctx.Data["EnableCaptcha"] = setting.Service.RequireExternalRegistrationCaptcha //&& setting.Service.EnableCaptcha
ctx.Data["AllowPassword"] = setting.Service.RequireExternalRegistrationPassword && !setting.Service.AllowOnlyExternalRegistration
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
ctx.Data["ShowRegistrationButton"] = false ctx.Data["ShowRegistrationButton"] = false
@ -688,7 +693,9 @@ func LinkAccountPostSignIn(ctx *context.Context, signInForm auth.SignInForm) {
ctx.Data["Title"] = ctx.Tr("link_account") ctx.Data["Title"] = ctx.Tr("link_account")
ctx.Data["LinkAccountMode"] = true ctx.Data["LinkAccountMode"] = true
ctx.Data["LinkAccountModeSignIn"] = true ctx.Data["LinkAccountModeSignIn"] = true
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha ctx.Data["EnableCaptcha"] = setting.Service.RequireExternalRegistrationCaptcha //&& setting.Service.EnableCaptcha
// 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["DisableRegistration"] = setting.Service.DisableRegistration
ctx.Data["ShowRegistrationButton"] = false ctx.Data["ShowRegistrationButton"] = false
@ -754,7 +761,9 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au
ctx.Data["Title"] = ctx.Tr("link_account") ctx.Data["Title"] = ctx.Tr("link_account")
ctx.Data["LinkAccountMode"] = true ctx.Data["LinkAccountMode"] = true
ctx.Data["LinkAccountModeRegister"] = true ctx.Data["LinkAccountModeRegister"] = true
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha ctx.Data["EnableCaptcha"] = setting.Service.RequireExternalRegistrationCaptcha //&& setting.Service.EnableCaptcha
// 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["DisableRegistration"] = setting.Service.DisableRegistration
ctx.Data["ShowRegistrationButton"] = false ctx.Data["ShowRegistrationButton"] = false
@ -778,12 +787,25 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au
return return
} }
if setting.Service.EnableCaptcha && !cpt.VerifyReq(ctx.Req) { if setting.Service.RequireExternalRegistrationCaptcha && !cpt.VerifyReq(ctx.Req) {
ctx.Data["Err_Captcha"] = true ctx.Data["Err_Captcha"] = true
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplLinkAccount, &form) ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplLinkAccount, &form)
return 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 { if (len(strings.TrimSpace(form.Password)) > 0 || len(strings.TrimSpace(form.Retype)) > 0) && form.Password != form.Retype {
ctx.Data["Err_Password"] = true ctx.Data["Err_Password"] = true
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplLinkAccount, &form) ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplLinkAccount, &form)
@ -794,6 +816,7 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplLinkAccount, &form) ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplLinkAccount, &form)
return return
} }
}
loginSource, err := models.GetActiveOAuth2LoginSourceByName(gothUser.(goth.User).Provider) loginSource, err := models.GetActiveOAuth2LoginSourceByName(gothUser.(goth.User).Provider)
if err != nil { if err != nil {
@ -881,6 +904,8 @@ func SignUp(ctx *context.Context) {
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
ctx.Data["AllowPassword"] = true
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
ctx.HTML(200, tplSignUp) ctx.HTML(200, tplSignUp)
@ -894,6 +919,8 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
ctx.Data["AllowPassword"] = true
//Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true //Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true
if !setting.Service.ShowRegistrationButton { if !setting.Service.ShowRegistrationButton {
ctx.Error(403) ctx.Error(403)

View File

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

View File

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