# Use OAuth for Single Sign-On (SSO)

You've likely seen buttons like "Sign in with Google" or "Sign in with GitHub" countless times. Clerk supports both sides of this experience:

1. **Sign in with [Other App]** – Let users sign in to your Clerk app using their existing credentials from social providers like Google, Facebook, or GitHub.
2. **Sign in with [Your App]** – Let users sign in to _other_ apps using their Clerk credentials from your app. In this case, _your app_ becomes the identity provider.

These features help you streamline authentication for your users, whether they're signing into your Clerk-powered app or accessing external apps with their Clerk credentials. This guide covers both options in detail and provides links to additional resources where applicable.

## Option 1: Sign in with [Other App]

This feature allows users to sign up or sign in to your Clerk app using their existing credentials from popular social providers (also known as Identity Providers, or IdPs) like Google, Facebook, or GitHub. For example, if you enable GitHub as a social provider, then a user can sign in to your Clerk app by selecting GitHub as an option and authenticating with their GitHub account credentials.

Refer to the appropriate provider's [guide](https://clerk.com/docs/guides/configure/auth-strategies/social-connections/overview.md) for implementation details.

## Option 2: Sign in with [Your App]

Clerk can be configured as an OAuth 2.0 and OpenID Connect (OIDC) Identity Provider (IdP) to enable Single Sign-On (SSO) with other clients that support these protocols. This allows users to authenticate to third-party applications using their Clerk credentials, enabling user information sharing between your Clerk app and OAuth clients.

It's the reverse of Option 1: instead of using an external provider to authenticate into your Clerk app, users use their Clerk credentials to sign in to external apps.

### What you can build

With Clerk as an IdP, you can:

- **Integrate with third-party tools** – Let users authenticate into platforms like Notion, Retool, or custom internal tools using their credentials from your app.
- **Build a developer ecosystem** – Enable partners or third-party developers to offer "Sign in with [Your App]" in their applications.
- **Support AI agents and automation** – Allow [MCP servers or AI tools](https://clerk.com/docs/guides/ai/overview.md) to authenticate users through your app.
- **Implement enterprise SSO** – Provide B2B customers with centralized identity management using OpenID Connect.

### How it works: The big picture

When you configure Clerk as an IdP, you're registering a third-party app as an OAuth client in your Clerk Dashboard. You then provide that client with credentials (a Client ID and Client Secret) that it uses to redirect users to Clerk for authentication. After the user authenticates with Clerk, they're redirected back to the third-party app with the authorization they need.

## Configure Clerk as an IdP

The following steps walk you through setting up Clerk as an OAuth provider for a third-party client.

Here is the general flow to set up your Clerk instance as an OAuth provider:

1. Create a connection or integration in the client.
2. Create an OAuth application in Clerk and configure it.
3. Obtain the Client ID and Client Secret from Clerk.
4. Enter these credentials into the client to complete the integration.

### Create a connection or integration in the client

Ensure you have setup a new connection within the third-party client or tool where your users will authenticate. As part of this process, you'll be provided a **redirect URL** that you'll need to use in the next step.

### Create a Clerk OAuth application

To create a Clerk OAuth application:

1. In the Clerk Dashboard, navigate to the [**OAuth applications**](https://dashboard.clerk.com/~/oauth-applications) page.
2. Select **Add OAuth application**. A modal will open.
3. Complete the following fields:
   - `Name` - Helps you identify your application.
   - `Scopes` - The scopes that you would like to leverage. Learn more about [OAuth scopes currently supported by Clerk](https://clerk.com/docs/guides/configure/auth-strategies/oauth/how-clerk-implements-oauth.md#scopes).
4. Select **Add**. A modal will open with your **Client Secret**. For security reasons, Clerk does not store your Client Secret and cannot show it to you again, so **ensure that you copy it and store it somewhere secure**, like an environment variable.
5. You'll be redirected to your app's settings page. Under **Application credentials**, save the **Client ID** somewhere secure as you'll need it later.
6. In the **Redirect URIs** field, add the redirect URI/URL provided by your client [in the earlier step](#create-a-connection-or-integration-in-the-client). This is the URL that Clerk will redirect to after the user has authenticated.

To learn more about the other OAuth application configuration settings, like **Dynamic client registration**, see the [dedicated guide](https://clerk.com/docs/guides/configure/auth-strategies/oauth/how-clerk-implements-oauth.md).

### Configure your client

Once you have set up a Clerk OAuth app, you'll need to configure a few settings in your client to establish the connection. All the necessary information can be found in your Clerk OAuth app's settings, starting with two key parameters:

- **Client ID**: Public identifier of your Clerk OAuth app.
- **Client Secret**: Confidential secret used to authenticate your Clerk OAuth app.

Both of these are available in your Clerk [OAuth app's settings in the Clerk Dashboard](https://dashboard.clerk.com/~/oauth-applications). They need to be entered into your client's setup interface to complete the integration. Once completed, your users will be able to authenticate into the third-party app using their Clerk credentials.

Other available settings that may be useful include:

- **Discovery URL**: Used by the client to retrieve the configuration data of the Clerk OAuth app.
- **Authorize URL**: Used by the client to request authorization from your user.
- **Token URL**: Used by the client to exchange an authorization code for an access token and a refresh token.
- **User Info URL**: Used by the client to retrieve additional user data upon authentication.

## Get additional user information with the OAuth 2.0 flow

After a user has successfully completed an OAuth 2.0 flow, you can retrieve additional user information from Clerk's [`/oauth/userinfo`](https://clerk.com/docs/reference/frontend-api/tag/oauth2-identify-provider/post/oauth/userinfo){{ target: '_blank' }} endpoint. When making the request to this endpoint, you must include the OAuth access token in the `Authorization` header.

This example is written for Next.js App Router **but can be adapted for any framework/language**. It assumes the OAuth flow has already been completed and that you have obtained an access token from Clerk.

filename: app/api/userinfo/route.ts
```tsx
import { NextResponse } from 'next/server'

export async function GET() {
  // Assume you already have the access token available here
  const accessToken = 'YOUR_ACCESS_TOKEN_HERE'

  try {
    // Your Frontend API URL can be found on the API keys page in the Clerk Dashboard
    // https://dashboard.clerk.com/~/api-keys
    const response = await fetch(`${process.env.CLERK_FRONTEND_API_URL}/oauth/userinfo`, {
      headers: {
        // Include the access token as a Bearer token in the Authorization header
        Authorization: `Bearer ${accessToken}`,
      },
    })

    if (!response.ok) {
      const errorData = await response.json()
      return NextResponse.json(errorData, { status: response.status })
    }

    const data = await response.json()
    return NextResponse.json(data)
  } catch (error: unknown) {
    return NextResponse.json(
      { error: 'Failed to fetch user info', details: (error as Error).message },
      { status: 500 },
    )
  }
}
```

**Example response**

```json
{
  "object": "oauth_user_info",
  "instance_id": "string",
  "user_id": "string",
  "sub": "string",
  "email": "string",
  "email_verified": true,
  "family_name": "string",
  "given_name": "string",
  "name": "string",
  "username": "string",
  "preferred_username": "string",
  "picture": "string",
  "public_metadata": {},
  "private_metadata": {},
  "unsafe_metadata": {},
  "org_id": "string",
  "org_name": "string",
  "org_slug": "string"
}
```

> The `org_id`, `org_name`, and `org_slug` properties are only present in the response when Organizations are enabled, the `user:org:read` scope was granted, and an Organization is associated with the token. See [Organizations and OAuth](https://clerk.com/docs/guides/configure/auth-strategies/oauth/how-clerk-implements-oauth.md#organizations-and-oauth).

The `/oauth/userinfo` endpoint provides the following user properties, depending on the granted scopes:

| Property             | Description                                                                                                                                                                                              |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `user_id`            | The ID of the user                                                                                                                                                                                       |
| `sub`                | The ID of the user                                                                                                                                                                                       |
| `given_name`         | The user's first name                                                                                                                                                                                    |
| `family_name`        | The user's last name                                                                                                                                                                                     |
| `name`               | The user's full name                                                                                                                                                                                     |
| `picture`            | The user's avatar URL                                                                                                                                                                                    |
| `preferred_username` | The user's username                                                                                                                                                                                      |
| `email`              | The user's primary email address                                                                                                                                                                         |
| `email_verified`     | Whether the user's primary email address is verified                                                                                                                                                     |
| `public_metadata`    | The user's public metadata                                                                                                                                                                               |
| `private_metadata`   | The user's private metadata                                                                                                                                                                              |
| `unsafe_metadata`    | The user's unsafe metadata                                                                                                                                                                               |
| `org_id`             | The ID of an Organization to which the user belongs. See [Organizations and OAuth](https://clerk.com/docs/guides/configure/auth-strategies/oauth/how-clerk-implements-oauth.md#organizations-and-oauth). |
| `org_name`           | The name of the user's Organization                                                                                                                                                                      |
| `org_slug`           | The slug for the user's Organization                                                                                                                                                                     |

### Get token information

For validating access tokens or refresh tokens and retrieving additional token metadata, Clerk provides a standard OAuth 2.0 [Token Introspection Endpoint](https://datatracker.ietf.org/doc/html/rfc7662) at [`/oauth/token_info`](https://clerk.com/docs/reference/frontend-api/tag/oauth2-identify-provider/post/oauth/token_info){{ target: '_blank' }}.

The endpoint returns detailed token information such as if the token is still active, the Client ID, and the granted scopes.

> This endpoint is protected. You must provide your Clerk Client ID and Client Secret credentials to authenticate.

This example is written for Next.js App Router **but can be adapted for any framework/language**. It demonstrates how to call the `/oauth/token_info` endpoint, assuming you already have the access token and refresh token available.

filename: app/api/tokeninfo/route.ts
```tsx
import { NextRequest, NextResponse } from 'next/server'

// Assume you already have the access token and refresh token.
// You can get your OAuth app's Client ID and Client Secret from the Clerk Dashboard:
// https://dashboard.clerk.com/~/oauth-applications
// In production, store these as environment variables loaded from `process.env.*`
// rather than hardcoded here.
const tokens = {
  accessToken: 'YOUR_ACCESS_TOKEN_HERE',
  refreshToken: 'YOUR_REFRESH_TOKEN_HERE',
}
const clientId = 'YOUR_CLIENT_ID_HERE'
const clientSecret = 'YOUR_CLIENT_SECRET_HERE'

export async function POST(req: NextRequest) {
  try {
    const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64')
    // Your Frontend API URL can be found on the API keys page in the Clerk Dashboard
    // https://dashboard.clerk.com/~/api-keys
    const response = await fetch(`${process.env.CLERK_FRONTEND_API_URL}/oauth/token_info`, {
      method: 'POST',
      headers: {
        Authorization: `Basic ${credentials}`,
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: new URLSearchParams({
        // Include the refresh token in the body
        token: tokens.refreshToken,
      }),
    })

    if (!response.ok) {
      return NextResponse.json({ error: 'Failed to fetch token info' }, { status: response.status })
    }

    const data = await response.json()
    return NextResponse.json(data)
  } catch (error) {
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}
```

**Example response**

```json
{
  "active": true,
  "client_id": "string",
  "iat": 0,
  "scope": "string",
  "sub": "string",
  "org_id": "string"
}
```

> The `org_id` property is only present in the response when Organizations are enabled, the `user:org:read` scope was granted, and an Organization is associated with the token. See [Organizations and OAuth](https://clerk.com/docs/guides/configure/auth-strategies/oauth/how-clerk-implements-oauth.md#organizations-and-oauth).

## Get additional user information with the OAuth 2.0 flow using the OpenID Connect (OIDC) protocol

> Not all third-party apps expect or use OIDC. However, this feature was designed with OIDC compatibility in mind, which is why it's included in this guide. Ensure that your integration target supports OIDC before proceeding.

In order to enable OIDC in your OAuth flow, you can follow the same steps outlined above, but ensure to select the `openid` scope when configuring your OAuth app in the Clerk Dashboard. This scope triggers OIDC and instructs the authorization server to issue an ID token alongside your access token.

You'll also need to include this `openid` scope in the query parameters of your authorization endpoint when initiating the OAuth flow. For example:

```http
GET /oauth/authorize?
  client_id=x&
  response_type=code&
  state=y&
  code_challenge=z&
  redirect_uri=a&
  scope=openid%20profile%20email&...
Host: clerk.<INSERT_YOUR_APP_DOMAIN>.com
```

Once a user successfully authenticates using the OIDC flow, you'll receive:

- An access token
- A **refresh token**
- An **ID token**

The **ID token** is a JWT (JSON Web Token) that contains standard JWT claims as defined in [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519), as well as additional custom claims that represent the authenticated user's profile information. The token is signed using your instance's private key.

You must verify the signature on the ID token before using any of the user information it contains. This will require your instance's public key. You can find your instance's public key by loading your Frontend API URL with `/.well-known/jwks.json` appended to it. For example:

- `https://verb-noun-00.clerk.accounts.dev/.well-known/jwks.json` for a development environment.
- `https://clerk.<INSERT_YOUR_APP_DOMAIN>.com/.well-known/jwks.json` for a production environment.

Here is an example verifying the ID token using the [`jsonwebtoken`](https://www.npmjs.com/package/jsonwebtoken) library in a production environment:

```js
const jwt = require('jsonwebtoken')

function verifyIdToken(idToken) {
  jwt.verify(
    idToken,
    PUBLIC_KEY,
    {
      algorithms: ['RS256'],
      issuer: 'https://clerk.<YOUR_APP_DOMAIN>.com',
      audience: '<YOUR_CLIENT_ID>',
    },
    (err, decoded) => {
      if (err) {
        console.error('Token verification failed:', err)
      } else {
        console.log('Token is valid:', decoded)
      }
    },
  )
}
```

The ID token includes the following standard claims:

| Standard claim | Description                                                          |
| -------------- | -------------------------------------------------------------------- |
| `iss`          | The issuer of the token, which matches your Clerk Frontend API URL   |
| `sub`          | The subject of the token, which matches the authenticated user ID    |
| `aud`          | The intended audience of the token, which matches the used Client ID |
| `exp`          | The expiration time of the token                                     |
| `iat`          | The time at which the token was issued                               |
| `jti`          | A unique identifier for the token                                    |

Depending on the granted scopes, the ID token can include the following additional claims:

| Additional claim     | Description                                                                                                                                                                                              |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `nonce`              | The nonce provided and used during the request                                                                                                                                                           |
| `family_name`        | The user's last name                                                                                                                                                                                     |
| `given_name`         | The user's first name                                                                                                                                                                                    |
| `name`               | The user's full name                                                                                                                                                                                     |
| `picture`            | The user's avatar URL                                                                                                                                                                                    |
| `preferred_username` | The user's username                                                                                                                                                                                      |
| `email`              | The user's primary email address                                                                                                                                                                         |
| `email_verified`     | Whether the user's primary email address is verified                                                                                                                                                     |
| `public_metadata`    | The user's public metadata                                                                                                                                                                               |
| `private_metadata`   | The user's private metadata                                                                                                                                                                              |
| `unsafe_metadata`    | The user's unsafe metadata                                                                                                                                                                               |
| `org_id`             | The ID of an Organization to which the user belongs. See [Organizations and OAuth](https://clerk.com/docs/guides/configure/auth-strategies/oauth/how-clerk-implements-oauth.md#organizations-and-oauth). |

---

## Sitemap

[Overview of all docs pages](https://clerk.com/docs/llms.txt)
