Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(clerk-expo): Deprecate useOAuth and introduce docs for useSSO #1908

Merged
merged 27 commits into from
Feb 4, 2025
Merged
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2e34970
Add bare draft for `useSSO` docs
LauraBeatris Jan 16, 2025
1e71a1a
Update snippets
LauraBeatris Jan 16, 2025
69c704d
update
victoriaxyz Jan 16, 2025
7f52af6
fix intros to code examples
victoriaxyz Jan 16, 2025
bcb5f9c
fix: Rollback guides for deprecated `useOAuth`
LauraBeatris Jan 17, 2025
2a15e4e
chore: Add deprecation warning
LauraBeatris Jan 17, 2025
bc2e51c
chore: Remove `redirectUrl` from properties
LauraBeatris Jan 17, 2025
bb12f81
chore: Improve description for `strategy` property
LauraBeatris Jan 17, 2025
ba4aed0
chore: Fix `useSSO` link
LauraBeatris Jan 17, 2025
36f8ba9
docs review
alexisintech Jan 17, 2025
11600ff
update oauth connections custom flow guide
alexisintech Jan 17, 2025
5c6d895
Update strategies types from OAuth-specific to general SSO (#1907)
LauraBeatris Jan 17, 2025
ba8abea
fix broken links
alexisintech Jan 17, 2025
cad401c
fix links
alexisintech Jan 21, 2025
6d51c33
Update `useSSO` with latest interface
LauraBeatris Jan 24, 2025
7187a29
Update deep link path for SSO callback
LauraBeatris Jan 24, 2025
17b642c
Update Expo overview to mention `useSSO`
LauraBeatris Jan 24, 2025
80081e5
Update snippets
LauraBeatris Jan 24, 2025
81107e2
Rollback OAuth connections changes
LauraBeatris Jan 24, 2025
d4c8941
Merge branch 'main' into laura/orgs-471-update-docs-for-clerkexpo
alexisintech Jan 30, 2025
0a5b335
docs review
alexisintech Jan 30, 2025
7d3fd2f
remove whitelist info from usesso doc
alexisintech Jan 31, 2025
01eef70
add callout; update todo
alexisintech Feb 4, 2025
1fff4b9
final docs review :fingerscrossed:
alexisintech Feb 4, 2025
0f6e969
Merge branch 'main' into laura/orgs-471-update-docs-for-clerkexpo
alexisintech Feb 4, 2025
5a8a7f9
Add reference for `authSessionResult`
LauraBeatris Feb 4, 2025
9c269f1
Fix linting and formatting
LauraBeatris Feb 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
update oauth connections custom flow guide
alexisintech authored and LauraBeatris committed Jan 28, 2025
commit 11600ffdbcfa90df5bef9fd74e50f56923bdbb1f
125 changes: 125 additions & 0 deletions docs/_partials/expo/sso-custom-flow.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<Tabs items={["With OAuth", "With SAML"]}>
<Tab>
The following example demonstrates how to create a custom SSO sign-in flow for [Google accounts](/docs/authentication/social-connections/google).

```tsx {{ filename: 'app/(auth)/sign-in.tsx', collapsible: true }}
import React, { useCallback, useEffect } from 'react'
import * as WebBrowser from 'expo-web-browser'
import * as Linking from 'expo-linking'
import { useSSO } from '@clerk/clerk-expo'
import { View, Button } from 'react-native'

export const useWarmUpBrowser = () => {
useEffect(() => {
// Preloads the browser for Android devices to reduce authentication load time
// See: https://docs.expo.dev/guides/authentication/#improving-user-experience
void WebBrowser.warmUpAsync()
return () => {
// Cleanup: closes browser when component unmounts
void WebBrowser.coolDownAsync()
}
}, [])
}

// Handle any pending authentication sessions
WebBrowser.maybeCompleteAuthSession()

export default function Page() {
useWarmUpBrowser()

const { startSSOFlow } = useSSO({ strategy: 'oauth_google' })

const onPress = useCallback(async () => {
try {
const { createdSessionId, setActive, signIn, signUp } = await startSSOFlow({
// URL to redirect to after successful authentication
// Must match the scheme defined in app.json
redirectUrl: Linking.createURL('/dashboard', { scheme: 'myapp' }),
})

// If sign in was successful, set the active session
if (createdSessionId) {
setActive!({ session: createdSessionId })
} else {
// Use `signIn` or `signUp` returned from `startSSOFlow`
// for next steps, such as MFA
}
} catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}, [])

return (
<View>
<Button title="Sign in with Google" onPress={onPress} />
</View>
)
}
```
</Tab>

<Tab>
The following example demonstrates how to create a custom SSO sign-in flow with [SAML](docs/authentication/enterprise-connections/overview#saml).

```tsx {{ filename: 'app/(auth)/sign-in.tsx', collapsible: true }}
import React, { useCallback, useEffect } from 'react'
import * as WebBrowser from 'expo-web-browser'
import * as Linking from 'expo-linking'
import { useSSO } from '@clerk/clerk-expo'
import { View, Button } from 'react-native'

export const useWarmUpBrowser = () => {
useEffect(() => {
// Preloads the browser for Android devices to reduce authentication load time
// See: https://docs.expo.dev/guides/authentication/#improving-user-experience
void WebBrowser.warmUpAsync()
return () => {
// Cleanup: closes browser when component unmounts
void WebBrowser.coolDownAsync()
}
}, [])
}

// Handle any pending authentication sessions
WebBrowser.maybeCompleteAuthSession()

export default function Page() {
useWarmUpBrowser()

const { startSSOFlow } = useSSO({ strategy: 'enterprise_sso', identifier: 'email' })

const onPress = useCallback(async () => {
try {
const { createdSessionId, setActive, signIn, signUp } = await startSSOFlow({
// URL to redirect to after successful authentication
// Must match the scheme defined in app.json
redirectUrl: Linking.createURL('/dashboard', { scheme: 'myapp' }),
// User identifier with a email domain that matches a enterprise connection
identifier: 'email',
})

// If sign in was successful, set the active session
if (createdSessionId) {
setActive!({ session: createdSessionId })
} else {
// Use `signIn` or `signUp` returned from `startSSOFlow`
// for next steps, such as MFA
}
} catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}, [])

return (
<View>
<Button title="Sign in with Google" onPress={onPress} />
</View>
)
}
```
</Tab>
</Tabs>
35 changes: 19 additions & 16 deletions docs/custom-flows/oauth-connections.mdx
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
---
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.
title: Build a custom flow for authenticating with SSO connections
description: Learn how to use the Clerk API to build a custom sign-up and sign-in flow that supports SSO connections.
---

<Include src="_partials/custom-flows-callout" />

## Before you start

You must configure your application instance through the Clerk Dashboard for the social connection(s) that you want to use, as described at [the top of the OAuth guide](/docs/authentication/social-connections/oauth#configuration).
You must configure your application instance through the Clerk Dashboard for the SSO connection that you want to use.

- For OAuth SSO, refer to [this guide](/docs/authentication/social-connections/oauth#enable-a-social-connection).
- For Enterprise SSO, refer to [this guide](/docs/authentication/enterprise-connections/overview).

## Create the sign-up and sign-in flow

When using OAuth, the sign-up and sign-in flows are equivalent.
When using SSO, the sign-up and sign-in flows are equivalent.

<Tabs items={["Next.js", "Expo", "iOS (beta)"]}>
<Tab>
A successful OAuth flow consists of the following steps:
A successful SSO flow consists of the following steps:

1. Start the OAuth flow by calling [`SignIn.authenticateWithRedirect(params)`](/docs/references/javascript/sign-in/authenticate-with#authenticate-with-redirect) or [`SignUp.authenticateWithRedirect(params)`](/docs/references/javascript/sign-up/authenticate-with#authenticate-with-redirect). Both of these methods require a `redirectUrl` param, which is the URL that the browser will be redirected to once the user authenticates with the OAuth provider.
1. Start the SSO flow by calling [`SignIn.authenticateWithRedirect(params)`](/docs/references/javascript/sign-in/authenticate-with#authenticate-with-redirect) or [`SignUp.authenticateWithRedirect(params)`](/docs/references/javascript/sign-up/authenticate-with#authenticate-with-redirect). Both of these methods require a `redirectUrl` param, which is the URL that the browser will be redirected to once the user authenticates with the OAuth provider.
1. Create a route at the URL that the `redirectUrl` param points to. The following example names this route `/sso-callback`. This route should call the [`Clerk.handleRedirectCallback()`](/docs/references/javascript/clerk/handle-navigation#handle-redirect-callback) method or simply render the prebuilt [`<AuthenticateWithRedirectCallback/>`](/docs/components/control/authenticate-with-callback) component.

The following example shows two files:

1. The sign-in page where the user can start the OAuth flow.
1. The SSO callback page where the OAuth flow is completed.
1. The sign-in page where the user can start the SSO flow.
1. The SSO callback page where the SSO flow is completed.

<CodeBlockTabs options={["Sign in page", "SSO callback page"]}>
```tsx {{ filename: 'app/sign-in/page.tsx' }}
@@ -90,7 +93,7 @@ When using OAuth, the sign-up and sign-in flows are equivalent.

### Build the flow

<Include src="_partials/expo/oauth-custom-flow" />
<Include src="_partials/expo/sso-custom-flow" />
</Tab>

<Tab>
@@ -159,9 +162,9 @@ When using OAuth, the sign-up and sign-in flows are equivalent.
</Tab>
</Tabs>

## OAuth account transfer flows
## SSO account transfer flows

It is common for users who are authenticating with OAuth to use a sign-in button when they mean to sign-up, and vice versa. For those cases, the `SignIn` and `SignUp` objects have a `transferable` status that indicates whether the user can be transferred to the other flow.
It is common for users who are authenticating with SSO to use a sign-in button when they mean to sign-up, and vice versa. For those cases, the `SignIn` and `SignUp` objects have a `transferable` status that indicates whether the user can be transferred to the other flow.

**If you would like to keep your sign-in and sign-up flows completely separate, then you can skip this section.**

@@ -176,7 +179,7 @@ The following example demonstrates how to handle these cases in your sign-in flo
import { OAuthStrategy } from '@clerk/types'
import { useSignIn, useSignUp } from '@clerk/nextjs'

export default function OauthSignIn() {
export default function SSOSignIn() {
const { signIn } = useSignIn()
const { signUp, setActive } = useSignUp()

@@ -194,7 +197,7 @@ The following example demonstrates how to handle these cases in your sign-in flo
if (!signIn || !signUp) return null

// If the user has an account in your application, but does not yet
// have an OAuth account connected to it, you can transfer the OAuth
// have an SSO account connected to it, you can transfer the SSO
// account to the existing user account.
const userExistsButNeedsToSignIn =
signUp.verifications.externalAccount.status === 'transferable' &&
@@ -210,9 +213,9 @@ The following example demonstrates how to handle these cases in your sign-in flo
}
}

// If the user has an OAuth account but does not yet
// If the user has an SSO account but does not yet
// have an account in your app, you can create an account
// for them using the OAuth information.
// for them using the SSO information.
const userNeedsToBeCreated = signIn.firstFactorVerification.status === 'transferable'

if (userNeedsToBeCreated) {
@@ -227,7 +230,7 @@ The following example demonstrates how to handle these cases in your sign-in flo
}
} else {
// If the user has an account in your application
// and has an OAuth account connected to it, you can sign them in.
// and has an SSO account connected to it, you can sign them in.
signInWith(strategy)
}
}
4 changes: 2 additions & 2 deletions docs/manifest.json
Original file line number Diff line number Diff line change
@@ -1697,8 +1697,8 @@
"href": "/docs/custom-flows/google-one-tap"
},
{
"title": "OAuth connections",
"href": "/docs/custom-flows/oauth-connections"
"title": "SSO connections",
"href": "/docs/custom-flows/sso-connections"
},
{
"title": "Enterprise connections",
134 changes: 1 addition & 133 deletions docs/references/expo/use-sso.mdx
Original file line number Diff line number Diff line change
@@ -69,136 +69,4 @@ It accepts the following parameters (`StartSSOFlowParams`):

## How to use the `useSSO()` hook

<Tabs items={["With OAuth", "With SAML"]}>
<Tab>
The following example demonstrates how to create a custom SSO sign-in flow for [Google accounts](/docs/authentication/social-connections/google).

The `useSSO()` hook is used to create a new SSO flow with the `oauth_google` strategy. When the user presses the sign-in button, the `startSSOFlow()` method is called. If sign-in is successful, `createdSessionId` is used to set the active session. The `redirectUrl` parameter is used to specify the URL to redirect to after the SSO flow is complete.

If sign-in isn't successful, the `signIn` or `signUp` method returned from `startSSOFlow()` can be used to further authenticate the user.

```tsx {{ filename: 'app/(auth)/sign-in.tsx', collapsible: true }}
import React, { useCallback, useEffect } from 'react'
import * as WebBrowser from 'expo-web-browser'
import * as Linking from 'expo-linking'
import { useSSO } from '@clerk/clerk-expo'
import { View, Button } from 'react-native'

export const useWarmUpBrowser = () => {
useEffect(() => {
// Preloads the browser for Android devices to reduce authentication load time
// See: https://docs.expo.dev/guides/authentication/#improving-user-experience
void WebBrowser.warmUpAsync()
return () => {
// Cleanup: closes browser when component unmounts
void WebBrowser.coolDownAsync()
}
}, [])
}

// Handle any pending authentication sessions
WebBrowser.maybeCompleteAuthSession()

export default function Page() {
useWarmUpBrowser()

const { startSSOFlow } = useSSO({ strategy: 'oauth_google' })

const onPress = useCallback(async () => {
try {
const { createdSessionId, setActive } = await startSSOFlow({
// Specify redirect URL after successful authentication
// Must match the scheme defined in app.json
redirectUrl: Linking.createURL('/dashboard', { scheme: 'myapp' }),
})

if (createdSessionId) {
// If sign in was successful, set the active session
setActive!({ session: createdSessionId })
} else {
// Use signIn or signUp returned from startSSOFlow
// for next steps, such as MFA
}
} catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}, [])

return (
<View>
<Button title="Sign in with Google" onPress={onPress} />
</View>
)
}
```
</Tab>

<Tab>
The following example demonstrates how to create a custom SSO sign-in flow with [SAML](docs/authentication/enterprise-connections/overview#saml).

The `useSSO()` hook is used to create a new SSO flow with the `enterprise_sso` strategy and the [`identifier`](/docs/authentication/configuration/sign-up-sign-in-options#identifier) parameter set to the user's email address. When the user presses the sign-in button, the `startSSOFlow()` method is called. If sign-in is successful, `createdSessionId` is used to set the active session. The `redirectUrl` parameter is used to specify the URL to redirect to after the SSO flow is complete.

If sign-in isn't successful, the `signIn` or `signUp` method returned from `startSSOFlow()` can be used to further authenticate the user.

```tsx {{ filename: 'app/(auth)/sign-in.tsx', collapsible: true }}
import React, { useCallback, useEffect } from 'react'
import * as WebBrowser from 'expo-web-browser'
import * as Linking from 'expo-linking'
import { useSSO } from '@clerk/clerk-expo'
import { View, Button } from 'react-native'

export const useWarmUpBrowser = () => {
useEffect(() => {
// Preloads the browser for Android devices to reduce authentication load time
// See: https://docs.expo.dev/guides/authentication/#improving-user-experience
void WebBrowser.warmUpAsync()
return () => {
// Cleanup: closes browser when component unmounts
void WebBrowser.coolDownAsync()
}
}, [])
}

// Handle any pending authentication sessions
WebBrowser.maybeCompleteAuthSession()

export default function Page() {
useWarmUpBrowser()

const { startSSOFlow } = useSSO({ strategy: 'enterprise_sso', identifier: 'email' })

const onPress = useCallback(async () => {
try {
const { createdSessionId, setActive } = await startSSOFlow({
// Specify redirect URL after successful authentication
// Must match the scheme defined in app.json
redirectUrl: Linking.createURL('/dashboard', { scheme: 'myapp' }),
// User identifier with a email domain that matches a enterprise connection
identifier: 'email',
})

if (createdSessionId) {
// If sign in was successful, set the active session
setActive!({ session: createdSessionId })
} else {
// Use signIn or signUp returned from startOAuthFlow
// for next steps, such as MFA
}
} catch (err) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(err, null, 2))
}
}, [])

return (
<View>
<Button title="Sign in with Google" onPress={onPress} />
</View>
)
}
```
</Tab>
</Tabs>
<Include src="_partials/expo/sso-custom-flow" />