mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-16 18:43:10 -06:00
add support for hcaptcha.com
This commit is contained in:
parent
7506e3303e
commit
117c6a5668
|
|
@ -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},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -382,7 +384,7 @@ func validateRecaptcha(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &util.JSONResponse{
|
return &util.JSONResponse{
|
||||||
Code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
JSON: jsonerror.BadJSON("Error in unmarshaling captcha server's response: " + err.Error()),
|
JSON: jsonerror.BadJSON("Error in unmarshaling captcha server's response: " + err.Error()+"\n"+ string(body) + "\n"+clientip),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -748,7 +750,8 @@ func handleRegistrationFlow(
|
||||||
switch r.Auth.Type {
|
switch r.Auth.Type {
|
||||||
case authtypes.LoginTypeRecaptcha:
|
case authtypes.LoginTypeRecaptcha:
|
||||||
// Check given captcha response
|
// Check given captcha response
|
||||||
resErr := validateRecaptcha(cfg, r.Auth.Response, req.RemoteAddr)
|
clientIp, _, _ := net.SplitHostPort(req.RemoteAddr)
|
||||||
|
resErr := validateRecaptcha(cfg, r.Auth.Response, clientIp)
|
||||||
if resErr != nil {
|
if resErr != nil {
|
||||||
return *resErr
|
return *resErr
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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