Created
March 17, 2024 09:11
-
-
Save Chenx221/f7b5acb5b16704cfd734214a3e578cfa to your computer and use it in GitHub Desktop.
Yii2, Webauthn Framework (Part 1)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public function actionCreateCredentialOptions(): Response | |
{ | |
$id = Yii::$app->params['domain']; | |
$user = Yii::$app->user->identity; | |
$rpEntity = PublicKeyCredentialRpEntity::create( | |
'NetDisk Application', | |
$id | |
); | |
$userEntity = PublicKeyCredentialUserEntity::create( | |
$user->username, | |
$user->id, | |
$user->name, | |
); | |
$challenge = random_bytes(16); | |
$publicKeyCredentialCreationOptions = | |
PublicKeyCredentialCreationOptions::create( | |
$rpEntity, | |
$userEntity, | |
$challenge | |
); | |
Yii::$app->session->set('publicKeyCredentialCreationOptions', $publicKeyCredentialCreationOptions); | |
return $this->asJson($publicKeyCredentialCreationOptions); | |
} | |
public function actionCreateCredential(): Response | |
{ | |
$data = Yii::$app->request->getRawBody(); | |
$json_decode = json_decode($data, true); | |
$fido_name = empty($json_decode['fido_name']) ? 'Unknown' : $json_decode['fido_name']; | |
$attestationStatementSupportManager = AttestationStatementSupportManager::create(); | |
$attestationStatementSupportManager->add(NoneAttestationStatementSupport::create()); | |
$webauthnSerializerFactory = new WebauthnSerializerFactory($attestationStatementSupportManager); | |
$serializer = $webauthnSerializerFactory->create(); | |
$publicKeyCredential = $serializer->deserialize($data, PublicKeyCredential::class, 'json'); | |
$authenticatorAttestationResponse = $publicKeyCredential->response; | |
if (!$authenticatorAttestationResponse instanceof AuthenticatorAttestationResponse) { | |
return $this->asJson(['message' => 'Invalid response type']); | |
} | |
// 什么时候更新开发文档? | |
$ceremonyStepManagerFactory = new CeremonyStepManagerFactory(); | |
$ceremonyStepManager = $ceremonyStepManagerFactory->creationCeremony(); | |
$authenticatorAttestationResponseValidator = AuthenticatorAttestationResponseValidator::create( | |
null, | |
null, | |
null, | |
null, | |
null, | |
$ceremonyStepManager | |
); | |
$publicKeyCredentialCreationOptions = Yii::$app->session->get('publicKeyCredentialCreationOptions'); | |
try { | |
$publicKeyCredentialSource = $authenticatorAttestationResponseValidator->check( | |
$authenticatorAttestationResponse, | |
$publicKeyCredentialCreationOptions, | |
Yii::$app->params['domain'] | |
); | |
$publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository(); | |
$publicKeyCredentialSourceRepository->saveCredential($publicKeyCredentialSource, $fido_name); | |
return $this->asJson(['verified' => true]); | |
} catch (Throwable $e) { | |
return $this->asJson(['message' => $e->getMessage(), 'verified' => false]); | |
} | |
} | |
public function actionRequestAssertionOptions(): Response | |
{ | |
$user = Yii::$app->user->identity; | |
$publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository(); | |
$registeredAuthenticators = $publicKeyCredentialSourceRepository->findAllForUserEntity($user); | |
$allowedCredentials = array_map( | |
static function (PublicKeyCredentialSourceRepository $credential): PublicKeyCredentialDescriptor { | |
$data = $credential->data; | |
$webauthnSerializerFactory = new WebauthnSerializerFactory(new AttestationStatementSupportManager()); | |
$publicKeyCredentialSource = $webauthnSerializerFactory->create()->deserialize($data, PublicKeyCredentialSource::class, 'json'); | |
return $publicKeyCredentialSource->getPublicKeyCredentialDescriptor(); | |
}, | |
$registeredAuthenticators | |
); | |
$publicKeyCredentialRequestOptions = | |
PublicKeyCredentialRequestOptions::create( | |
random_bytes(32), // Challenge | |
allowCredentials: $allowedCredentials | |
); | |
Yii::$app->session->set('publicKeyCredentialRequestOptions', $publicKeyCredentialRequestOptions); | |
return $this->asJson($publicKeyCredentialRequestOptions); | |
} | |
public function actionVerifyAssertion(): Response | |
{ | |
$data = Yii::$app->request->getRawBody(); | |
$attestationStatementSupportManager = AttestationStatementSupportManager::create(); | |
$attestationStatementSupportManager->add(NoneAttestationStatementSupport::create()); | |
$webauthnSerializerFactory = new WebauthnSerializerFactory($attestationStatementSupportManager); | |
$serializer = $webauthnSerializerFactory->create(); | |
$publicKeyCredential = $serializer->deserialize($data, PublicKeyCredential::class, 'json'); | |
$authenticatorAssertionResponse = $publicKeyCredential->response; | |
if (!$authenticatorAssertionResponse instanceof AuthenticatorAssertionResponse) { | |
return $this->asJson(['message' => 'Invalid response type']); | |
} | |
$publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository(); | |
$publicKeyCredentialSourceRepository1 = $publicKeyCredentialSourceRepository->findOneByCredentialId( | |
$publicKeyCredential->id | |
); | |
if ($publicKeyCredentialSourceRepository1 === null) { | |
return $this->asJson(['message' => 'Invalid credential']); | |
} | |
$PKCS = $webauthnSerializerFactory->create()->deserialize($publicKeyCredentialSourceRepository1->data, PublicKeyCredentialSource::class, 'json'); | |
$ceremonyStepManagerFactory = new CeremonyStepManagerFactory(); | |
$ceremonyStepManager = $ceremonyStepManagerFactory->requestCeremony(); | |
$authenticatorAssertionResponseValidator = AuthenticatorAssertionResponseValidator::create( | |
null, | |
null, | |
null, | |
null, | |
null, | |
$ceremonyStepManager | |
); | |
$publicKeyCredentialRequestOptions = Yii::$app->session->get('publicKeyCredentialRequestOptions'); | |
try { | |
$publicKeyCredentialSource = $authenticatorAssertionResponseValidator->check( | |
$PKCS, //credential source | |
$authenticatorAssertionResponse, //user response | |
$publicKeyCredentialRequestOptions, | |
Yii::$app->params['domain'], | |
$publicKeyCredentialSourceRepository1->user_id | |
); | |
} catch (AuthenticatorResponseVerificationException $e) { | |
return $this->asJson(['message' => $e->getMessage(), 'verified' => false]); | |
} | |
// Optional, but highly recommended, you can save the credential source as it may be modified | |
// during the verification process (counter may be higher). | |
$publicKeyCredentialSourceRepository1->saveCredential($publicKeyCredentialSource, '',false); | |
return $this->asJson(['verified' => true]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment