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:

  1. Start the OAuth flow by calling SignIn.authenticateWithRedirect(params) or SignUp.authenticateWithRedirect(params). Note that 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.
  2. Create a route at the URL redirectUrl points, typically /sso-callback, that calls the Clerk.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 {
} from "react-router-dom";
import { OAuthStrategy } from "@clerk/types";
import {
} 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
      <ClerkProvider publishableKey={publishableKey}>
          {/* Define a / route that displays the OAuth buttons */}
          <Route path="/">
              <SignInOAuthButtons />
              <UserButton afterSignOutAllUrl="/" />
           {/* Define a /sso-callback route that handle the OAuth redirect flow */}
          <Route path="/sso-callback">
            <SSOCallback />

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({
      redirectUrl: "/sso-callback",
      redirectUrlComplete: "/",

  // Render a button for each supported OAuth provider
  // you want to add to your app
  return (
      <button onClick={() => signInWith("oauth_google")}>
        Sign in with Google

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.

  .createExternalAccount({ strategy: strategy, redirectUrl: '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 or the Clerk Backend API.

To allowlist a redirect URL via the Clerk Dashboard, go to User & Authentication > Social Connections. On the Social Connections page, click on the *Settings tab and add your redirect URL to the Redirect URLs list.

The 'Social Connections' page of the Clerk Dashboard, with the 'Settings' tab selected. The 'Settings' tab shows a section titled 'allowlist for mobile OAuth redirect' and has an input for redirect URLs.

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 ===

if (userExistsButNeedsToSignIn) {
  const res = await signIn.create({ transfer: true });
  if (res.status === "complete") {
      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") {
      session: res.createdSessionId,


What did you think of this content?