OAuth connections
In case one of our standard OAuth integration methods doesn't cover your needs, you can leverage the Clerk SDK to build completely custom OAuth flows.
You still need to configure your instance through the Clerk Dashboard, as described at the top of the OAuth guide.
When using OAuth, the sign-in and sign-up are equivalent. A successful OAuth flow consists of the following steps:
- Start the OAuth flow by calling
SignIn.authenticateWithRedirect(params)
orSignUp.authenticateWithRedirect(params)
. Note that both of these methods require aredirectUrl
param, which is the URL that the browser will be redirected to once the user authenticates with the OAuth provider. - Create a route at the URL
redirectUrl
points, typically/sso-callback
, that calls theClerk.handleRedirectCallback()
or simply renders the prebuilt<AuthenticateWithRedirectCallback/>
component.
The React example below uses react-router-dom
to define the required route. For NextJS apps, you only need to create a pages/sso-callback
file.
import React from "react"; import { BrowserRouter, Switch, Route, } from "react-router-dom"; import { OAuthStrategy } from "@clerk/types"; import { ClerkProvider, ClerkLoaded, AuthenticateWithRedirectCallback, UserButton, useSignIn, } from "@clerk/clerk-react"; const publishableKey = process.env.REACT_APP_CLERK_PUBLISHABLE_KEY; function App() { return ( // react-router-dom requires your app to be wrapped with a Router <BrowserRouter> <ClerkProvider publishableKey={publishableKey}> <Switch> {/* Define a / route that displays the OAuth buttons */} <Route path="/"> <SignedOut> <SignInOAuthButtons /> </SignedOut> <SignedIn> <UserButton afterSignOutAllUrl="/" /> </SignedIn> </Route> {/* Define a /sso-callback route that handle the OAuth redirect flow */} <Route path="/sso-callback"> <SSOCallback /> </Route> </Switch> </ClerkProvider> </BrowserRouter> ); } function SSOCallback() { // Handle the redirect flow by rendering the // prebuilt AuthenticateWithRedirectCallback component. // This is the final step in the custom OAuth flow return <AuthenticateWithRedirectCallback />; } function SignInOAuthButtons() { const { signIn } = useSignIn(); const signInWith = (strategy: OAuthStrategy) => { return signIn.authenticateWithRedirect({ strategy, redirectUrl: "/sso-callback", redirectUrlComplete: "/", }); }; // Render a button for each supported OAuth provider // you want to add to your app return ( <div> <button onClick={() => signInWith("oauth_google")}> Sign in with Google </button> </div> ); } export default App;
To initiate an OAuth flow for a user that is already signed in, you can use the user.createExternalAccount(params)
method, where user
is a reference to the currently signed in user.
user .createExternalAccount({ strategy: strategy, redirect_url: 'your-redirect-url' }) .then(externalAccount => { // navigate to // externalAccount.verification!.externalVerificationRedirectURL }) .catch(err => { // handle error });
OAuth for React Native applications
With Clerk, you can add OAuth flows in your React Native or Expo applications.
Clerk ensures that security critical nonces will be passed only to allowlisted URLs when the OAuth flow is complete in native browsers or webviews.
So for maximum security in your production instances, you need to allowlist your custom redirect URLs via the Clerk Dashboard(opens in a new tab) or the Clerk Backend API(opens in a new tab).
To allowlist a redirect URL via the Clerk Dashboard, go to User & Authentication > Social Connections(opens in a new tab). On the Social Connections page, click on the *Settings tab and add your redirect URL to the Redirect URLs list.
OAuth account transfer flow
When a user initiates an OAuth verification during sign-in or sign-up, it may sometimes be necessary to move the verification between the two flows.
For example, if someone already has an account, and tries to go through the sign up flow with the same OAuth account, they can't perform a successful sign-up again. Or, if someone attempts to sign in with their OAuth credentials but does not yet have an account, they won't be signed in to the account. For these scenarios, Clerk provides "account transfers."
// Get sign-in and sign-up objects in the OAuth callback page const { signIn, signUp } = window.Clerk.client; // If the user has an account in your application, but does not yet // have an oauth account connected, you can use the transfer method to // forward that information. const userExistsButNeedsToSignIn = signUp.verifications.externalAccount.status === "transferable" && signUp.verifications.externalAccount.error?.code === "external_account_exists"; if (userExistsButNeedsToSignIn) { const res = await signIn.create({ transfer: true }); if (res.status === "complete") { window.Clerk.setActive({ session: res.createdSessionId, }); } } // If the user has an existing oauth account but does not yet exist as // a user in your app, you can use the transfer method to forward that // information. const userNeedsToBeCreated = signIn.firstFactorVerification.status === "transferable"; if (userNeedsToBeCreated) { const res = await signUp.create({ transfer: true, }); if (res.status === "complete") { window.Clerk.setActive({ session: res.createdSessionId, }); } }