Clerk logo

Clerk Docs

Ctrl + K
Go to clerk.dev

OAuth Connections

Custom flow

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.

1
import React from "react";
2
import {
3
BrowserRouter,
4
Switch,
5
Route,
6
} from "react-router-dom";
7
import { OAuthStrategy } from "@clerk/types";
8
import {
9
ClerkProvider,
10
ClerkLoaded,
11
AuthenticateWithRedirectCallback,
12
UserButton,
13
useSignIn,
14
} from "@clerk/clerk-react";
15
16
function App() {
17
return (
18
// react-router-dom requires your app to be wrapped with a Router
19
<BrowserRouter>
20
<ClerkProvider frontendApi="{{fapi}}">
21
<Switch>
22
{/* Define a / route that displays the OAuth buttons */}
23
<Route path="/">
24
<SignedOut>
25
<SignInOAuthButtons />
26
</SignedOut>
27
<SignedIn>
28
<UserButton afterSignOutAllUrl="/" />
29
</SignedIn>
30
</Route>
31
32
{/* Define a /sso-callback route that handle the OAuth redirect flow */}
33
<Route path="/sso-callback">
34
<SSOCallback />
35
</Route>
36
</Switch>
37
</ClerkProvider>
38
</BrowserRouter>
39
);
40
}
41
42
function SSOCallback() {
43
// Handle the redirect flow by rendering the
44
// prebuilt AuthenticateWithRedirectCallback component.
45
// This is the final step in the custom OAuth flow
46
return <AuthenticateWithRedirectCallback />;
47
}
48
49
function SignInOAuthButtons() {
50
const { signIn } = useSignIn();
51
52
const signInWith = (strategy: OAuthStrategy) => {
53
return signIn.authenticateWithRedirect({
54
strategy,
55
redirectUrl: "/sso-callback",
56
redirectUrlComplete: "/",
57
});
58
};
59
60
// Render a button for each supported OAuth provider
61
// you want to add to your app
62
return (
63
<div>
64
<button onClick={() => signInWith("oauth_google")}>
65
Sign in with Google
66
</button>
67
</div>
68
);
69
}
70
71
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.

1
user
2
.createExternalAccount({ strategy: strategy, redirect_url: 'your-redirect-url' })
3
.then(externalAccount => {
4
// navigate to
5
// externalAccount.verification!.externalVerificationRedirectURL
6
})
7
.catch(err => {
8
// handle error
9
});

OAuth for Native applications

Clerk ensures that security critical nonces will be passed only to whitelisted URLs when the OAuth flow is complete in native browsers or webviews.

So for maximum security in your production instances, you need to whitelist your custom redirect URLs via Clerk Dashboard or Clerk Backend API.

Social login redirect URLs for native applications

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 we have "account transfers."

1
const { signIn, signUp } = window.Clerk.client;
2
3
// If the user has an account in your application, but does not yet
4
// have an oauth account connected, you can use the transfer method to
5
// forward that information.
6
7
const userExistsButNeedsToSignIn =
8
signUp.verifications.externalAccount.status === "transferable" &&
9
signUp.verifications.externalAccount.error?.code ===
10
"external_account_exists";
11
12
if (userExistsButNeedsToSignIn) {
13
const res = await signIn.create({ transfer: true });
14
if (res.status === "complete") {
15
window.Clerk.setActive({
16
session: res.createdSessionId,
17
});
18
}
19
}
20
21
// If the user has an existing oauth account but does not yet exist as
22
// a user in your app, you can use the transfer method to forward that
23
// information.
24
25
const userNeedsToBeCreated =
26
signIn.firstFactorVerification.status === "transferable";
27
28
if (userNeedsToBeCreated) {
29
const res = await signUp.create({
30
transfer: true,
31
});
32
if (res.status === "complete") {
33
window.Clerk.setActive({
34
session: res.createdSessionId,
35
});
36
}
37
}

Was this helpful?

Clerk © 2023