Skip to content

Commit 6a5649d

Browse files
author
AJ ONeal
committed
Make captcha and password optional for external accounts
1 parent 46373e7 commit 6a5649d

File tree

5 files changed

+59
-21
lines changed

5 files changed

+59
-21
lines changed

modules/auth/user_form.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func (f *InstallForm) Validate(ctx *macaron.Context, errs binding.Errors) bindin
7878
type RegisterForm struct {
7979
UserName string `binding:"Required;AlphaDashDot;MaxSize(40)"`
8080
Email string `binding:"Required;Email;MaxSize(254)"`
81-
Password string `binding:"Required;MaxSize(255)"`
81+
Password string `binding:"MaxSize(255)"`
8282
Retype string
8383
GRecaptchaResponse string `form:"g-recaptcha-response"`
8484
}
@@ -128,6 +128,7 @@ func (f *MustChangePasswordForm) Validate(ctx *macaron.Context, errs binding.Err
128128
// SignInForm form for signing in with user/password
129129
type SignInForm struct {
130130
UserName string `binding:"Required;MaxSize(254)"`
131+
// TODO remove required from password for SecondFactorAuthentication
131132
Password string `binding:"Required;MaxSize(255)"`
132133
Remember bool
133134
}

modules/setting/service.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ var Service struct {
2727
EnableReverseProxyAutoRegister bool
2828
EnableReverseProxyEmail bool
2929
EnableCaptcha bool
30+
RequireExternalRegistrationCaptcha bool
31+
RequireExternalRegistrationPassword bool
3032
CaptchaType string
3133
RecaptchaSecret string
3234
RecaptchaSitekey string
@@ -61,6 +63,8 @@ func newService() {
6163
Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
6264
Service.EnableReverseProxyEmail = sec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool()
6365
Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false)
66+
Service.RequireExternalRegistrationCaptcha = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA").MustBool()
67+
Service.RequireExternalRegistrationPassword = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_PASSWORD").MustBool()
6468
Service.CaptchaType = sec.Key("CAPTCHA_TYPE").MustString(ImageCaptcha)
6569
Service.RecaptchaSecret = sec.Key("RECAPTCHA_SECRET").MustString("")
6670
Service.RecaptchaSitekey = sec.Key("RECAPTCHA_SITEKEY").MustString("")

routers/user/auth.go

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
package user
77

88
import (
9+
"crypto/rand"
10+
"encoding/hex"
911
"errors"
1012
"fmt"
1113
"net/http"
@@ -116,6 +118,7 @@ func SignIn(ctx *context.Context) {
116118
return
117119
}
118120

121+
ctx.Data["AllowPassword"] = true
119122
orderedOAuth2Names, oauth2Providers, err := models.GetActiveOAuth2Providers()
120123
if err != nil {
121124
ctx.ServerError("UserSignIn", err)
@@ -135,6 +138,7 @@ func SignIn(ctx *context.Context) {
135138
func SignInPost(ctx *context.Context, form auth.SignInForm) {
136139
ctx.Data["Title"] = ctx.Tr("sign_in")
137140

141+
ctx.Data["AllowPassword"] = true
138142
orderedOAuth2Names, oauth2Providers, err := models.GetActiveOAuth2Providers()
139143
if err != nil {
140144
ctx.ServerError("UserSignIn", err)
@@ -658,9 +662,10 @@ func oAuth2UserLoginCallback(loginSource *models.LoginSource, request *http.Requ
658662

659663
// LinkAccount shows the page where the user can decide to login or create a new account
660664
func LinkAccount(ctx *context.Context) {
665+
ctx.Data["AllowPassword"] = setting.Service.RequireExternalRegistrationPassword && !setting.Service.AllowOnlyExternalRegistration
661666
ctx.Data["Title"] = ctx.Tr("link_account")
662667
ctx.Data["LinkAccountMode"] = true
663-
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
668+
ctx.Data["EnableCaptcha"] = setting.Service.RequireExternalRegistrationCaptcha
664669
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
665670
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
666671
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
@@ -707,10 +712,11 @@ func LinkAccount(ctx *context.Context) {
707712

708713
// LinkAccountPostSignIn handle the coupling of external account with another account using signIn
709714
func LinkAccountPostSignIn(ctx *context.Context, signInForm auth.SignInForm) {
715+
ctx.Data["AllowPassword"] = !setting.Service.AllowOnlyExternalRegistration
710716
ctx.Data["Title"] = ctx.Tr("link_account")
711717
ctx.Data["LinkAccountMode"] = true
712718
ctx.Data["LinkAccountModeSignIn"] = true
713-
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
719+
ctx.Data["EnableCaptcha"] = setting.Service.RequireExternalRegistrationCaptcha
714720
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
715721
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
716722
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
@@ -776,10 +782,13 @@ func LinkAccountPostSignIn(ctx *context.Context, signInForm auth.SignInForm) {
776782

777783
// LinkAccountPostRegister handle the creation of a new account for an external account using signUp
778784
func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) {
785+
// TODO Make insecure passwords optional for local accounts also,
786+
// once email-based Second-Factor Auth is available
787+
ctx.Data["AllowPassword"] = setting.Service.RequireExternalRegistrationPassword && !setting.Service.AllowOnlyExternalRegistration
779788
ctx.Data["Title"] = ctx.Tr("link_account")
780789
ctx.Data["LinkAccountMode"] = true
781790
ctx.Data["LinkAccountModeRegister"] = true
782-
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
791+
ctx.Data["EnableCaptcha"] = setting.Service.RequireExternalRegistrationCaptcha
783792
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
784793
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
785794
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
@@ -821,15 +830,30 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au
821830
}
822831
}
823832

824-
if (len(strings.TrimSpace(form.Password)) > 0 || len(strings.TrimSpace(form.Retype)) > 0) && form.Password != form.Retype {
825-
ctx.Data["Err_Password"] = true
826-
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplLinkAccount, &form)
827-
return
828-
}
829-
if len(strings.TrimSpace(form.Password)) > 0 && len(form.Password) < setting.MinPasswordLength {
830-
ctx.Data["Err_Password"] = true
831-
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplLinkAccount, &form)
832-
return
833+
if setting.Service.AllowOnlyExternalRegistration || !setting.Service.RequireExternalRegistrationPassword {
834+
// Generating a random password a stop-gap shim to get around the password requirement.
835+
// Eventually the database should be changed to indicate "Second Factor"-enabled accounts
836+
// (accounts that do not introduce the security vulnerabilities of a password).
837+
// If a user decides to circumvent second-factor security, and purposefully create a password,
838+
// they can still do so using the "Recover Account" option.
839+
bytes := make([]byte, 16)
840+
_, err := rand.Read(bytes)
841+
if nil != err {
842+
ctx.ServerError("CreateUser", err)
843+
return
844+
}
845+
form.Password = hex.EncodeToString(bytes)
846+
} else {
847+
if (len(strings.TrimSpace(form.Password)) > 0 || len(strings.TrimSpace(form.Retype)) > 0) && form.Password != form.Retype {
848+
ctx.Data["Err_Password"] = true
849+
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplLinkAccount, &form)
850+
return
851+
}
852+
if len(strings.TrimSpace(form.Password)) > 0 && len(form.Password) < setting.MinPasswordLength {
853+
ctx.Data["Err_Password"] = true
854+
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplLinkAccount, &form)
855+
return
856+
}
833857
}
834858

835859
loginSource, err := models.GetActiveOAuth2LoginSourceByName(gothUser.(goth.User).Provider)
@@ -916,6 +940,8 @@ func SignOut(ctx *context.Context) {
916940

917941
// SignUp render the register page
918942
func SignUp(ctx *context.Context) {
943+
ctx.Data["AllowPassword"] = true
944+
919945
ctx.Data["Title"] = ctx.Tr("sign_up")
920946

921947
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
@@ -932,6 +958,8 @@ func SignUp(ctx *context.Context) {
932958

933959
// SignUpPost response for sign up information submission
934960
func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) {
961+
ctx.Data["AllowPassword"] = true
962+
935963
ctx.Data["Title"] = ctx.Tr("sign_up")
936964

937965
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"

templates/user/auth/signin_inner.tmpl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
<label for="user_name">{{.i18n.Tr "home.uname_holder"}}</label>
1616
<input id="user_name" name="user_name" value="{{.user_name}}" autofocus required>
1717
</div>
18+
{{if .AllowPassword}}
1819
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
1920
<label for="password">{{.i18n.Tr "password"}}</label>
2021
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
2122
</div>
23+
{{end}}
2224
{{if not .LinkAccountMode}}
2325
<div class="inline field">
2426
<label></label>

templates/user/auth/signup_inner.tmpl

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@
2525
<label for="email">{{.i18n.Tr "email"}}</label>
2626
<input id="email" name="email" type="email" value="{{.email}}" required>
2727
</div>
28-
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
29-
<label for="password">{{.i18n.Tr "password"}}</label>
30-
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
31-
</div>
32-
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
33-
<label for="retype">{{.i18n.Tr "re_type"}}</label>
34-
<input id="retype" name="retype" type="password" value="{{.retype}}" autocomplete="off" required>
35-
</div>
28+
29+
{{if .AllowPassword}}
30+
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
31+
<label for="password">{{.i18n.Tr "password"}}</label>
32+
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" required>
33+
</div>
34+
<div class="required inline field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeRegister))}}error{{end}}">
35+
<label for="retype">{{.i18n.Tr "re_type"}}</label>
36+
<input id="retype" name="retype" type="password" value="{{.retype}}" autocomplete="off" required>
37+
</div>
38+
{{end}}
3639
{{if and .EnableCaptcha (eq .CaptchaType "image")}}
3740
<div class="inline field">
3841
<label></label>

0 commit comments

Comments
 (0)