user("web")->name, $request->user("web")->id, $request->user("web")->name, ); $challenge = random_bytes(16); $request->session()->put("webauthn_register_challenge", $challenge); return WebAuthnService::createRequestOptions($userEntity, $challenge); } public function login_options(Request $request): PublicKeyCredentialRequestOptions { $challenge = random_bytes(32); $request->session()->put("webauthn_login_challenge", $challenge); $publicKeyCredentialRequestOptions = new PublicKeyCredentialRequestOptions( $challenge ); $publicKeyCredentialRequestOptions->setUserVerification( PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_REQUIRED ); $publicKeyCredentialRequestOptions->allowCredentials([]); $publicKeyCredentialRequestOptions->setTimeout($this->TIMEOUT); return $publicKeyCredentialRequestOptions; } public function register_validate(Request $request) { if (!$request->session()->has("webauthn_register_challenge")) { /// } $publicKeyCredential = $this->get_public_key_credential_loader()->loadArray($request->json()->all()); $authenticatorAttestationResponse = $publicKeyCredential->getResponse(); if (!$authenticatorAttestationResponse instanceof AuthenticatorAttestationResponse) { //e.g. process here with a redirection to the public key creation page. } $userEntity = new PublicKeyCredentialUserEntity( $request->user("web")->name, $request->user("web")->id, $request->user("web")->name, ); $challenge = $request->session()->remove("webauthn_register_challenge"); $publicKeyCredentialCreationOptions = WebAuthnService::createRequestOptions($userEntity, $challenge); $publicKeyCredentialSource = $this->get_authn_attestation_response_validator()->check( $authenticatorAttestationResponse, $publicKeyCredentialCreationOptions, ServerRequest::fromGlobals(), ["localhost"] ); $this->get_pub_key_cred_source_repository()->saveCredentialSource($publicKeyCredentialSource); return $publicKeyCredentialSource; } public function login_validate(Request $request) { if (!$request->session()->has("webauthn_login_challenge")) { /// } $publicKeyCredentialRequestOptions = new PublicKeyCredentialRequestOptions( $request->session()->remove("webauthn_login_challenge") ); $publicKeyCredential = $this->get_public_key_credential_loader()->loadArray($request->json()->all()); $authenticatorAssertionResponse = $publicKeyCredential->getResponse(); if (!$authenticatorAssertionResponse instanceof AuthenticatorAssertionResponse) { //e.g. process here with a redirection to the public key login/MFA page. } try { $publicKeyCredentialSource = $this->get_authn_assertion_response_validator()->check( $publicKeyCredential->getRawId(), $authenticatorAssertionResponse, $publicKeyCredentialRequestOptions, ServerRequest::fromGlobals(), $authenticatorAssertionResponse->getUserHandle(), ["localhost"] ); } catch (\Throwable $e) { return redirect(route("login")); } Auth::loginUsingId($publicKeyCredentialSource->getUserHandle()); return redirect()->intended(); } private function get_authn_attestation_response_validator(): AuthenticatorAttestationResponseValidator { $authenticatorAttestationResponseValidator = new AuthenticatorAttestationResponseValidator( $this->get_attestation_stmt_sup_mgr(), WebAuthnService::getPublicKeyCredentialSourceRepository(), new IgnoreTokenBindingHandler(), new ExtensionOutputCheckerHandler() ); return $authenticatorAttestationResponseValidator; } private function get_authn_assertion_response_validator(): AuthenticatorAssertionResponseValidator { $algorithmManager = new Manager(); $algorithmManager->add(new ES256()); $algorithmManager->add(new RS256()); $authenticatorAssertionResponseValidator = new AuthenticatorAssertionResponseValidator( WebAuthnService::getPublicKeyCredentialSourceRepository(), new IgnoreTokenBindingHandler(), new ExtensionOutputCheckerHandler(), $algorithmManager ); return $authenticatorAssertionResponseValidator; } private function get_public_key_credential_loader(): PublicKeyCredentialLoader { $publicKeyCredentialLoader = new PublicKeyCredentialLoader( $this->get_attestation_loader() ); return $publicKeyCredentialLoader; } private function get_attestation_loader(): AttestationObjectLoader { $attestationObjectLoader = new AttestationObjectLoader($this->get_attestation_stmt_sup_mgr()); return $attestationObjectLoader; } private function get_attestation_stmt_sup_mgr() { if ($this->attestationStatementSupportManager === null) { $this->attestationStatementSupportManager = new AttestationStatementSupportManager(); $this->attestationStatementSupportManager->add(new NoneAttestationStatementSupport()); } return $this->attestationStatementSupportManager; } }