# useOAuthConsent()

The `useOAuthConsent()` hook loads OAuth consent metadata for an authenticated user. You can use it to build a custom OAuth consent page that fetches the OAuth application's name, logo, URL, requested scopes, and related loading state.

Unlike the [<OAuthConsent />](https://clerk.com/docs/nextjs/reference/components/authentication/oauth-consent.md) component, this hook doesn't read values from the current URL. Pass the `oauthClientId` explicitly. Optionally pass `scope` if you want Clerk to scope the request to a specific space-delimited scope string, and pass `redirectUri` when you need a public-suffix-aware [redirectDomain](https://clerk.com/docs/nextjs/reference/types/oauth-consent-info.md) for presenting the redirect destination.

Building a low-level custom consent flow is security-sensitive. For setup guidance, redirect URL presentation requirements, and a safer prebuilt component option, see [Set up a custom OAuth consent page](https://clerk.com/docs/nextjs/guides/configure/auth-strategies/oauth/custom-consent-page.md).

> Pages that host OAuth consent flows must set the referrer policy to `strict-origin-when-cross-origin`. This ensures the cross-origin `POST` request to FAPI includes the `Origin` header and Clerk can validate the CSRF token.

## Parameters

`useOAuthConsent()` accepts a single object with the following properties:

| Property                                          | Type      | Description                                                                                                      |
| ------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------- |
| <a id="enabled"></a> `enabled?`                   | `boolean` | If `true`, a request will be triggered when the hook is mounted and the user is signed in. Defaults to `true`.   |
| <a id="keeppreviousdata"></a> `keepPreviousData?` | `boolean` | If `true`, the previous data will be kept in the cache until new data is fetched. Defaults to `true`.            |
| <a id="oauthclientid"></a> `oauthClientId`        | `string`  | The OAuth `client_id` from the authorize request. The hook is disabled when this value is empty or omitted.      |
| <a id="redirecturi"></a> `redirectUri?`           | `string`  | The redirect URI from the authorize request. When provided, the backend returns a PSL-resolved `redirectDomain`. |
| <a id="scope"></a> `scope?`                       | `string`  | A space-delimited scope string from the authorize request.                                                       |

## Returns

| Property                             | Type                                                                                                                              | Description                                                                                            |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| <a id="data"></a> `data`             | <code>undefined | <a href="https://clerk.com/docs/nextjs/reference/types/oauth-consent-info.md">OAuthConsentInfo</a></code>       | The OAuth consent screen metadata returned by Clerk, or `undefined` before the first successful fetch. |
| <a id="error"></a> `error`           | <code>null | <a href="https://clerk.com/docs/nextjs/reference/types/clerk-api-response-error.md">ClerkAPIResponseError</a></code> | Any error that occurred during the data fetch, or `null` if no error occurred.                         |
| <a id="isfetching"></a> `isFetching` | `boolean`                                                                                                                         | Whether any request is still in flight, including background updates.                                  |
| <a id="isloading"></a> `isLoading`   | `boolean`                                                                                                                         | Whether the initial consent metadata fetch is still in progress.                                       |

## Example

The following example demonstrates how to use the `useOAuthConsent()` hook to fetch OAuth consent metadata and build a custom consent form. In this example, `client_id` and `redirect_uri` are read from the current URL and passed to the hook, and the form submits to the URL generated by the [buildConsentActionUrl()](https://clerk.com/docs/nextjs/reference/types/oauth-application.md) method. The example intentionally focuses on the hook API; production consent pages must also clearly present the redirect destination and other security context described in [Set up a custom OAuth consent page](https://clerk.com/docs/nextjs/guides/configure/auth-strategies/oauth/custom-consent-page.md).

filename: app/oauth-consent/custom-consent-form.tsx
```tsx
'use client'

import { useClerk, useOAuthConsent } from '@clerk/nextjs'
import { useSearchParams } from 'next/navigation'

export function CustomConsentForm() {
  const clerk = useClerk()
  const params = useSearchParams()
  const clientId = params.get('client_id') ?? ''
  const redirectUri = params.get('redirect_uri') ?? ''
  const scope = params.get('scope') ?? undefined

  const { data, isLoading, error } = useOAuthConsent({
    oauthClientId: clientId,
    scope,
    redirectUri,
  })

  if (!clientId) return <div>Missing OAuth client ID.</div>
  if (isLoading) return <div>Loading...</div>
  if (error || !data) return <div>Something went wrong.</div>

  const actionUrl = clerk.oauthApplication.buildConsentActionUrl({ clientId })

  return (
    <form method="POST" action={actionUrl}>
      <h1>{data.oauthApplicationName} wants access to your account</h1>
      <p>
        Redirect destination:{' '}
        <strong>{data.redirectDomain || new URL(redirectUri).hostname}</strong>
      </p>
      <ul>
        {data.scopes.map((scope) => (
          <li key={scope.scope}>{scope.description ?? scope.scope}</li>
        ))}
      </ul>

      <button type="submit" name="consented" value="false">
        Deny
      </button>
      <button type="submit" name="consented" value="true">
        Allow
      </button>

      {/* Forward the original OAuth parameters, except fields set by this form. */}
      {Array.from(params.entries())
        .filter(([key]) => key !== 'consented' && key !== 'organization_id')
        .map(([key, value], index) => (
          <input key={`${key}:${index}`} type="hidden" name={key} value={value} />
        ))}
    </form>
  )
}
```

filename: app/oauth-consent/page.tsx
```tsx
import { CustomConsentForm } from './custom-consent-form'
import type { Metadata } from 'next'
import { Suspense } from 'react'

export const metadata: Metadata = {
  referrer: 'strict-origin-when-cross-origin',
}

export default function Page() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <CustomConsentForm />
    </Suspense>
  )
}
```

---

## Sitemap

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