diff --git a/components/magicLink/login.tsx b/components/magicLink/login.tsx index 61eed1c7..6cc171a3 100644 --- a/components/magicLink/login.tsx +++ b/components/magicLink/login.tsx @@ -34,6 +34,7 @@ export default function Login({ challenge, clinical=false, authonly=false, clien const [error, setError] = useState(""); const [isError, setIsError] = useState(false); const [isChecking, setIsChecking] = useState(false); + const [isTimeout, setIsTimeout] = useState(false); const [isAvailable, setIsAvailable] = useState(null); const [register, setRegister] = useState(false); const [progress, setProgress] = useState(""); @@ -64,102 +65,110 @@ export default function Login({ challenge, clinical=false, authonly=false, clien { method: "PUT", headers: {"Content-Type": "application/json"}, body: JSON.stringify({email: email} )}) .then((res) => res.json()).then((json) => json.nonce); let check = false; - while (!check) { + let proceed = false; + let timer = 0; + while (!check || timer < 240) { await sleep(5); const nonce_check = await fetch("/api/auth/check", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({nonce: nonce}) }) .then((res) => res.json()); if (nonce_check.success) { check = true; + proceed = true; } + timer++; } - await fetch("/api/magicLink/login", - { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({email: email}) }); - if (isRegistered === undefined) { - const body = { email: email }; - const data = await fetch(`/api/couchdb/patients/new`, - { method: "POST", headers : {"Content-Type": "application/json"}, body: JSON.stringify(body) }) - .then((res) => res.json()); - if (data.successs) { - console.log('user added'); - } - } - setProgress('Registering PassKey...'); - const cco = parseCreationOptionsFromJSON({ - publicKey: { - challenge: challenge, - rp: { - name: "next-webauthn", - // TODO: Change - id: window.location.hostname - }, - user: { - id: window.crypto.randomUUID(), - name: email, - displayName: email.substring(0, email.indexOf("@")) - }, - pubKeyCredParams: [ - { alg: -7, type: "public-key" }, - { alg: -8, type: "public-key" }, - { alg: -257, type: "public-key" } - ], - timeout: 60000, - attestation: "direct", - authenticatorSelection: { - residentKey: "required", - userVerification: "required" + if (proceed) { + await fetch("/api/magicLink/login", + { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({email: email}) }); + if (isRegistered === undefined) { + const body = { email: email }; + const data = await fetch(`/api/couchdb/patients/new`, + { method: "POST", headers : {"Content-Type": "application/json"}, body: JSON.stringify(body) }) + .then((res) => res.json()); + if (data.successs) { + console.log('user added'); } } - }); - const credential_reg = await create(cco); - const result = await fetch("/api/auth/register", - { method: "POST", body: JSON.stringify({ email: email, credential: credential_reg }), headers: {"Content-Type": "application/json"} }); - if (result.ok) { - setProgress('Authentication using PassKey...') - const cro = parseRequestOptionsFromJSON({ + setProgress('Registering PassKey...'); + const cco = parseCreationOptionsFromJSON({ publicKey: { - challenge, + challenge: challenge, + rp: { + name: "next-webauthn", + // TODO: Change + id: window.location.hostname + }, + user: { + id: window.crypto.randomUUID(), + name: email, + displayName: email.substring(0, email.indexOf("@")) + }, + pubKeyCredParams: [ + { alg: -7, type: "public-key" }, + { alg: -8, type: "public-key" }, + { alg: -257, type: "public-key" } + ], timeout: 60000, - userVerification: "required", - rpId: window.location.hostname + attestation: "direct", + authenticatorSelection: { + residentKey: "required", + userVerification: "required" + } } }); - const credential_auth = await get(cro); - setRegister(true) - const result1 = await fetch("/api/auth/login", - { method: "POST", body: JSON.stringify({ email: email, credential: credential_auth }), headers: {"Content-Type": "application/json"} }); - if (result1.ok) { - if (authonly) { - await fetch(`/api/auth/logout`, { method: "POST" }); - setEmail(email); - } else { - const patient = await fetch("/api/couchdb/patients/" + email, - { method: "GET", headers: {"Content-Type": "application/json"} }) - .then((res) => res.json()); - const is_phr = objectPath.has(patient, 'phr'); - if (!is_phr) { - if (!clinical) { - router.push("/newPatient/" + email); - } else { - router.push("/requestAccess"); - } + const credential_reg = await create(cco); + const result = await fetch("/api/auth/register", + { method: "POST", body: JSON.stringify({ email: email, credential: credential_reg }), headers: {"Content-Type": "application/json"} }); + if (result.ok) { + setProgress('Authentication using PassKey...') + const cro = parseRequestOptionsFromJSON({ + publicKey: { + challenge, + timeout: 60000, + userVerification: "required", + rpId: window.location.hostname + } + }); + const credential_auth = await get(cro); + setRegister(true) + const result1 = await fetch("/api/auth/login", + { method: "POST", body: JSON.stringify({ email: email, credential: credential_auth }), headers: {"Content-Type": "application/json"} }); + if (result1.ok) { + if (authonly) { + await fetch(`/api/auth/logout`, { method: "POST" }); + setEmail(email); } else { - if (router.query.from) { - router.push(objectPath.get(router, 'query.from')); + const patient = await fetch("/api/couchdb/patients/" + email, + { method: "GET", headers: {"Content-Type": "application/json"} }) + .then((res) => res.json()); + const is_phr = objectPath.has(patient, 'phr'); + if (!is_phr) { + if (!clinical) { + router.push("/newPatient/" + email); + } else { + router.push("/requestAccess"); + } } else { - router.push("/myTrustee/dashboard"); + if (router.query.from) { + router.push(objectPath.get(router, 'query.from')); + } else { + router.push("/myTrustee/dashboard"); + } } } + } else { + setRegister(false) + const { message } = await result.json(); + setIsError(true); + setError(message); } } else { - setRegister(false) const { message } = await result.json(); - setIsError(true); setError(message); } } else { - const { message } = await result.json(); - setError(message); + setIsTimeout(true); } } else { setIsError(true); @@ -324,6 +333,7 @@ export default function Login({ challenge, clinical=false, authonly=false, clien {isChecking ? (Check your e-mail to verify...) : (
)} + {isTimeout ? (Verification Timed Out - Click on the link below to try again...) : (
)} {authonly || clinical ? ( New to Trustee? Create your Passkey ) : (