mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-27 07:28:27 +00:00
Add hcaptcha support besides Google ReCaptcha (#2834)
### Pull Request Checklist This PR add support for hcaptcha.com as an alternative to Google ReCaptcha. It also makes possible for user to customize ReCaptcha URL when needed. (Such as use recaptcha.net instead of www.google.com) This feature needs manual test cuz it involves 3rd party _captcha_. Signed-off-by: `Simon Ding <dxl@plotbridge.com>` Co-authored-by: dxl <dxl@plotbridge.com>
This commit is contained in:
parent
f6035822e7
commit
0782011f54
5 changed files with 45 additions and 11 deletions
|
@ -31,8 +31,7 @@ const recaptchaTemplate = `
|
||||||
<title>Authentication</title>
|
<title>Authentication</title>
|
||||||
<meta name='viewport' content='width=device-width, initial-scale=1,
|
<meta name='viewport' content='width=device-width, initial-scale=1,
|
||||||
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
|
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
|
||||||
<script src="https://www.google.com/recaptcha/api.js"
|
<script src="{{.apiJsUrl}}" async defer></script>
|
||||||
async defer></script>
|
|
||||||
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
|
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function captchaDone() {
|
function captchaDone() {
|
||||||
|
@ -51,8 +50,8 @@ function captchaDone() {
|
||||||
Please verify that you're not a robot.
|
Please verify that you're not a robot.
|
||||||
</p>
|
</p>
|
||||||
<input type="hidden" name="session" value="{{.session}}" />
|
<input type="hidden" name="session" value="{{.session}}" />
|
||||||
<div class="g-recaptcha"
|
<div class="{{.sitekeyClass}}"
|
||||||
data-sitekey="{{.siteKey}}"
|
data-sitekey="{{.sitekey}}"
|
||||||
data-callback="captchaDone">
|
data-callback="captchaDone">
|
||||||
</div>
|
</div>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
@ -116,7 +115,10 @@ func AuthFallback(
|
||||||
data := map[string]string{
|
data := map[string]string{
|
||||||
"myUrl": req.URL.String(),
|
"myUrl": req.URL.String(),
|
||||||
"session": sessionID,
|
"session": sessionID,
|
||||||
"siteKey": cfg.RecaptchaPublicKey,
|
"apiJsUrl": cfg.RecaptchaApiJsUrl,
|
||||||
|
"sitekey": cfg.RecaptchaPublicKey,
|
||||||
|
"sitekeyClass": cfg.RecaptchaSitekeyClass,
|
||||||
|
"formField": cfg.RecaptchaFormField,
|
||||||
}
|
}
|
||||||
serveTemplate(w, recaptchaTemplate, data)
|
serveTemplate(w, recaptchaTemplate, data)
|
||||||
}
|
}
|
||||||
|
@ -155,7 +157,7 @@ func AuthFallback(
|
||||||
return &res
|
return &res
|
||||||
}
|
}
|
||||||
|
|
||||||
response := req.Form.Get("g-recaptcha-response")
|
response := req.Form.Get(cfg.RecaptchaFormField)
|
||||||
if err := validateRecaptcha(cfg, response, clientIP); err != nil {
|
if err := validateRecaptcha(cfg, response, clientIP); err != nil {
|
||||||
util.GetLogger(req.Context()).Error(err)
|
util.GetLogger(req.Context()).Error(err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -336,6 +337,7 @@ func validateRecaptcha(
|
||||||
response string,
|
response string,
|
||||||
clientip string,
|
clientip string,
|
||||||
) *util.JSONResponse {
|
) *util.JSONResponse {
|
||||||
|
ip, _, _ := net.SplitHostPort(clientip)
|
||||||
if !cfg.RecaptchaEnabled {
|
if !cfg.RecaptchaEnabled {
|
||||||
return &util.JSONResponse{
|
return &util.JSONResponse{
|
||||||
Code: http.StatusConflict,
|
Code: http.StatusConflict,
|
||||||
|
@ -355,7 +357,7 @@ func validateRecaptcha(
|
||||||
url.Values{
|
url.Values{
|
||||||
"secret": {cfg.RecaptchaPrivateKey},
|
"secret": {cfg.RecaptchaPrivateKey},
|
||||||
"response": {response},
|
"response": {response},
|
||||||
"remoteip": {clientip},
|
"remoteip": {ip},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,13 @@ client_api:
|
||||||
recaptcha_public_key: ""
|
recaptcha_public_key: ""
|
||||||
recaptcha_private_key: ""
|
recaptcha_private_key: ""
|
||||||
recaptcha_bypass_secret: ""
|
recaptcha_bypass_secret: ""
|
||||||
recaptcha_siteverify_api: ""
|
|
||||||
|
# To use hcaptcha.com instead of ReCAPTCHA, set the following parameters, otherwise just keep them empty.
|
||||||
|
# recaptcha_siteverify_api: "https://hcaptcha.com/siteverify"
|
||||||
|
# recaptcha_api_js_url: "https://js.hcaptcha.com/1/api.js"
|
||||||
|
# recaptcha_form_field: "h-captcha-response"
|
||||||
|
# recaptcha_sitekey_class: "h-captcha"
|
||||||
|
|
||||||
|
|
||||||
# TURN server information that this homeserver should send to clients.
|
# TURN server information that this homeserver should send to clients.
|
||||||
turn:
|
turn:
|
||||||
|
|
|
@ -175,7 +175,13 @@ client_api:
|
||||||
recaptcha_public_key: ""
|
recaptcha_public_key: ""
|
||||||
recaptcha_private_key: ""
|
recaptcha_private_key: ""
|
||||||
recaptcha_bypass_secret: ""
|
recaptcha_bypass_secret: ""
|
||||||
recaptcha_siteverify_api: ""
|
|
||||||
|
# To use hcaptcha.com instead of ReCAPTCHA, set the following parameters, otherwise just keep them empty.
|
||||||
|
# recaptcha_siteverify_api: "https://hcaptcha.com/siteverify"
|
||||||
|
# recaptcha_api_js_url: "https://js.hcaptcha.com/1/api.js"
|
||||||
|
# recaptcha_form_field: "h-captcha-response"
|
||||||
|
# recaptcha_sitekey_class: "h-captcha"
|
||||||
|
|
||||||
|
|
||||||
# TURN server information that this homeserver should send to clients.
|
# TURN server information that this homeserver should send to clients.
|
||||||
turn:
|
turn:
|
||||||
|
|
|
@ -32,6 +32,12 @@ type ClientAPI struct {
|
||||||
// Boolean stating whether catpcha registration is enabled
|
// Boolean stating whether catpcha registration is enabled
|
||||||
// and required
|
// and required
|
||||||
RecaptchaEnabled bool `yaml:"enable_registration_captcha"`
|
RecaptchaEnabled bool `yaml:"enable_registration_captcha"`
|
||||||
|
// Recaptcha api.js Url, for compatible with hcaptcha.com, etc.
|
||||||
|
RecaptchaApiJsUrl string `yaml:"recaptcha_api_js_url"`
|
||||||
|
// Recaptcha div class for sitekey, for compatible with hcaptcha.com, etc.
|
||||||
|
RecaptchaSitekeyClass string `yaml:"recaptcha_sitekey_class"`
|
||||||
|
// Recaptcha form field, for compatible with hcaptcha.com, etc.
|
||||||
|
RecaptchaFormField string `yaml:"recaptcha_form_field"`
|
||||||
// This Home Server's ReCAPTCHA public key.
|
// This Home Server's ReCAPTCHA public key.
|
||||||
RecaptchaPublicKey string `yaml:"recaptcha_public_key"`
|
RecaptchaPublicKey string `yaml:"recaptcha_public_key"`
|
||||||
// This Home Server's ReCAPTCHA private key.
|
// This Home Server's ReCAPTCHA private key.
|
||||||
|
@ -75,6 +81,18 @@ func (c *ClientAPI) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
||||||
checkNotEmpty(configErrs, "client_api.recaptcha_public_key", c.RecaptchaPublicKey)
|
checkNotEmpty(configErrs, "client_api.recaptcha_public_key", c.RecaptchaPublicKey)
|
||||||
checkNotEmpty(configErrs, "client_api.recaptcha_private_key", c.RecaptchaPrivateKey)
|
checkNotEmpty(configErrs, "client_api.recaptcha_private_key", c.RecaptchaPrivateKey)
|
||||||
checkNotEmpty(configErrs, "client_api.recaptcha_siteverify_api", c.RecaptchaSiteVerifyAPI)
|
checkNotEmpty(configErrs, "client_api.recaptcha_siteverify_api", c.RecaptchaSiteVerifyAPI)
|
||||||
|
if c.RecaptchaSiteVerifyAPI == "" {
|
||||||
|
c.RecaptchaSiteVerifyAPI = "https://www.google.com/recaptcha/api/siteverify"
|
||||||
|
}
|
||||||
|
if c.RecaptchaApiJsUrl == "" {
|
||||||
|
c.RecaptchaApiJsUrl = "https://www.google.com/recaptcha/api.js"
|
||||||
|
}
|
||||||
|
if c.RecaptchaFormField == "" {
|
||||||
|
c.RecaptchaFormField = "g-recaptcha"
|
||||||
|
}
|
||||||
|
if c.RecaptchaSitekeyClass == "" {
|
||||||
|
c.RecaptchaSitekeyClass = "g-recaptcha-response"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Ensure there is any spam counter measure when enabling registration
|
// Ensure there is any spam counter measure when enabling registration
|
||||||
if !c.RegistrationDisabled && !c.OpenRegistrationWithoutVerificationEnabled {
|
if !c.RegistrationDisabled && !c.OpenRegistrationWithoutVerificationEnabled {
|
||||||
|
|
Loading…
Reference in a new issue