Skip to content

Allow blocking some email domains from registering an account #14667

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,8 @@ REGISTER_MANUAL_CONFIRM = false
; List of domain names that are allowed to be used to register on a Gitea instance
; gitea.io,example.com
EMAIL_DOMAIN_WHITELIST =
; Comma-separated list of domain names that are not allowed to be used to register on a Gitea instance
EMAIL_DOMAIN_BLOCKLIST =
; Disallow registration, only allow admins to create accounts.
DISABLE_REGISTRATION = false
; Allow registration only using third-party services, it works only when DISABLE_REGISTRATION is false
Expand Down
1 change: 1 addition & 0 deletions docs/content/doc/advanced/config-cheat-sheet.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ relation to port exhaustion.
- `DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME`: **true**: Only allow users with write permissions to track time.
- `EMAIL_DOMAIN_WHITELIST`: **\<empty\>**: If non-empty, list of domain names that can only be used to register
on this instance.
- `EMAIL_DOMAIN_BLOCKLIST`: **\<empty\>**: If non-empty, list of domain names that cannot be used to register on this instance
- `SHOW_REGISTRATION_BUTTON`: **! DISABLE\_REGISTRATION**: Show Registration Button
- `SHOW_MILESTONES_DASHBOARD_PAGE`: **true** Enable this to show the milestones dashboard page - a view of all the user's milestones
- `AUTO_WATCH_NEW_REPOS`: **true**: Enable this to let all organisation users watch new repos when they are created
Expand Down
11 changes: 6 additions & 5 deletions docs/content/doc/help/faq.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,14 @@ For more information, refer to Gitea's [API docs]({{< relref "doc/developers/api

There are multiple things you can combine to prevent spammers.

1. By only whitelisting certain domains with OpenID (see below)
2. Setting `ENABLE_CAPTCHA` to `true` in your `app.ini` and properly configuring `RECAPTCHA_SECRET` and `RECAPTCHA_SITEKEY`
3. Settings `DISABLE_REGISTRATION` to `true` and creating new users via the [CLI]({{< relref "doc/usage/command-line.en-us.md" >}}), [API]({{< relref "doc/developers/api-usage.en-us.md" >}}), or Gitea's Admin UI
1. By whitelisting or blocklisting certain email domains
2. By only whitelisting certain domains with OpenID (see below)
3. Setting `ENABLE_CAPTCHA` to `true` in your `app.ini` and properly configuring `RECAPTCHA_SECRET` and `RECAPTCHA_SITEKEY`
4. Settings `DISABLE_REGISTRATION` to `true` and creating new users via the [CLI]({{< relref "doc/usage/command-line.en-us.md" >}}), [API]({{< relref "doc/developers/api-usage.en-us.md" >}}), or Gitea's Admin UI

### Only allow certain email domains
### Only allow/block certain email domains

You can configure `EMAIL_DOMAIN_WHITELIST` in your app.ini under `[service]`
You can configure `EMAIL_DOMAIN_WHITELIST` or `EMAIL_DOMAIN_BLOCKLIST` in your app.ini under `[service]`

### Only allow/block certain OpenID providers

Expand Down
31 changes: 21 additions & 10 deletions modules/forms/user_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,23 +95,21 @@ func (f *RegisterForm) Validate(req *http.Request, errs binding.Errors) binding.
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
}

// IsEmailDomainWhitelisted validates that the email address
// provided by the user matches what has been configured .
// If the domain whitelist from the config is empty, it marks the
// email as whitelisted
func (f RegisterForm) IsEmailDomainWhitelisted() bool {
if len(setting.Service.EmailDomainWhitelist) == 0 {
return true
// IsEmailDomainListed checks whether the domain of an email address
// matches a list of domains
func IsEmailDomainListed(list []string, email string) bool {
if len(list) == 0 {
return false
}

n := strings.LastIndex(f.Email, "@")
n := strings.LastIndex(email, "@")
if n <= 0 {
return false
}

domain := strings.ToLower(f.Email[n+1:])
domain := strings.ToLower(email[n+1:])

for _, v := range setting.Service.EmailDomainWhitelist {
for _, v := range list {
if strings.ToLower(v) == domain {
return true
}
Expand All @@ -120,6 +118,19 @@ func (f RegisterForm) IsEmailDomainWhitelisted() bool {
return false
}

// IsEmailDomainAllowed validates that the email address
// provided by the user matches what has been configured .
// The email is marked as allowed if it matches any of the
// domains in the whitelist or if it doesn't match any of
// domains in the blocklist, if any such list is not empty.
func (f RegisterForm) IsEmailDomainAllowed() bool {
if len(setting.Service.EmailDomainWhitelist) == 0 {
return !IsEmailDomainListed(setting.Service.EmailDomainBlocklist, f.Email)
}

return IsEmailDomainListed(setting.Service.EmailDomainWhitelist, f.Email)
}

// MustChangePasswordForm form for updating your password after account creation
// by an admin
type MustChangePasswordForm struct {
Expand Down
34 changes: 28 additions & 6 deletions modules/forms/user_form_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ import (
"github.com/stretchr/testify/assert"
)

func TestRegisterForm_IsDomainWhiteList_Empty(t *testing.T) {
func TestRegisterForm_IsDomainAllowed_Empty(t *testing.T) {
_ = setting.Service

setting.Service.EmailDomainWhitelist = []string{}

form := RegisterForm{}

assert.True(t, form.IsEmailDomainWhitelisted())
assert.True(t, form.IsEmailDomainAllowed())
}

func TestRegisterForm_IsDomainWhiteList_InvalidEmail(t *testing.T) {
func TestRegisterForm_IsDomainAllowed_InvalidEmail(t *testing.T) {
_ = setting.Service

setting.Service.EmailDomainWhitelist = []string{"gitea.io"}
Expand All @@ -37,11 +37,11 @@ func TestRegisterForm_IsDomainWhiteList_InvalidEmail(t *testing.T) {
for _, v := range tt {
form := RegisterForm{Email: v.email}

assert.False(t, form.IsEmailDomainWhitelisted())
assert.False(t, form.IsEmailDomainAllowed())
}
}

func TestRegisterForm_IsDomainWhiteList_ValidEmail(t *testing.T) {
func TestRegisterForm_IsDomainAllowed_WhitelistedEmail(t *testing.T) {
_ = setting.Service

setting.Service.EmailDomainWhitelist = []string{"gitea.io"}
Expand All @@ -59,6 +59,28 @@ func TestRegisterForm_IsDomainWhiteList_ValidEmail(t *testing.T) {
for _, v := range tt {
form := RegisterForm{Email: v.email}

assert.Equal(t, v.valid, form.IsEmailDomainWhitelisted())
assert.Equal(t, v.valid, form.IsEmailDomainAllowed())
}
}

func TestRegisterForm_IsDomainAllowed_BlocklistedEmail(t *testing.T) {
_ = setting.Service

setting.Service.EmailDomainWhitelist = []string{}
setting.Service.EmailDomainBlocklist = []string{"gitea.io"}

tt := []struct {
email string
valid bool
}{
{"security@gitea.io", false},
{"security@gitea.example", true},
{"hdudhdd", true},
}

for _, v := range tt {
form := RegisterForm{Email: v.email}

assert.Equal(t, v.valid, form.IsEmailDomainAllowed())
}
}
2 changes: 2 additions & 0 deletions modules/setting/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var Service struct {
RegisterEmailConfirm bool
RegisterManualConfirm bool
EmailDomainWhitelist []string
EmailDomainBlocklist []string
DisableRegistration bool
AllowOnlyExternalRegistration bool
ShowRegistrationButton bool
Expand Down Expand Up @@ -72,6 +73,7 @@ func newService() {
Service.RegisterManualConfirm = false
}
Service.EmailDomainWhitelist = sec.Key("EMAIL_DOMAIN_WHITELIST").Strings(",")
Service.EmailDomainBlocklist = sec.Key("EMAIL_DOMAIN_BLOCKLIST").Strings(",")
Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration))
Service.ShowMilestonesDashboardPage = sec.Key("SHOW_MILESTONES_DASHBOARD_PAGE").MustBool(true)
Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool()
Expand Down
2 changes: 1 addition & 1 deletion routers/user/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -1129,7 +1129,7 @@ func SignUpPost(ctx *context.Context) {
}
}

if !form.IsEmailDomainWhitelisted() {
if !form.IsEmailDomainAllowed() {
ctx.RenderWithErr(ctx.Tr("auth.email_domain_blacklisted"), tplSignUp, &form)
return
}
Expand Down