No invitation token found.
- } + const handleSubmit = async (formData: FormData) => { + const firstName = formData.get('firstName') as string + const lastName = formData.get('lastName') as string + const password = formData.get('password') as string - // Handle submission of the sign-up form - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault() - - if (!isLoaded) return - - try { - if (!token) return null - - // Create a new sign-up with the supplied invitation token. - // Make sure you're also passing the ticket strategy. - // After the below call, the user's email address will be - // automatically verified because of the invitation token. - const signUpAttempt = await signUp.create({ - strategy: 'ticket', - ticket: token, - firstName, - lastName, - password, + await signUp.ticket({ + firstName, + lastName, + password, + }) + if (signUp.status === 'complete') { + await signUp.finalize({ + navigate: () => { + router.push('/') + }, }) - - // If the sign-up was completed, set the session to active - if (signUpAttempt.status === 'complete') { - await setActive({ session: signUpAttempt.createdSessionId }) - } else { - // If the sign-up status is not complete, check why. User may need to - // complete further steps. - console.error(JSON.stringify(signUpAttempt, null, 2)) - } - } catch (err) { - console.error(JSON.stringify(err, null, 2)) } } + if (signUp.status === 'complete' || isSignedIn) { + return null + } + return ( <>No invitation token found.
+ } + + // Handle submission of the sign-up form + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + + if (!isLoaded) return + + try { + if (!token) return null + + // Create a new sign-up with the supplied invitation token. + // Make sure you're also passing the ticket strategy. + // After the below call, the user's email address will be + // automatically verified because of the invitation token. + const signUpAttempt = await signUp.create({ + strategy: 'ticket', + ticket: token, + firstName, + lastName, + password, + }) + + // If the sign-up was completed, set the session to active + if (signUpAttempt.status === 'complete') { + await setActive({ session: signUpAttempt.createdSessionId }) + } else { + // If the sign-up status is not complete, check why. User may need to + // complete further steps. + console.error(JSON.stringify(signUpAttempt, null, 2)) + } + } catch (err) { + console.error(JSON.stringify(err, null, 2)) + } + } + + return ( + <> +Error: {error}
+ +Check your email and visit the link that was sent to you.
+ +The email link verification failed.
+ Sign up +The email link has expired.
+ Sign up ++ You must complete the email link sign-up on the same device and browser that you started + it on. +
+ Sign up +Successfully signed up. Return to the original tab to continue.
+Error: {error}
+ +Check your email and visit the link that was sent to you.
+ +The email link verification failed.
+ Sign in +The email link has expired.
+ Sign in ++ You must complete the email link sign-in on the same device and browser as you started it + on. +
+ Sign in +Successfully signed in. Return to the original tab to continue.
+Passkeys:
+Passkey updated: {success ? 'Yes' : 'No'}
+ > + ) +} +``` + +## Delete user passkeys + +To delete a user's passkey from your Clerk app, you must call the [`delete()`](/docs/reference/javascript/types/passkey-resource#delete) method of the passkey object, as shown in the following example: + +```tsx {{ filename: 'components/DeletePasskeyUI.tsx' }} +export function DeletePasskeyUI() { + const { user } = useUser() + const { passkeys } = user + + const passkeyToDeleteId = useRefPasskeys:
+Passkey deleted: {success ? 'Yes' : 'No'}
+ > + ) +} +``` diff --git a/docs/guides/development/custom-flows/authentication/oauth-connections.mdx b/docs/guides/development/custom-flows/authentication/oauth-connections.mdx index 4a722abfd6..c24a8bc025 100644 --- a/docs/guides/development/custom-flows/authentication/oauth-connections.mdx +++ b/docs/guides/development/custom-flows/authentication/oauth-connections.mdx @@ -1,6 +1,7 @@ --- title: Build a custom flow for authenticating with OAuth connections description: Learn how to use the Clerk API to build a custom sign-up and sign-in flow that supports OAuth connections. +sdk: nextjs, react, expo, js-frontend, react-router, tanstack-react-start ---