Skip to content
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

Add support mCaptcha as captcha provider #20458

Merged
merged 32 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d56af8e
Add config stuff
Jul 22, 2022
46be033
Load mCaptcha on register page
Jul 22, 2022
62ea258
Code-style
Jul 22, 2022
75d079d
Implement backend verification
Jul 22, 2022
614ad0b
Add copyright text
Jul 22, 2022
df5f337
Merge branch 'main' into add-mcaptcha
Jul 22, 2022
5015c38
Don't use hardcoded instance
Jul 23, 2022
890c583
Merge branch 'main' into add-mcaptcha
Jul 23, 2022
46fd68f
Merge branch 'main' into add-mcaptcha
Jul 23, 2022
3c84682
Merge branch 'main' into add-mcaptcha
Jul 23, 2022
d7c5033
Nit pick
Jul 23, 2022
747c47b
Merge branch 'main' into add-mcaptcha
Jul 23, 2022
773f07e
Merge branch 'main' into add-mcaptcha
6543 Jul 24, 2022
06c6c95
Apply suggestions from code review
6543 Jul 26, 2022
9ed76bb
Merge branch 'main' into add-mcaptcha
6543 Jul 26, 2022
668a701
Merge branch 'master' into add-mcaptcha
6543 Jul 26, 2022
4c52706
fix lint
6543 Jul 26, 2022
08790c5
Merge branch 'main' into add-mcaptcha
Jul 26, 2022
0789b33
Hack mobile CSS together
Jul 26, 2022
d29138b
Merge branch 'main' into add-mcaptcha
6543 Jul 27, 2022
c866103
Update mCaptcha-glue
Jul 28, 2022
9208741
Merge branch 'main' into add-mcaptcha
Jul 28, 2022
f4e417b
Use `<span>` instead of `<label>`
Jul 29, 2022
4ea9eb4
Merge branch 'main' into add-mcaptcha
Jul 29, 2022
eccc205
Merge branch 'main' into add-mcaptcha
Aug 1, 2022
db8a806
Merge branch 'main' into add-mcaptcha
Aug 2, 2022
5f219f2
Merge branch 'main' into add-mcaptcha
Aug 3, 2022
559cf0d
Fix incorrect formatting
Aug 3, 2022
24d059b
Merge branch 'main' into add-mcaptcha
Aug 9, 2022
540ae07
Fix borked package-lock.json
Aug 9, 2022
3b1c008
Merge branch 'main' into add-mcaptcha
6543 Aug 9, 2022
a1d9503
Merge branch 'main' into add-mcaptcha
6543 Aug 10, 2022
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
13 changes: 10 additions & 3 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -696,9 +696,11 @@ ROUTER = console
;; Enable captcha validation for registration
;ENABLE_CAPTCHA = false
;;
;; Type of captcha you want to use. Options: image, recaptcha, hcaptcha
;; Type of captcha you want to use. Options: image, recaptcha, hcaptcha, mcaptcha.
;CAPTCHA_TYPE = image
;;
;; Change this to use recaptcha.net or other recaptcha service
;RECAPTCHA_URL = https://www.google.com/recaptcha/
;; Enable recaptcha to use Google's recaptcha service
;; Go to https://www.google.com/recaptcha/admin to sign up for a key
;RECAPTCHA_SECRET =
Expand All @@ -708,8 +710,13 @@ ROUTER = console
;HCAPTCHA_SECRET =
;HCAPTCHA_SITEKEY =
;;
;; Change this to use recaptcha.net or other recaptcha service
;RECAPTCHA_URL = https://www.google.com/recaptcha/
;; Change this to use demo.mcaptcha.org or your self-hosted mcaptcha.org instance.
;MCAPTCHA_URL = https://demo.mcaptcha.org
;;
;; Go to your configured mCaptcha instance and register a sitekey
;; and use your account's secret.
;MCAPTCHA_SECRET =
;MCAPTCHA_SITEKEY =
;;
;; Default value for KeepEmailPrivate
;; Each new user will get the value of this setting copied into their profile
Expand Down
7 changes: 5 additions & 2 deletions docs/content/doc/advanced/config-cheat-sheet.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -576,13 +576,16 @@ Certain queues have defaults that override the defaults set in `[queue]` (this o
provided email rather than a generated email.
- `ENABLE_CAPTCHA`: **false**: Enable this to use captcha validation for registration.
- `REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA`: **false**: Enable this to force captcha validation
even for External Accounts (i.e. GitHub, OpenID Connect, etc). You must `ENABLE_CAPTCHA` also.
- `CAPTCHA_TYPE`: **image**: \[image, recaptcha, hcaptcha\]
even for External Accounts (i.e. GitHub, OpenID Connect, etc). You also must enable `ENABLE_CAPTCHA`.
- `CAPTCHA_TYPE`: **image**: \[image, recaptcha, hcaptcha, mcaptcha\]
- `RECAPTCHA_SECRET`: **""**: Go to https://www.google.com/recaptcha/admin to get a secret for recaptcha.
- `RECAPTCHA_SITEKEY`: **""**: Go to https://www.google.com/recaptcha/admin to get a sitekey for recaptcha.
- `RECAPTCHA_URL`: **https://www.google.com/recaptcha/**: Set the recaptcha url - allows the use of recaptcha net.
- `HCAPTCHA_SECRET`: **""**: Sign up at https://www.hcaptcha.com/ to get a secret for hcaptcha.
- `HCAPTCHA_SITEKEY`: **""**: Sign up at https://www.hcaptcha.com/ to get a sitekey for hcaptcha.
- `MCAPTCHA_SECRET`: **""**: Go to your mCaptcha instance to get a secret for mCaptcha.
- `MCAPTCHA_SITEKEY`: **""**: Go to your mCaptcha instance to get a sitekey for mCaptcha.
- `MCAPTCHA_URL` **https://demo.mcaptcha.org/**: Set the mCaptcha URL.
- `DEFAULT_KEEP_EMAIL_PRIVATE`: **false**: By default set users to keep their email address private.
- `DEFAULT_ALLOW_CREATE_ORGANIZATION`: **true**: Allow new users to create organizations by default.
- `DEFAULT_USER_IS_RESTRICTED`: **false**: Give new users restricted permissions by default
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.18
require (
code.gitea.io/gitea-vet v0.2.2-0.20220122151748-48ebc902541b
code.gitea.io/sdk/gitea v0.15.1
codeberg.org/gusted/mcaptcha v0.0.0-20220722211632-55c1ffff1222
gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb
gitea.com/go-chi/cache v0.2.0
gitea.com/go-chi/captcha v0.0.0-20211013065431-70641c1a35d5
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ code.gitea.io/gitea-vet v0.2.2-0.20220122151748-48ebc902541b/go.mod h1:zcNbT/aJE
code.gitea.io/sdk/gitea v0.11.3/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
code.gitea.io/sdk/gitea v0.15.1 h1:WJreC7YYuxbn0UDaPuWIe/mtiNKTvLN8MLkaw71yx/M=
code.gitea.io/sdk/gitea v0.15.1/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
codeberg.org/gusted/mcaptcha v0.0.0-20220722211632-55c1ffff1222 h1:PCW4i+gnQ9XxF8V+nBch3KWdGe4MiP3xXUCA/z0jhHk=
codeberg.org/gusted/mcaptcha v0.0.0-20220722211632-55c1ffff1222/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw=
Expand Down
27 changes: 27 additions & 0 deletions modules/mcaptcha/mcaptcha.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package mcaptcha

import (
"context"
"fmt"

"code.gitea.io/gitea/modules/setting"

"codeberg.org/gusted/mcaptcha"
)

func Verify(ctx context.Context, token string) (bool, error) {
valid, err := mcaptcha.Verify(ctx, &mcaptcha.VerifyOpts{
InstanceURL: setting.Service.McaptchaURL,
Sitekey: setting.Service.McaptchaSitekey,
Secret: setting.Service.McaptchaSecret,
Token: token,
})
if err != nil {
return false, fmt.Errorf("wasn't able to verify mCaptcha: %v", err)
}
return valid, nil
}
6 changes: 6 additions & 0 deletions modules/setting/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ var Service = struct {
RecaptchaURL string
HcaptchaSecret string
HcaptchaSitekey string
McaptchaSecret string
McaptchaSitekey string
McaptchaURL string
DefaultKeepEmailPrivate bool
DefaultAllowCreateOrganization bool
DefaultUserIsRestricted bool
Expand Down Expand Up @@ -133,6 +136,9 @@ func newService() {
Service.RecaptchaURL = sec.Key("RECAPTCHA_URL").MustString("https://www.google.com/recaptcha/")
Service.HcaptchaSecret = sec.Key("HCAPTCHA_SECRET").MustString("")
Service.HcaptchaSitekey = sec.Key("HCAPTCHA_SITEKEY").MustString("")
Service.McaptchaURL = sec.Key("MCAPTCHA_URL").MustString("https://demo.mcaptcha.org/")
Service.McaptchaSecret = sec.Key("MCAPTCHA_SECRET").MustString("")
Service.McaptchaSitekey = sec.Key("MCAPTCHA_SITEKEY").MustString("")
Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
Service.DefaultUserIsRestricted = sec.Key("DEFAULT_USER_IS_RESTRICTED").MustBool(false)
Expand Down
1 change: 1 addition & 0 deletions modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const (
ImageCaptcha = "image"
ReCaptcha = "recaptcha"
HCaptcha = "hcaptcha"
MCaptcha = "mcaptcha"
)

// settings
Expand Down
63 changes: 63 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"dependencies": {
"@claviska/jquery-minicolors": "2.3.6",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-1",
Gusted marked this conversation as resolved.
Show resolved Hide resolved
"@primer/octicons": "17.3.0",
"add-asset-webpack-plugin": "2.0.1",
"css-loader": "6.7.1",
Expand Down
7 changes: 7 additions & 0 deletions routers/web/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/eventsource"
"code.gitea.io/gitea/modules/hcaptcha"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/mcaptcha"
"code.gitea.io/gitea/modules/password"
"code.gitea.io/gitea/modules/recaptcha"
"code.gitea.io/gitea/modules/session"
Expand Down Expand Up @@ -414,6 +415,8 @@ func SignUp(ctx *context.Context) {
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
ctx.Data["PageIsSignUp"] = true

// Show Disabled Registration message if DisableRegistration or AllowOnlyExternalRegistration options are true
Expand All @@ -435,6 +438,8 @@ func SignUpPost(ctx *context.Context) {
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
ctx.Data["PageIsSignUp"] = true

// Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true
Expand All @@ -458,6 +463,8 @@ func SignUpPost(ctx *context.Context) {
valid, err = recaptcha.Verify(ctx, form.GRecaptchaResponse)
case setting.HCaptcha:
valid, err = hcaptcha.Verify(ctx, form.HcaptchaResponse)
case setting.MCaptcha:
valid, err = mcaptcha.Verify(ctx, form.McaptchaResponse)
default:
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("Unknown Captcha Type: %s", setting.Service.CaptchaType))
return
Expand Down
9 changes: 9 additions & 0 deletions routers/web/auth/linkaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/hcaptcha"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/mcaptcha"
"code.gitea.io/gitea/modules/recaptcha"
"code.gitea.io/gitea/modules/session"
"code.gitea.io/gitea/modules/setting"
Expand All @@ -40,6 +41,8 @@ func LinkAccount(ctx *context.Context) {
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
ctx.Data["AllowOnlyInternalRegistration"] = setting.Service.AllowOnlyInternalRegistration
ctx.Data["ShowRegistrationButton"] = false
Expand Down Expand Up @@ -96,6 +99,8 @@ func LinkAccountPostSignIn(ctx *context.Context) {
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
ctx.Data["ShowRegistrationButton"] = false

Expand Down Expand Up @@ -195,6 +200,8 @@ func LinkAccountPostRegister(ctx *context.Context) {
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
ctx.Data["ShowRegistrationButton"] = false

Expand Down Expand Up @@ -233,6 +240,8 @@ func LinkAccountPostRegister(ctx *context.Context) {
valid, err = recaptcha.Verify(ctx, form.GRecaptchaResponse)
case setting.HCaptcha:
valid, err = hcaptcha.Verify(ctx, form.HcaptchaResponse)
case setting.MCaptcha:
valid, err = mcaptcha.Verify(ctx, form.McaptchaResponse)
default:
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("Unknown Captcha Type: %s", setting.Service.CaptchaType))
return
Expand Down
11 changes: 11 additions & 0 deletions routers/web/auth/openid.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/hcaptcha"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/mcaptcha"
"code.gitea.io/gitea/modules/recaptcha"
"code.gitea.io/gitea/modules/session"
"code.gitea.io/gitea/modules/setting"
Expand Down Expand Up @@ -341,6 +342,8 @@ func RegisterOpenID(ctx *context.Context) {
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
ctx.Data["OpenID"] = oid
userName, _ := ctx.Session.Get("openid_determined_username").(string)
if userName != "" {
Expand Down Expand Up @@ -372,6 +375,8 @@ func RegisterOpenIDPost(ctx *context.Context) {
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
ctx.Data["OpenID"] = oid

if setting.Service.AllowOnlyInternalRegistration {
Expand All @@ -397,6 +402,12 @@ func RegisterOpenIDPost(ctx *context.Context) {
return
}
valid, err = hcaptcha.Verify(ctx, form.HcaptchaResponse)
case setting.MCaptcha:
if err := ctx.Req.ParseForm(); err != nil {
ctx.ServerError("", err)
return
}
valid, err = mcaptcha.Verify(ctx, form.McaptchaResponse)
default:
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("Unknown Captcha Type: %s", setting.Service.CaptchaType))
return
Expand Down
1 change: 1 addition & 0 deletions services/forms/user_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ type RegisterForm struct {
Retype string
GRecaptchaResponse string `form:"g-recaptcha-response"`
HcaptchaResponse string `form:"h-captcha-response"`
McaptchaResponse string `form:"m-captcha-response"`
}

// Validate validates the fields
Expand Down
1 change: 1 addition & 0 deletions services/forms/user_form_auth_openid.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type SignUpOpenIDForm struct {
Email string `binding:"Required;Email;MaxSize(254)"`
GRecaptchaResponse string `form:"g-recaptcha-response"`
HcaptchaResponse string `form:"h-captcha-response"`
McaptchaResponse string `form:"m-captcha-response"`
}

// Validate validates the fields
Expand Down
8 changes: 8 additions & 0 deletions templates/user/auth/signup_inner.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@
<div class="h-captcha" data-sitekey="{{ .HcaptchaSitekey }}"></div>
</div>
{{end}}
{{if and .EnableCaptcha (eq .CaptchaType "mcaptcha")}}
<div class="inline field required df ac">
<label></label>
<div class="border-secondary" id="mcaptcha__widget-container" style="width: 304px; height: 78px"></div>
Gusted marked this conversation as resolved.
Show resolved Hide resolved
<div class="m-captcha" data-sitekey="{{ .McaptchaSitekey }}" data-instance-url="{{ .McaptchaURL }}"></div>
</div>
{{end}}


<div class="inline field">
<label></label>
Expand Down
5 changes: 5 additions & 0 deletions templates/user/auth/signup_openid_register.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
<div class="h-captcha" data-sitekey="{{ .HcaptchaSitekey }}"></div>
</div>
{{end}}
{{if and .EnableCaptcha (eq .CaptchaType "mcaptcha")}}
<div class="inline field required">
<div class="m-captcha" data-sitekey="{{ .McaptchaSitekey }}" data-instance-url="{{ .McaptchaURL }}"></div>
</div>
{{end}}
<div class="inline field">
<label for="openid">OpenID URI</label>
<input id="openid" value="{{ .OpenID }}" readonly>
Expand Down
16 changes: 16 additions & 0 deletions web_src/js/features/mcaptcha.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export async function initMcaptcha() {
const mCaptchaEl = document.querySelector('.m-captcha');
if (!mCaptchaEl) return;

const {default: mCaptcha} = await import(/* webpackChunkName: "mcaptcha-vanilla-glue" */'@mcaptcha/vanilla-glue');
mCaptcha.INPUT_NAME = 'm-captcha-response';
const siteKey = mCaptchaEl.getAttribute('data-sitekey');
const instanceURL = mCaptchaEl.getAttribute('data-instance-url');

mCaptcha.default({
siteKey: {
instanceUrl: new URL(instanceURL),
key: siteKey,
}
});
}
Loading