json(['error' => 'کاربر لاگین نیست'], 403); } $customer = User::where('user_name', $user_identity)->first(); if (!$customer) { return response()->json(['error' => 'کاربر یافت نشد'], 404); } $challenge = random_bytes(32); $challengeBase64 = $this->b64e($challenge); Cache::put("register_challenge_{$customer->id}", $challengeBase64, 120); return response()->json([ "publicKey" => [ "rp" => [ "name" => $this->rpName, "id" => $this->rpId, ], "user" => [ "id" => $this->b64e($customer->id), "name" => $customer->user_name, "displayName" => $customer->name, "number" => $customer->number, ], "challenge" => $challengeBase64, "pubKeyCredParams" => [ ["type" => "public-key", "alg" => -7] ], "authenticatorSelection" => [ "userVerification" => "required" ] ] ]); } /** تایید ثبت اثر انگشت */ public function verifyRegister(Request $request) { $user_identity = $_COOKIE['user_identity'] ?? null; if (!$user_identity) { return response()->json(['error' => 'کاربر لاگین نیست'], 403); } $customer = User::where('user_name', $user_identity)->first(); if (!$customer) { return response()->json(['error' => 'کاربر یافت نشد'], 404); } $data = $request->all(); $storedChallenge = Cache::pull("register_challenge_{$customer->id}"); if (!$storedChallenge) return response()->json(["error" => "challenge not found"], 400); if (!isset($data['response']['clientDataJSON'])) return response()->json(["error" => "clientDataJSON missing"], 400); $clientDataJSON = base64_decode(strtr($data['response']['clientDataJSON'], '-_', '+/')); $clientData = json_decode($clientDataJSON, true); if (!$clientData) return response()->json(["error" => "Invalid clientData"], 400); if (!hash_equals($clientData['challenge'], $storedChallenge)) return response()->json(["error" => "Invalid challenge"], 403); if ($clientData['origin'] !== 'https://' . $this->rpId) return response()->json(["error" => "Invalid origin"], 403); if ($clientData['type'] !== 'webauthn.create') return response()->json(["error" => "Invalid type"], 403); Webauth::create([ "name" => $request->input("name", "دستگاه " . $customer->name), "customer_id" => $customer->id, "credential_id" => $data["id"], "public_key" => $data["response"]["publicKey"], "attestation" => json_encode($data["response"]["attestationObject"]), "transports" => null, "sign_count" => 0, "last_used_at" => now(), ]); return response()->json(["message" => "اثر انگشت با موفقیت ثبت شد"]); } /** تولید challenge برای ورود */ public function generateLoginOptions() { $challenge = $this->b64e(random_bytes(32)); Cache::put("login_challenge_global", $challenge, 120); return response()->json([ "publicKey" => [ "challenge" => $challenge, "rpId" => $this->rpId, "userVerification" => "required", "timeout" => 60000, ] ]); } /** تایید ورود */ public function verifyLogin(Request $request) { $data = $request->all(); $credentialId = $data['id'] ?? null; if (!$credentialId) { return response()->json(["message" => "credential_id missing"], 400); } $credential = Webauth::where("credential_id", $credentialId)->first(); if (!$credential) { return response()->json(["message" => "اثر انگشت شناخته نشد"], 404); } $customer = User::find($credential->customer_id); if (!$customer) { return response()->json(["message" => "کاربر حذف شده"], 404); } $storedChallenge = Cache::pull("login_challenge_global"); if (!$storedChallenge) { return response()->json(["message" => "Challenge منقضی شد"], 403); } // clientData $clientDataJSON = base64_decode(strtr($data['response']['clientDataJSON'], '-_', '+/')); $clientData = json_decode($clientDataJSON, true); if ($clientData['challenge'] !== $storedChallenge) { return response()->json(["message" => "Invalid challenge"], 403); } if ($clientData['origin'] !== 'https://' . $this->rpId) { return response()->json(["message" => "Invalid origin"], 403); } // authenticatorData $authData = base64_decode(strtr($data['response']['authenticatorData'], '-_', '+/')); $signature = base64_decode(strtr($data['response']['signature'], '-_', '+/')); $clientDataHash = hash('sha256', $clientDataJSON, true); $signedData = $authData . $clientDataHash; $ok = openssl_verify($signedData, $signature, $credential->public_key, OPENSSL_ALGO_SHA256); if ($ok !== 1) { return response()->json(["message" => "Invalid signature"], 403); } // لاگین $token = auth('customer')->login($customer); auth('customer')->setUser($customer); return response()->json([ "message" => "ورود موفق", "token" => $token, "user_id" => $customer->id ]); } private function b64e($v) { return rtrim(strtr(base64_encode($v),'+/','-_'),'='); } }