PluginProbe ʕ •ᴥ•ʔ
CloudSecure WP Security / 1.2.3
CloudSecure WP Security v1.2.3
1.4.10 1.4.9 trunk 0.9.0 1.0.2 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.19 1.3.2 1.3.20 1.3.21 1.3.22 1.3.23 1.3.24 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8
cloudsecure-wp-security / modules / admin / two-factor-authentication-registration.php
cloudsecure-wp-security / modules / admin Last commit date
captcha.php 2 years ago common.php 2 years ago dashboard.php 2 years ago disable-author-query.php 2 years ago disable-login.php 2 years ago disable-restapi.php 2 years ago disable-xmlrpc.php 2 years ago login-log-table.php 2 years ago login-log.php 2 years ago login-notification.php 2 years ago rename-login-page.php 2 years ago restrict-admin-page.php 2 years ago server-error-notification.php 2 years ago server-error-table.php 2 years ago two-factor-authentication-registration.php 2 years ago two-factor-authentication.php 2 years ago unify-messages.php 2 years ago update-notice.php 2 years ago
two-factor-authentication-registration.php
197 lines
1 <?php
2
3 class CloudSecureWP_Admin_Two_Factor_Authentication_Registration extends CloudSecureWP_Admin_Common {
4 private $two_factor_authentication;
5 /**
6 * 管理画面にレンダリングするキー
7 *
8 * @var string
9 */
10 private $default_key;
11
12 function __construct( array $info, CloudSecureWP_Two_Factor_Authentication $two_factor_authentication ) {
13 parent::__construct( $info );
14 $this->two_factor_authentication = $two_factor_authentication;
15 $this->prepare_view_data();
16 $this->render();
17 }
18
19 /**
20 * 画面表示用のデータを準備
21 */
22 public function prepare_view_data(): void {
23 $this->default_key = get_user_option( 'cloudsecurewp_two_factor_authentication_secret' );
24 if ( ! empty( $_POST ) && check_admin_referer( $this->two_factor_authentication->get_feature_key() . '_csrf' ) ) {
25 if ( ! empty( $_POST['key'] ) ) {
26 $this->default_key = sanitize_text_field( $_POST['key'] );
27 }
28 if ( empty( $_POST['key'] ) ) {
29 $this->errors[] = 'セットアップキーを保存できませんでした。<br />セットアップキーを生成してください。';
30
31 return;
32 }
33 if ( empty( $_POST['google_authenticator_code'] ) ) {
34 $this->errors[] = 'セットアップキーを保存できませんでした。<br />QRコードをGoogle Authenticator アプリケーションでスキャンし、認証コードを�
35 �力してください。';
36
37 return;
38 }
39 $key = sanitize_text_field( $_POST['key'] );
40 $google_authenticator_code = sanitize_text_field( $_POST['google_authenticator_code'] );
41 if ( CloudSecureWP_Time_Based_One_Time_Password::verify_code( $key, $google_authenticator_code, 2 ) ) {
42 update_user_option( get_current_user_id(), 'cloudsecurewp_two_factor_authentication_secret', $key );
43 $this->messages[] = 'セットアップキーを保存しました。';
44 } else {
45 $this->errors[] = 'セットアップキーを保存できませんでした。<br />認証コードが間違っています。';
46 }
47 }
48 }
49
50 /**
51 * ディスクリプション
52 */
53 protected function admin_description(): void {
54 ?>
55 <div class="title-block mb-12">
56 <h1 class="title-block-title">デバイス登録 - 2段階認証</h1>
57 <p class="title-block-small-text">この機能のマニュアルは<a class="title-block-link" target="_blank"
58 href="https://wpplugin.cloudsecure.ne.jp/cloudsecure_wp_security/two_factor_authentication.php">こちら</a>
59 </p>
60 </div>
61 <div class="title-bottom-text">
62 2段階認証機能をアクティブにするには、セットアップキーを生成し、<a class="title-block-link" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" target="_blank">Google Authenticator</a>  アプリケーションでQRコードを読み込んでください。<br />
63 QRコードを読み込めない場合、<a class="title-block-link" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" target="_blank">Google Authenticator</a>  アプリケーションにセットアップキーを�
64 �力してください。
65 </div>
66 <?php
67 }
68
69 /**
70 * ページコンテンツ
71 */
72 protected function page(): void {
73 ?>
74 <form method="post">
75 <div class="box">
76 <div class="box-bottom">
77 <div class="box-row flex-start">
78 <div class="box-row-title not-label pt-12">
79 <label for="key">セットアップキー</label>
80 </div>
81 <div class="box-row-content">
82 <div class="flex">
83 <input type="text" id="key" name="key"
84 value="<?php echo esc_attr( $this->default_key ); ?>" maxlength="16"
85 readonly/>
86 <button id="generate_key" type="button" class="button button-large">
87 セットアップキーを生成
88 </button>
89 </div>
90 <div id="qrcode_container" hidden>
91 <div id="qrcode"></div>
92 <div class="flex onetime-password-container">
93 <label for="google_authenticator_code">認証コード:</label>
94 <input type="text" id="google_authenticator_code" name="google_authenticator_code"
95 maxlength="6"/>
96 </div>
97 </div>
98 </div>
99 </div>
100 </div>
101 </div>
102 <div id="submit-btn-area">
103 <?php $this->nonce_wp( $this->two_factor_authentication->get_feature_key() ); ?>
104 <p id="guide_message" hidden>アプリケーションに表示された6桁の認証コードを�
105 �力し、「変更を保存」ボタンをクリックしてください。</p>
106 <?php $this->submit_button_wp(); ?>
107 </div>
108 </form>
109 <style>
110 #generate_key {
111 margin-left: 16px;
112 }
113
114 #qrcode {
115 margin: 32px 32px 16px;
116 }
117
118 .onetime-password-container {
119 margin-left: -20px;
120 }
121 </style>
122 <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"
123 type="text/javascript"></script>
124 <script type="text/javascript">
125 function quintetCount(buff) {
126 const quintets = Math.floor(buff.length / 5);
127 return buff.length % 5 === 0 ? quintets : quintets + 1;
128 }
129
130 function bufferToBase32(plain) {
131 let i = 0;
132 let j = 0;
133 let shiftIndex = 0;
134 let digit = 0;
135 const charTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
136 const encoded = new Array(quintetCount(plain) * 8);
137
138 /* byte by byte は、quintet by quintet ほどきれいではありませんが、テストは少し速くなります。 再訪する�
139 要があります。 */
140 while (i < plain.length) {
141 const current = plain[i];
142
143 if (shiftIndex > 3) {
144 digit = current & (0xff >> shiftIndex);
145 shiftIndex = (shiftIndex + 5) % 8;
146 digit = (digit << shiftIndex) | ((i + 1 < plain.length) ?
147 plain[i + 1] : 0) >> (8 - shiftIndex);
148 i++;
149 } else {
150 digit = (current >> (8 - (shiftIndex + 5))) & 0x1f;
151 shiftIndex = (shiftIndex + 5) % 8;
152 if (shiftIndex === 0) {
153 i++;
154 }
155 }
156
157 encoded[j] = charTable[digit];
158 j++;
159 }
160
161 for (i = j; i < encoded.length; i++) {
162 encoded[i] = '=';
163 }
164
165 return encoded.join('');
166 }
167
168 function generateKey() {
169 return bufferToBase32(crypto.getRandomValues(new Uint8Array(10)))
170 }
171
172 const qrcode = new QRCode('qrcode', {correctLevel: QRCode.CorrectLevel.M})
173
174 function showQRIfExists() {
175 const key = document.getElementById('key').value
176 document.getElementById('qrcode_container').hidden = !key
177 document.getElementById('guide_message').hidden = !key
178 if (!key) return
179 const name = document.querySelector('.display-name').textContent
180
181 // https://github.com/google/google-authenticator/wiki/Key-Uri-Format
182 qrcode.makeCode(`otpauth://totp/${encodeURIComponent(name)}?secret=${key}&issuer=${location.hostname}`)
183
184 document.getElementById('google_authenticator_code').focus()
185 }
186
187 showQRIfExists()
188
189 document.getElementById('generate_key').addEventListener('click', () => {
190 document.getElementById('key').value = generateKey()
191 showQRIfExists()
192 })
193 </script>
194 <?php
195 }
196 }
197