Skip to content

Commit ffaf7a9

Browse files
committed
MC-22950: Enable 2FA by default for Admins
- Refactored configure process
1 parent 23ed204 commit ffaf7a9

File tree

4 files changed

+48
-39
lines changed

4 files changed

+48
-39
lines changed

TwoFactorAuth/Block/Provider/U2fKey/Configure.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,16 @@ public function getJsLayout()
5858
$this->jsLayout['components']['tfa-configure']['touchImageUrl'] =
5959
$this->getViewFileUrl('Magento_TwoFactorAuth::images/u2f/touch.png');
6060

61-
$this->jsLayout['components']['tfa-configure']['registerData'] =
62-
$this->u2fKey->getRegisterData($this->session->getUser());
61+
$this->jsLayout['components']['tfa-configure']['registerData'] = $this->getRegisterData();
6362

6463
return parent::getJsLayout();
6564
}
65+
66+
public function getRegisterData(): array
67+
{
68+
$registerData = $this->u2fKey->getRegisterData($this->session->getUser());
69+
$this->session->setTfaU2fChallenge($registerData['publicKey']['challenge']);
70+
71+
return $registerData;
72+
}
6673
}

TwoFactorAuth/Controller/Adminhtml/U2f/Configurepost.php

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,19 +94,28 @@ public function execute()
9494
$result = $this->jsonFactory->create();
9595

9696
try {
97-
$data = $this->getRequest()->getParam('publicKeyCredential');
97+
$challenge = $this->session->getTfaU2fChallenge();
98+
if (!empty($challenge)) {
99+
$data = [
100+
'publicKeyCredential' => $this->getRequest()->getParam('publicKeyCredential'),
101+
'challenge' => $challenge
102+
];
103+
104+
$this->u2fKey->registerDevice($this->getUser(), $data);
105+
$this->tfaSession->grantAccess();
106+
$this->session->unsTfaU2fChallenge();
107+
108+
$this->alert->event(
109+
'Magento_TwoFactorAuth',
110+
'U2F New device registered',
111+
AlertInterface::LEVEL_INFO,
112+
$this->getUser()->getUserName()
113+
);
114+
$res = ['success' => true];
115+
} else {
116+
$res = ['success' => false];
117+
}
98118

99-
$this->u2fKey->registerDevice($this->getUser(), $data);
100-
$this->tfaSession->grantAccess();
101-
102-
$this->alert->event(
103-
'Magento_TwoFactorAuth',
104-
'U2F New device registered',
105-
AlertInterface::LEVEL_INFO,
106-
$this->getUser()->getUserName()
107-
);
108-
109-
$res = ['success' => true];
110119
} catch (\Throwable $e) {
111120
$this->alert->event(
112121
'Magento_TwoFactorAuth',

TwoFactorAuth/Model/Provider/Engine/U2fKey/WebAuthn.php

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,18 +214,30 @@ public function getRegisterData(UserInterface $user): array
214214
*/
215215
public function getPublicKeyFromRegistrationData(array $data): array
216216
{
217-
// Remaining steps (8+) of @see https://www.w3.org/TR/webauthn/#registering-a-new-credential
218-
if (empty($data['response']['attestationObject']) || empty($data['id'])) {
219-
throw new ValidationException(__('Invalid U2F key data'));
217+
// Verification process as defined by w3 @see https://www.w3.org/TR/webauthn/#registering-a-new-credential
218+
219+
$credentialData = $data['publicKeyCredential'];
220+
$domain = $this->getDomainName();
221+
222+
if (rtrim(strtr(base64_encode($this->convertArrayToBytes($data['challenge'])), '+/', '-_'), '=')
223+
!== $credentialData['response']['clientData']['challenge']
224+
|| 'https://' . $domain !== $credentialData['response']['clientData']['origin']
225+
|| $credentialData['response']['clientData']['type'] !== 'webauthn.create'
226+
) {
227+
throw new LocalizedException(__('Invalid U2F key.'));
220228
}
221229

222-
$byteString = base64_decode($data['response']['attestationObject']);
230+
if (empty($credentialData['response']['attestationObject']) || empty($credentialData['id'])) {
231+
throw new ValidationException(__('Invalid U2F key data'));
232+
}
233+
$byteString = base64_decode($credentialData['response']['attestationObject']);
223234
$attestationObject = CBOREncoder::decode($byteString);
224235
if (empty($attestationObject['fmt'])
225236
|| empty($attestationObject['authData'])
226237
) {
227238
throw new ValidationException(__('Invalid U2F key data'));
228239
}
240+
229241
$byteString = $attestationObject['authData']->get_byte_string();
230242

231243
// @see https://www.w3.org/TR/webauthn/#sec-authenticator-data
@@ -257,14 +269,14 @@ public function getPublicKeyFromRegistrationData(array $data): array
257269
$attestationObject['attestationData']['keyBytes'] = $this->COSEECDHAtoPKCS($cborPublicKey);
258270

259271
if (empty($attestationObject['attestationData']['keyBytes'])
260-
|| $attestationObject['attestationData']['credId'] !== base64_decode($data['id'])
272+
|| $attestationObject['attestationData']['credId'] !== base64_decode($credentialData['id'])
261273
) {
262274
throw new ValidationException(__('Invalid U2F key data'));
263275
}
264276

265277
return [
266278
'key' => $attestationObject['attestationData']['keyBytes'],
267-
'id' => $data['id'],
279+
'id' => $credentialData['id'],
268280
'aaguid' => $attestationObject['attestationData']['aaguid'] ?? null
269281
];
270282
}

TwoFactorAuth/view/adminhtml/web/js/u2fkey/configure.js

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,25 +107,6 @@ define([
107107
* @private
108108
*/
109109
_processCredentialData: function (credentialData) {
110-
// Steps 1-5 of @see https://www.w3.org/TR/webauthn/#registering-a-new-credential
111-
var b64Challenge = window.btoa(
112-
String.fromCharCode.apply(null, new Uint8Array(this.registerData.publicKey.challenge))
113-
)
114-
.replace(/=+$/g, '')
115-
.replace(/\+/g, '-')
116-
.replace(/\//g, '_');
117-
118-
if (b64Challenge !== credentialData.clientData.challenge ||
119-
'https://' + this.registerData.publicKey.rp.name !== credentialData.clientData.origin ||
120-
!('type' in credentialData.clientData) ||
121-
credentialData.clientData.type !== 'webauthn.create'
122-
) {
123-
error.display($t('Invalid key'));
124-
this.idle(true);
125-
126-
return;
127-
}
128-
129110
this.loading(true);
130111
$.post(this.getPostUrl(), {
131112
publicKeyCredential: {

0 commit comments

Comments
 (0)