From 951fd8d8cf9b86bb3cabbcc68823109e513a5172 Mon Sep 17 00:00:00 2001 From: Peter Date: Mon, 16 Mar 2026 15:36:53 -0400 Subject: [PATCH 1/7] extracted login --- src/AuthProvider.tsx | 2 ++ src/utils.ts | 77 +++++++++++++++++++++++++++++++++++++++++++- src/views/Login.tsx | 49 +++++++++------------------- 3 files changed, 94 insertions(+), 34 deletions(-) diff --git a/src/AuthProvider.tsx b/src/AuthProvider.tsx index 651bce6..dde9b00 100644 --- a/src/AuthProvider.tsx +++ b/src/AuthProvider.tsx @@ -42,6 +42,7 @@ export interface AuthContextType { credentials: Credential[]; updateCredential: (credential: Credential) => Promise; deleteCredential: (credentialId: string) => Promise; + fetchWithAuth(input: string, init?: RequestInit): Promise; } export interface Credential { @@ -221,6 +222,7 @@ export const AuthProvider: React.FC = ({ credentials, updateCredential, deleteCredential, + fetchWithAuth, }} > diff --git a/src/utils.ts b/src/utils.ts index 6cdda15..0f17dba 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,6 @@ import parsePhoneNumberFromString from 'libphonenumber-js'; - +import { startAuthentication } from '@simplewebauthn/browser'; +import { createFetchWithAuth } from './fetchWithAuth'; /** * isValidEmail * @@ -101,3 +102,77 @@ export function parseUserAgent() { return { platform, browser, deviceInfo }; } + +export const login = async ( + fetchWithAuth: (input: string, init?: RequestInit) => Promise, + identifier: string, + passkeyAvailable: boolean +) => { + // setFormErrors(''); + + const response = await fetchWithAuth(`/login`, { + method: 'POST', + body: JSON.stringify({ identifier, passkeyAvailable }), + }); + + // if (!response.ok) { + // setFormErrors('Failed to send login link. Please try again.'); + // return; + // } + + // if (!passkeyAvailable) { + // setShowFallbackOptions(true); + // return; + // } + + try { + await handlePasskeyLogin(fetchWithAuth); + } catch (err) { + console.error('Passkey login failed', err); + // setShowFallbackOptions(true); + } +}; + +const handlePasskeyLogin = async ( + fetchWithAuth: (input: string, init?: RequestInit) => Promise +) => { + try { + const response = await fetchWithAuth(`/webAuthn/login/start`, { + method: 'POST', + }); + + if (!response.ok) { + console.error('Something went wrong getting webauthn options'); + return; + } + + const options = await response.json(); + const credential = await startAuthentication({ optionsJSON: options }); + + const verificationResponse = await fetchWithAuth(`/webAuthn/login/finish`, { + method: 'POST', + body: JSON.stringify({ assertionResponse: credential }), + }); + + if (!verificationResponse.ok) { + console.error('Failed to verify passkey'); + } + + const verificationResult = await verificationResponse.json(); + + // let them handle the below + // if (verificationResult.message === 'Success') { + // if (verificationResult.mfaLogin) { + // navigate('/mfaLogin'); + // return; + // } + // await validateToken(); + // navigate('/'); + // return; + // } else { + // console.error('Passkey login failed:', verificationResult.message); + // } + } catch (error) { + console.error('Passkey login error:', error); + } +}; diff --git a/src/views/Login.tsx b/src/views/Login.tsx index 489dad1..5cc61ee 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -4,7 +4,7 @@ import PhoneInputWithCountryCode from '@/components/phoneInput'; import { useInternalAuth } from '@/context/InternalAuthContext'; import React, { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; - +import { login } from '../utils'; import styles from '@/styles/login.module.css'; import { isPasskeySupported, isValidEmail, isValidPhoneNumber } from '../utils'; import { createFetchWithAuth } from '@/fetchWithAuth'; @@ -12,7 +12,7 @@ import AuthFallbackOptions from '@/components/AuthFallbackOptions'; const Login: React.FC = () => { const navigate = useNavigate(); - const { apiHost, hasSignedInBefore, mode: authMode } = useAuth(); + const { apiHost, hasSignedInBefore, mode: authMode, fetchWithAuth } = useAuth(); const { validateToken } = useInternalAuth(); const [identifier, setIdentifier] = useState(''); const [email, setEmail] = useState(''); @@ -25,15 +25,17 @@ const Login: React.FC = () => { const [passkeyAvailable, setPasskeyAvailable] = useState(false); const [showFallbackOptions, setShowFallbackOptions] = useState(false); - const fetchWithAuth = createFetchWithAuth({ - authMode, - authHost: apiHost, - }); + // const fetchWithAuth = createFetchWithAuth({ + // authMode, + // authHost: apiHost, + // }); useEffect(() => { async function checkSupport() { const supported = await isPasskeySupported(); + // console.log('checking passkey', supported); setPasskeyAvailable(supported); + console.log('checking passkey', supported); } checkSupport(); @@ -102,32 +104,6 @@ const Login: React.FC = () => { } }; - const login = async () => { - setFormErrors(''); - - const response = await fetchWithAuth(`/login`, { - method: 'POST', - body: JSON.stringify({ identifier, passkeyAvailable }), - }); - - if (!response.ok) { - setFormErrors('Failed to send login link. Please try again.'); - return; - } - - if (!passkeyAvailable) { - setShowFallbackOptions(true); - return; - } - - try { - await handlePasskeyLogin(); - } catch (err) { - console.error('Passkey login failed', err); - setShowFallbackOptions(true); - } - }; - const register = async () => { setFormErrors(''); @@ -198,7 +174,14 @@ const Login: React.FC = () => { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); - if (mode === 'login') login(); + if (mode === 'login') { + if (passkeyAvailable) { + const res = login(fetchWithAuth, identifier, passkeyAvailable); + } else { + setShowFallbackOptions(true); + console.log(setShowFallbackOptions); + } + } if (mode === 'register') register(); }; From 3d89cae79044fb0577d5a842f274eab40587f697 Mon Sep 17 00:00:00 2001 From: Peter Date: Mon, 16 Mar 2026 23:57:58 -0400 Subject: [PATCH 2/7] abstracted out handlePassKey --- src/AuthProvider.tsx | 80 +++++++++++++++++++++++- src/AuthRoutes.tsx | 2 +- src/components/MagicLinkSent.tsx | 6 +- src/utils.ts | 59 +++++++++--------- src/views/Login.tsx | 104 ++++++++++++++++--------------- src/views/VerifyMagicLink.tsx | 2 +- 6 files changed, 168 insertions(+), 85 deletions(-) diff --git a/src/AuthProvider.tsx b/src/AuthProvider.tsx index dde9b00..3129c6f 100644 --- a/src/AuthProvider.tsx +++ b/src/AuthProvider.tsx @@ -1,4 +1,5 @@ import { InternalAuthProvider } from '@/context/InternalAuthContext'; +import { startAuthentication } from '@simplewebauthn/browser'; import React, { createContext, ReactNode, @@ -42,7 +43,8 @@ export interface AuthContextType { credentials: Credential[]; updateCredential: (credential: Credential) => Promise; deleteCredential: (credentialId: string) => Promise; - fetchWithAuth(input: string, init?: RequestInit): Promise; + login: (identifier: string, passkeyAvailable: boolean) => Promise; + handlePasskeyLogin: () => Promise; } export interface Credential { @@ -98,6 +100,79 @@ export const AuthProvider: React.FC = ({ authHost: apiHost, }); + const login = async ( + identifier: string, + passkeyAvailable: boolean + ): Promise => { + const response = await fetchWithAuth(`/login`, { + method: 'POST', + body: JSON.stringify({ identifier, passkeyAvailable }), + }); + if (!passkeyAvailable) { + // setShowFallbackOptions(true); + console.log('stopped early'); + return response; + } + + try { + // await handlePasskeyLogin(); + // Another ticket? + return response; + } catch (err) { + console.error('Passkey login failed', err); + // setShowFallbackOptions(true); + return response; + } + }; + + const handlePasskeyLogin = async () => { + try { + const response = await fetchWithAuth(`/webAuthn/login/start`, { + method: 'POST', + }); + + if (!response.ok) { + console.error('Something went wrong getting webauthn options'); + return 'Failed'; + } + + const options = await response.json(); + const credential = await startAuthentication({ optionsJSON: options }); + + const verificationResponse = await fetchWithAuth(`/webAuthn/login/finish`, { + method: 'POST', + body: JSON.stringify({ assertionResponse: credential }), + }); + + if (!verificationResponse.ok) { + console.error('Failed to verify passkey'); + } + + const verificationResult = await verificationResponse.json(); + + if (verificationResult.message === 'Success') { + if (verificationResult.mfaLogin) { + // navigate('/mfaLogin'); + // need to return "Success" + + return 'Success'; + } + await validateToken(); + // navigate('/'); + // need to return validateToken response/message + return 'Token'; + } else { + console.error('Passkey login failed:', verificationResult.message); + // return failed + return 'Failed'; + } + } catch (error) { + console.error('Passkey login error:', error); + // throw error? + return 'Error'; + } + }; + const logout = useCallback(async () => { if (user) { try { @@ -222,7 +297,8 @@ export const AuthProvider: React.FC = ({ credentials, updateCredential, deleteCredential, - fetchWithAuth, + login, + handlePasskeyLogin, }} > diff --git a/src/AuthRoutes.tsx b/src/AuthRoutes.tsx index e1c0506..5318d59 100644 --- a/src/AuthRoutes.tsx +++ b/src/AuthRoutes.tsx @@ -16,7 +16,7 @@ export const AuthRoutes = () => ( } /> } /> } /> - } /> + } /> } /> ); diff --git a/src/components/MagicLinkSent.tsx b/src/components/MagicLinkSent.tsx index 1f13c35..5b6565e 100644 --- a/src/components/MagicLinkSent.tsx +++ b/src/components/MagicLinkSent.tsx @@ -32,7 +32,7 @@ const MagicLinkSent: React.FC = () => { const resend = async () => { if (cooldown > 0) return; - await fetchWithAuth(`/magic-link`, { + await fetchWithAuth(`/magiclinks`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -47,7 +47,7 @@ const MagicLinkSent: React.FC = () => { channel.onmessage = async event => { if (event.data?.type === 'MAGIC_LINK_AUTH_SUCCESS') { - const response = await fetchWithAuth(`/magic-link/check`, { + const response = await fetchWithAuth(`/magiclinks/check`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -68,7 +68,7 @@ const MagicLinkSent: React.FC = () => { useEffect(() => { const interval = setInterval(async () => { try { - const response = await fetchWithAuth(`/magic-link/check`, { + const response = await fetchWithAuth(`/magiclinks/check`, { method: 'GET', headers: { 'Content-Type': 'application/json', diff --git a/src/utils.ts b/src/utils.ts index 0f17dba..b8f4ac5 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -103,35 +103,36 @@ export function parseUserAgent() { return { platform, browser, deviceInfo }; } -export const login = async ( - fetchWithAuth: (input: string, init?: RequestInit) => Promise, - identifier: string, - passkeyAvailable: boolean -) => { - // setFormErrors(''); - - const response = await fetchWithAuth(`/login`, { - method: 'POST', - body: JSON.stringify({ identifier, passkeyAvailable }), - }); - - // if (!response.ok) { - // setFormErrors('Failed to send login link. Please try again.'); - // return; - // } - - // if (!passkeyAvailable) { - // setShowFallbackOptions(true); - // return; - // } - - try { - await handlePasskeyLogin(fetchWithAuth); - } catch (err) { - console.error('Passkey login failed', err); - // setShowFallbackOptions(true); - } -}; +// export const login = async ( +// fetchWithAuth: (input: string, init?: RequestInit) => Promise, +// identifier: string, +// passkeyAvailable: boolean +// ) => { +// // setFormErrors(''); + +// const response = await fetchWithAuth(`/login`, { +// method: 'POST', +// body: JSON.stringify({ identifier, passkeyAvailable }), +// }); +// console.log('response from /login', response); +// // if (!response.ok) { +// // setFormErrors('Failed to send login link. Please try again.'); +// // return; +// // } + +// if (!passkeyAvailable) { +// // setShowFallbackOptions(true); +// console.log +// return; +// } + +// try { +// await handlePasskeyLogin(fetchWithAuth); +// } catch (err) { +// console.error('Passkey login failed', err); +// // setShowFallbackOptions(true); +// } +// }; const handlePasskeyLogin = async ( fetchWithAuth: (input: string, init?: RequestInit) => Promise diff --git a/src/views/Login.tsx b/src/views/Login.tsx index 5cc61ee..591c10b 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -4,7 +4,6 @@ import PhoneInputWithCountryCode from '@/components/phoneInput'; import { useInternalAuth } from '@/context/InternalAuthContext'; import React, { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { login } from '../utils'; import styles from '@/styles/login.module.css'; import { isPasskeySupported, isValidEmail, isValidPhoneNumber } from '../utils'; import { createFetchWithAuth } from '@/fetchWithAuth'; @@ -12,7 +11,13 @@ import AuthFallbackOptions from '@/components/AuthFallbackOptions'; const Login: React.FC = () => { const navigate = useNavigate(); - const { apiHost, hasSignedInBefore, mode: authMode, fetchWithAuth } = useAuth(); + const { + apiHost, + hasSignedInBefore, + mode: authMode, + login, + handlePasskeyLogin, + } = useAuth(); const { validateToken } = useInternalAuth(); const [identifier, setIdentifier] = useState(''); const [email, setEmail] = useState(''); @@ -25,10 +30,10 @@ const Login: React.FC = () => { const [passkeyAvailable, setPasskeyAvailable] = useState(false); const [showFallbackOptions, setShowFallbackOptions] = useState(false); - // const fetchWithAuth = createFetchWithAuth({ - // authMode, - // authHost: apiHost, - // }); + const fetchWithAuth = createFetchWithAuth({ + authMode, + authHost: apiHost, + }); useEffect(() => { async function checkSupport() { @@ -63,46 +68,46 @@ const Login: React.FC = () => { return isValidEmail(email) && isValidPhoneNumber(phone); }; - const handlePasskeyLogin = async () => { - try { - const response = await fetchWithAuth(`/webAuthn/login/start`, { - method: 'POST', - }); - - if (!response.ok) { - console.error('Something went wrong getting webauthn options'); - return; - } - - const options = await response.json(); - const credential = await startAuthentication({ optionsJSON: options }); - - const verificationResponse = await fetchWithAuth(`/webAuthn/login/finish`, { - method: 'POST', - body: JSON.stringify({ assertionResponse: credential }), - }); - - if (!verificationResponse.ok) { - console.error('Failed to verify passkey'); - } - - const verificationResult = await verificationResponse.json(); - - if (verificationResult.message === 'Success') { - if (verificationResult.mfaLogin) { - navigate('/mfaLogin'); - return; - } - await validateToken(); - navigate('/'); - return; - } else { - console.error('Passkey login failed:', verificationResult.message); - } - } catch (error) { - console.error('Passkey login error:', error); - } - }; + // const handlePasskeyLogin = async () => { + // try { + // const response = await fetchWithAuth(`/webAuthn/login/start`, { + // method: 'POST', + // }); + + // if (!response.ok) { + // console.error('Something went wrong getting webauthn options'); + // return; + // } + + // const options = await response.json(); + // const credential = await startAuthentication({ optionsJSON: options }); + + // const verificationResponse = await fetchWithAuth(`/webAuthn/login/finish`, { + // method: 'POST', + // body: JSON.stringify({ assertionResponse: credential }), + // }); + + // if (!verificationResponse.ok) { + // console.error('Failed to verify passkey'); + // } + + // const verificationResult = await verificationResponse.json(); + + // if (verificationResult.message === 'Success') { + // if (verificationResult.mfaLogin) { + // navigate('/mfaLogin'); + // return; + // } + // await validateToken(); + // navigate('/'); + // return; + // } else { + // console.error('Passkey login failed:', verificationResult.message); + // } + // } catch (error) { + // console.error('Passkey login error:', error); + // } + // }; const register = async () => { setFormErrors(''); @@ -136,7 +141,7 @@ const Login: React.FC = () => { const sendMagicLink = async () => { try { - const response = await fetchWithAuth(`/magic-link`, { + const response = await fetchWithAuth(`/magiclinks`, { method: 'GET', }); @@ -145,7 +150,7 @@ const Login: React.FC = () => { return; } - navigate('/magic-link-sent'); + navigate('/magiclinks-sent'); } catch (err) { console.error(err); setFormErrors('Failed to send magic link.'); @@ -175,8 +180,9 @@ const Login: React.FC = () => { e.preventDefault(); if (mode === 'login') { + const res = login(identifier, passkeyAvailable); if (passkeyAvailable) { - const res = login(fetchWithAuth, identifier, passkeyAvailable); + console.log('herro'); } else { setShowFallbackOptions(true); console.log(setShowFallbackOptions); diff --git a/src/views/VerifyMagicLink.tsx b/src/views/VerifyMagicLink.tsx index 2488a77..9473733 100644 --- a/src/views/VerifyMagicLink.tsx +++ b/src/views/VerifyMagicLink.tsx @@ -21,7 +21,7 @@ const VerifyMagicLink: React.FC = () => { useEffect(() => { const verify = async () => { - const response = await fetchWithAuth(`/magic-link/verify/${token}`, { + const response = await fetchWithAuth(`/magiclinks/verify/${token}`, { method: 'GET', headers: { 'Content-Type': 'application/json', From 564f955cd516b9c5c08deb14932e6a96b577f4b3 Mon Sep 17 00:00:00 2001 From: Peter Date: Mon, 23 Mar 2026 18:06:17 -0400 Subject: [PATCH 3/7] changed magiclinks back to magic-links --- src/components/MagicLinkSent.tsx | 6 +++--- src/views/Login.tsx | 4 ++-- src/views/VerifyMagicLink.tsx | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/MagicLinkSent.tsx b/src/components/MagicLinkSent.tsx index 5b6565e..296f427 100644 --- a/src/components/MagicLinkSent.tsx +++ b/src/components/MagicLinkSent.tsx @@ -32,7 +32,7 @@ const MagicLinkSent: React.FC = () => { const resend = async () => { if (cooldown > 0) return; - await fetchWithAuth(`/magiclinks`, { + await fetchWithAuth(`/magic-links`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -47,7 +47,7 @@ const MagicLinkSent: React.FC = () => { channel.onmessage = async event => { if (event.data?.type === 'MAGIC_LINK_AUTH_SUCCESS') { - const response = await fetchWithAuth(`/magiclinks/check`, { + const response = await fetchWithAuth(`/magic-links/check`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -68,7 +68,7 @@ const MagicLinkSent: React.FC = () => { useEffect(() => { const interval = setInterval(async () => { try { - const response = await fetchWithAuth(`/magiclinks/check`, { + const response = await fetchWithAuth(`/magic-links/check`, { method: 'GET', headers: { 'Content-Type': 'application/json', diff --git a/src/views/Login.tsx b/src/views/Login.tsx index 591c10b..52defdb 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -141,7 +141,7 @@ const Login: React.FC = () => { const sendMagicLink = async () => { try { - const response = await fetchWithAuth(`/magiclinks`, { + const response = await fetchWithAuth(`/magic-links`, { method: 'GET', }); @@ -150,7 +150,7 @@ const Login: React.FC = () => { return; } - navigate('/magiclinks-sent'); + navigate('/magic-links-sent'); } catch (err) { console.error(err); setFormErrors('Failed to send magic link.'); diff --git a/src/views/VerifyMagicLink.tsx b/src/views/VerifyMagicLink.tsx index 9473733..66a00ef 100644 --- a/src/views/VerifyMagicLink.tsx +++ b/src/views/VerifyMagicLink.tsx @@ -21,7 +21,7 @@ const VerifyMagicLink: React.FC = () => { useEffect(() => { const verify = async () => { - const response = await fetchWithAuth(`/magiclinks/verify/${token}`, { + const response = await fetchWithAuth(`/magic-links/verify/${token}`, { method: 'GET', headers: { 'Content-Type': 'application/json', From ab921eb289ef980a80b7675523bf594590ba4972 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 25 Mar 2026 00:02:45 -0400 Subject: [PATCH 4/7] updated endpoints to singular, and moved handlepasskey --- src/AuthProvider.tsx | 17 ++++++----------- src/components/MagicLinkSent.tsx | 6 +++--- src/views/Login.tsx | 7 ++++++- src/views/VerifyMagicLink.tsx | 26 +++++++++++++++----------- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/AuthProvider.tsx b/src/AuthProvider.tsx index 3129c6f..5100609 100644 --- a/src/AuthProvider.tsx +++ b/src/AuthProvider.tsx @@ -44,7 +44,7 @@ export interface AuthContextType { updateCredential: (credential: Credential) => Promise; deleteCredential: (credentialId: string) => Promise; login: (identifier: string, passkeyAvailable: boolean) => Promise; - handlePasskeyLogin: () => Promise; + handlePasskeyLogin: () => Promise; } export interface Credential { @@ -131,11 +131,6 @@ export const AuthProvider: React.FC = ({ method: 'POST', }); - if (!response.ok) { - console.error('Something went wrong getting webauthn options'); - return 'Failed'; - } - const options = await response.json(); const credential = await startAuthentication({ optionsJSON: options }); @@ -154,22 +149,22 @@ export const AuthProvider: React.FC = ({ if (verificationResult.mfaLogin) { // navigate('/mfaLogin'); // need to return "Success" - - return 'Success'; + // can just return a bool, if success true otherwise false anywhere else + return true; } await validateToken(); // navigate('/'); // need to return validateToken response/message - return 'Token'; + return false; } else { console.error('Passkey login failed:', verificationResult.message); // return failed - return 'Failed'; + return false; } } catch (error) { console.error('Passkey login error:', error); // throw error? - return 'Error'; + return false; } }; diff --git a/src/components/MagicLinkSent.tsx b/src/components/MagicLinkSent.tsx index 296f427..1f13c35 100644 --- a/src/components/MagicLinkSent.tsx +++ b/src/components/MagicLinkSent.tsx @@ -32,7 +32,7 @@ const MagicLinkSent: React.FC = () => { const resend = async () => { if (cooldown > 0) return; - await fetchWithAuth(`/magic-links`, { + await fetchWithAuth(`/magic-link`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -47,7 +47,7 @@ const MagicLinkSent: React.FC = () => { channel.onmessage = async event => { if (event.data?.type === 'MAGIC_LINK_AUTH_SUCCESS') { - const response = await fetchWithAuth(`/magic-links/check`, { + const response = await fetchWithAuth(`/magic-link/check`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -68,7 +68,7 @@ const MagicLinkSent: React.FC = () => { useEffect(() => { const interval = setInterval(async () => { try { - const response = await fetchWithAuth(`/magic-links/check`, { + const response = await fetchWithAuth(`/magic-link/check`, { method: 'GET', headers: { 'Content-Type': 'application/json', diff --git a/src/views/Login.tsx b/src/views/Login.tsx index 52defdb..5e28bd9 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -141,7 +141,7 @@ const Login: React.FC = () => { const sendMagicLink = async () => { try { - const response = await fetchWithAuth(`/magic-links`, { + const response = await fetchWithAuth(`/magic-link`, { method: 'GET', }); @@ -181,8 +181,13 @@ const Login: React.FC = () => { if (mode === 'login') { const res = login(identifier, passkeyAvailable); + if (passkeyAvailable) { console.log('herro'); + const passkeyResult = await handlePasskeyLogin(); + if (passkeyResult) { + navigate('/'); + } } else { setShowFallbackOptions(true); console.log(setShowFallbackOptions); diff --git a/src/views/VerifyMagicLink.tsx b/src/views/VerifyMagicLink.tsx index 66a00ef..5f5989e 100644 --- a/src/views/VerifyMagicLink.tsx +++ b/src/views/VerifyMagicLink.tsx @@ -21,17 +21,21 @@ const VerifyMagicLink: React.FC = () => { useEffect(() => { const verify = async () => { - const response = await fetchWithAuth(`/magic-links/verify/${token}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }); - - if (!response.ok) { - console.error('Failed to verify token'); - setError('Failed to verify token'); - return; + try { + const response = await fetchWithAuth(`/magic-link/verify/${token}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + console.error('Failed to verify token'); + setError('Failed to verify token'); + return; + } + } catch (error) { + console.log(error); } const channel = new BroadcastChannel('seamless-auth'); From e5b44fa9a74362680ba407f1e25d01ec95dcc107 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 27 Mar 2026 21:03:12 -0400 Subject: [PATCH 5/7] cleaned and removed lint warnings --- src/AuthProvider.tsx | 3 -- src/utils.ts | 77 -------------------------------------------- src/views/Login.tsx | 11 ++----- 3 files changed, 2 insertions(+), 89 deletions(-) diff --git a/src/AuthProvider.tsx b/src/AuthProvider.tsx index 5100609..27b58bc 100644 --- a/src/AuthProvider.tsx +++ b/src/AuthProvider.tsx @@ -110,13 +110,10 @@ export const AuthProvider: React.FC = ({ }); if (!passkeyAvailable) { // setShowFallbackOptions(true); - console.log('stopped early'); return response; } try { - // await handlePasskeyLogin(); - // Another ticket? return response; } catch (err) { console.error('Passkey login failed', err); diff --git a/src/utils.ts b/src/utils.ts index b8f4ac5..2f155b8 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,4 @@ import parsePhoneNumberFromString from 'libphonenumber-js'; -import { startAuthentication } from '@simplewebauthn/browser'; -import { createFetchWithAuth } from './fetchWithAuth'; /** * isValidEmail * @@ -102,78 +100,3 @@ export function parseUserAgent() { return { platform, browser, deviceInfo }; } - -// export const login = async ( -// fetchWithAuth: (input: string, init?: RequestInit) => Promise, -// identifier: string, -// passkeyAvailable: boolean -// ) => { -// // setFormErrors(''); - -// const response = await fetchWithAuth(`/login`, { -// method: 'POST', -// body: JSON.stringify({ identifier, passkeyAvailable }), -// }); -// console.log('response from /login', response); -// // if (!response.ok) { -// // setFormErrors('Failed to send login link. Please try again.'); -// // return; -// // } - -// if (!passkeyAvailable) { -// // setShowFallbackOptions(true); -// console.log -// return; -// } - -// try { -// await handlePasskeyLogin(fetchWithAuth); -// } catch (err) { -// console.error('Passkey login failed', err); -// // setShowFallbackOptions(true); -// } -// }; - -const handlePasskeyLogin = async ( - fetchWithAuth: (input: string, init?: RequestInit) => Promise -) => { - try { - const response = await fetchWithAuth(`/webAuthn/login/start`, { - method: 'POST', - }); - - if (!response.ok) { - console.error('Something went wrong getting webauthn options'); - return; - } - - const options = await response.json(); - const credential = await startAuthentication({ optionsJSON: options }); - - const verificationResponse = await fetchWithAuth(`/webAuthn/login/finish`, { - method: 'POST', - body: JSON.stringify({ assertionResponse: credential }), - }); - - if (!verificationResponse.ok) { - console.error('Failed to verify passkey'); - } - - const verificationResult = await verificationResponse.json(); - - // let them handle the below - // if (verificationResult.message === 'Success') { - // if (verificationResult.mfaLogin) { - // navigate('/mfaLogin'); - // return; - // } - // await validateToken(); - // navigate('/'); - // return; - // } else { - // console.error('Passkey login failed:', verificationResult.message); - // } - } catch (error) { - console.error('Passkey login error:', error); - } -}; diff --git a/src/views/Login.tsx b/src/views/Login.tsx index 5e28bd9..8ab67c8 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -1,7 +1,5 @@ -import { startAuthentication } from '@simplewebauthn/browser'; import { useAuth } from '@/AuthProvider'; import PhoneInputWithCountryCode from '@/components/phoneInput'; -import { useInternalAuth } from '@/context/InternalAuthContext'; import React, { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import styles from '@/styles/login.module.css'; @@ -18,7 +16,6 @@ const Login: React.FC = () => { login, handlePasskeyLogin, } = useAuth(); - const { validateToken } = useInternalAuth(); const [identifier, setIdentifier] = useState(''); const [email, setEmail] = useState(''); const [mode, setMode] = useState<'login' | 'register'>('register'); @@ -38,9 +35,7 @@ const Login: React.FC = () => { useEffect(() => { async function checkSupport() { const supported = await isPasskeySupported(); - // console.log('checking passkey', supported); setPasskeyAvailable(supported); - console.log('checking passkey', supported); } checkSupport(); @@ -150,7 +145,7 @@ const Login: React.FC = () => { return; } - navigate('/magic-links-sent'); + navigate('/magiclinks-sent'); } catch (err) { console.error(err); setFormErrors('Failed to send magic link.'); @@ -180,17 +175,15 @@ const Login: React.FC = () => { e.preventDefault(); if (mode === 'login') { - const res = login(identifier, passkeyAvailable); + login(identifier, passkeyAvailable); if (passkeyAvailable) { - console.log('herro'); const passkeyResult = await handlePasskeyLogin(); if (passkeyResult) { navigate('/'); } } else { setShowFallbackOptions(true); - console.log(setShowFallbackOptions); } } if (mode === 'register') register(); From a7abb954aab1410b44544c9a9b9c5535fdc44b7a Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 1 Apr 2026 19:51:30 -0400 Subject: [PATCH 6/7] removed extra comments per change requested --- src/AuthProvider.tsx | 19 +------------------ src/views/Login.tsx | 45 ++------------------------------------------ 2 files changed, 3 insertions(+), 61 deletions(-) diff --git a/src/AuthProvider.tsx b/src/AuthProvider.tsx index 27b58bc..8d9b224 100644 --- a/src/AuthProvider.tsx +++ b/src/AuthProvider.tsx @@ -108,18 +108,8 @@ export const AuthProvider: React.FC = ({ method: 'POST', body: JSON.stringify({ identifier, passkeyAvailable }), }); - if (!passkeyAvailable) { - // setShowFallbackOptions(true); - return response; - } - try { - return response; - } catch (err) { - console.error('Passkey login failed', err); - // setShowFallbackOptions(true); - return response; - } + return response; }; const handlePasskeyLogin = async () => { @@ -144,23 +134,16 @@ export const AuthProvider: React.FC = ({ if (verificationResult.message === 'Success') { if (verificationResult.mfaLogin) { - // navigate('/mfaLogin'); - // need to return "Success" - // can just return a bool, if success true otherwise false anywhere else return true; } await validateToken(); - // navigate('/'); - // need to return validateToken response/message return false; } else { console.error('Passkey login failed:', verificationResult.message); - // return failed return false; } } catch (error) { console.error('Passkey login error:', error); - // throw error? return false; } }; diff --git a/src/views/Login.tsx b/src/views/Login.tsx index 8ab67c8..ea26f3d 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -63,47 +63,6 @@ const Login: React.FC = () => { return isValidEmail(email) && isValidPhoneNumber(phone); }; - // const handlePasskeyLogin = async () => { - // try { - // const response = await fetchWithAuth(`/webAuthn/login/start`, { - // method: 'POST', - // }); - - // if (!response.ok) { - // console.error('Something went wrong getting webauthn options'); - // return; - // } - - // const options = await response.json(); - // const credential = await startAuthentication({ optionsJSON: options }); - - // const verificationResponse = await fetchWithAuth(`/webAuthn/login/finish`, { - // method: 'POST', - // body: JSON.stringify({ assertionResponse: credential }), - // }); - - // if (!verificationResponse.ok) { - // console.error('Failed to verify passkey'); - // } - - // const verificationResult = await verificationResponse.json(); - - // if (verificationResult.message === 'Success') { - // if (verificationResult.mfaLogin) { - // navigate('/mfaLogin'); - // return; - // } - // await validateToken(); - // navigate('/'); - // return; - // } else { - // console.error('Passkey login failed:', verificationResult.message); - // } - // } catch (error) { - // console.error('Passkey login error:', error); - // } - // }; - const register = async () => { setFormErrors(''); @@ -175,9 +134,9 @@ const Login: React.FC = () => { e.preventDefault(); if (mode === 'login') { - login(identifier, passkeyAvailable); + const loginRes = await login(identifier, passkeyAvailable); - if (passkeyAvailable) { + if (loginRes.ok && passkeyAvailable) { const passkeyResult = await handlePasskeyLogin(); if (passkeyResult) { navigate('/'); From b23a10c06aa96e92aa274b4ea0d96ef4592d1b3c Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 1 Apr 2026 20:30:20 -0400 Subject: [PATCH 7/7] changed console.logs to errors --- src/views/VerifyMagicLink.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/VerifyMagicLink.tsx b/src/views/VerifyMagicLink.tsx index 5f5989e..d5c5279 100644 --- a/src/views/VerifyMagicLink.tsx +++ b/src/views/VerifyMagicLink.tsx @@ -35,7 +35,7 @@ const VerifyMagicLink: React.FC = () => { return; } } catch (error) { - console.log(error); + console.error(error); } const channel = new BroadcastChannel('seamless-auth');