Subversion Repositories oidplus

Rev

Rev 1149 | Rev 1181 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1001 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
1086 daniel-mar 5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
1001 daniel-mar 6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
1050 daniel-mar 20
namespace ViaThinkSoft\OIDplus;
1001 daniel-mar 21
 
1086 daniel-mar 22
// phpcs:disable PSR1.Files.SideEffects
23
\defined('INSIDE_OIDPLUS') or die;
24
// phpcs:enable PSR1.Files.SideEffects
25
 
1001 daniel-mar 26
class OIDplusCaptchaPluginHCaptcha extends OIDplusCaptchaPlugin {
27
 
1116 daniel-mar 28
        /**
29
         * @return string
30
         */
1001 daniel-mar 31
        public static function id(): string {
32
                return 'hCaptcha';
33
        }
34
 
1116 daniel-mar 35
        /**
36
         * @return bool
37
         */
1016 daniel-mar 38
        public function isVisible(): bool {
1001 daniel-mar 39
                return true;
40
        }
41
 
1116 daniel-mar 42
        /**
43
         * @param string|null $header_text
44
         * @param string|null $footer_text
45
         * @return string
46
         * @throws OIDplusException
47
         */
48
        public function captchaGenerate(string $header_text=null, string $footer_text=null): string {
1001 daniel-mar 49
                return ($header_text ? '<p>'.$header_text.'</p>' : '') .
50
                       '<noscript>'.
51
                       '<p><font color="red">'._L('You need to enable JavaScript to solve the CAPTCHA.').'</font></p>'.
52
                       '</noscript>'.
53
                       '<div id="h-captcha"></div>'.
1019 daniel-mar 54
                       '<script src="https://js.hcaptcha.com/1/api.js"></script>'.
1024 daniel-mar 55
                       '<script>'.
56
                       'OIDplusCaptchaPluginHCaptcha.captchaShow('.js_escape(OIDplus::baseConfig()->getValue('HCAPTCHA_SITEKEY', '')).')'.
57
                       '</script>'.
1001 daniel-mar 58
                       ($footer_text ? '<p>'.$footer_text.'</p>' : '');
59
        }
60
 
1116 daniel-mar 61
        /**
62
         * @param string[] $params
63
         * @param string|null $fieldname
64
         * @return void
65
         * @throws OIDplusException
66
         */
67
        public function captchaVerify(array $params, string $fieldname=null) {
1001 daniel-mar 68
                $sitekey=OIDplus::baseConfig()->getValue('HCAPTCHA_SITEKEY', '');
69
                $secret=OIDplus::baseConfig()->getValue('HCAPTCHA_SECRET', '');
70
 
71
                // Yes, it is really "g-recaptcha-response"!
72
                if (is_null($fieldname)) $fieldname = 'g-recaptcha-response'; // no individual field name (created by oidplus_captcha_response()) means that it is a plain POST event (e.g. by oobe.php)
73
                _CheckParamExists($params, $fieldname);
74
                $response=$params[$fieldname];
75
 
1149 daniel-mar 76
                $res = url_post_contents(
77
                        'https://hcaptcha.com/siteverify',
78
                        array(
79
                                "secret"   => $secret,
80
                                "response" => $response,
81
                                "remoteip" => $_SERVER['REMOTE_ADDR'],
82
                                "sitekey"  => $sitekey
83
                        )
84
                );
85
 
86
                if ($res === false) {
87
                        throw new OIDplusException(_L('Communication with %1 server failed', 'hCaptcha'));
1001 daniel-mar 88
                }
89
 
90
                $captcha_success=@json_decode($res);
1162 daniel-mar 91
                if (!$captcha_success || !$captcha_success->success) {
1001 daniel-mar 92
                        throw new OIDplusException(_L('CAPTCHA not successfully verified').' ('.implode(", ",$captcha_success->{'error-codes'}).')');
93
                }
94
        }
95
 
1116 daniel-mar 96
        /**
97
         * @return string
98
         */
1001 daniel-mar 99
        public static function setupHTML(): string {
1149 daniel-mar 100
                $curl_status = url_post_contents_available() ? 1 : 0;
1001 daniel-mar 101
                return '<div id="CAPTCHAPLUGIN_PARAMS_HCAPTCHA">'.
102
                       '<p>(<a href="https://www.hcaptcha.com/" target="_blank">'._L('more information and obtain key').'</a>)</p>'.
103
                       '<p>'._L('hCaptcha Site key').'<br><input id="hcaptcha_sitekey" type="text" onkeypress="rebuild()" onkeyup="rebuild()"> <span id="hcaptcha_sitekey_warn"></span></p>'.
104
                       '<p>'._L('hCaptcha Secret').'<br><input id="hcaptcha_secret" type="text" onkeypress="rebuild()" onkeyup="rebuild()"> <span id="hcaptcha_secret_warn"></span></p>'.
1003 daniel-mar 105
                       '<input id="hcaptcha_curl_status" value="'.$curl_status.'" type="hidden">'.
106
                       (!$curl_status ? '<p><font color="red">'._L('hCaptcha plugin needs the PHP extension php_curl').'</font></p>' : '').
1001 daniel-mar 107
                       '</div>';
108
        }
109
 
1116 daniel-mar 110
        /**
111
         * @param array $http_headers
112
         * @return void
113
         */
114
        function httpHeaderCheck(array &$http_headers) {
1001 daniel-mar 115
 
116
                // If you use CSP headers, please add the following to your configuration:
117
                // script-src should include https://hcaptcha.com, https://*.hcaptcha.com
118
                $http_headers["Content-Security-Policy"]["script-src"][] = "https://hcaptcha.com";
119
                $http_headers["Content-Security-Policy"]["script-src"][] = "https://*.hcaptcha.com";
120
                // frame-src should include https://hcaptcha.com, https://*.hcaptcha.com
121
                $http_headers["Content-Security-Policy"]["frame-src"][] = "https://hcaptcha.com";
122
                $http_headers["Content-Security-Policy"]["frame-src"][] = "https://*.hcaptcha.com";
123
                // style-src should include https://hcaptcha.com, https://*.hcaptcha.com
124
                $http_headers["Content-Security-Policy"]["style-src"][] = "https://hcaptcha.com";
125
                $http_headers["Content-Security-Policy"]["style-src"][] = "https://*.hcaptcha.com";
126
                // connect-src should include https://hcaptcha.com, https://*.hcaptcha.com
127
                $http_headers["Content-Security-Policy"]["connect-src"][] = "https://hcaptcha.com";
128
                $http_headers["Content-Security-Policy"]["connect-src"][] = "https://*.hcaptcha.com";
129
 
130
                //If you are an enterprise customer and would like to enable additional verification to be performed, you can optionally choose the following CSP strategy:
131
                //unsafe-eval and unsafe-inline should include https://hcaptcha.com, https://*.hcaptcha.com
132
                //$http_headers["Content-Security-Policy"]["unsafe-eval"][] = "https://hcaptcha.com";
133
                //$http_headers["Content-Security-Policy"]["unsafe-eval"][] = "https://*.hcaptcha.com";
134
                //$http_headers["Content-Security-Policy"]["unsafe-inline"][] = "https://hcaptcha.com";
135
                //$http_headers["Content-Security-Policy"]["unsafe-inline"][] = "https://*.hcaptcha.com";
136
 
137
        }
138
 
139
}