|
| 1 | +# Accounts Portal OAuth Consent Refactor Design |
| 2 | + |
| 3 | +> **For agentic workers:** This spec targets the accounts repo at `/Users/wobsoriano/Documents/projects/clerk/accounts`, not the javascript repo. |
| 4 | +
|
| 5 | +**Goal:** Replace the accounts portal's manual OAuth consent implementation with the new `<OAuthConsent />` component from `@clerk/nextjs/internal`, deleting all custom fetch utilities, hidden forms, and types in the process. |
| 6 | + |
| 7 | +**Context:** The `OAuthConsent` component (in `packages/ui`) now handles the full public path: it reads `client_id`, `redirect_uri`, and `scope` from the URL, fetches consent info via `clerk.oauthApplication.getConsentInfo`, renders scopes, and submits the consent form to `clerk.oauthApplication.buildConsentActionUrl`. The accounts portal's manual implementation duplicates all of this and can be deleted entirely. |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## Files Deleted |
| 12 | + |
| 13 | +- `components/oauth-consent/index.tsx` — manual fetch + `__internal_mountOAuthConsent` + hidden forms |
| 14 | +- `utils/oauth-consent.ts` — `getConsentInfoForOAuth` FAPI fetch utility |
| 15 | +- `types/OAuthConsent.ts` — `OAuthConsentInfo` type (only used by the above two files) |
| 16 | + |
| 17 | +## Files Modified |
| 18 | + |
| 19 | +### `types/index.ts` |
| 20 | + |
| 21 | +Remove the re-export of the deleted type file: |
| 22 | + |
| 23 | +```diff |
| 24 | +- export * from './OAuthConsent'; |
| 25 | + export * from './AccountPortalJSON'; |
| 26 | + export * from './constants'; |
| 27 | +``` |
| 28 | + |
| 29 | +`constants.ts` and `AccountPortalJSON.ts` are untouched — `DEV_BROWSER_JWT_MARKER` and `CLIENT_COOKIE_NAME` are still used elsewhere. |
| 30 | + |
| 31 | +### `pages/oauth-consent/[[...index]].tsx` |
| 32 | + |
| 33 | +Replace the entire file. `getServerSideProps` is removed — clerk-js handles `devBrowserJWT` and session auth automatically, and the new component reads all params from `window.location.search`. The referrer meta tag is kept (FAPI requires the `Origin` header on consent form POSTs). |
| 34 | + |
| 35 | +```tsx |
| 36 | +import React from 'react'; |
| 37 | +import Head from 'next/head'; |
| 38 | +import { OAuthConsent } from '@clerk/nextjs/internal'; |
| 39 | + |
| 40 | +export default function ConsentPage(): JSX.Element { |
| 41 | + return ( |
| 42 | + <div className='pageContainer'> |
| 43 | + <div className='componentContainer'> |
| 44 | + <Head> |
| 45 | + <meta |
| 46 | + name='referrer' |
| 47 | + content='origin' |
| 48 | + /> |
| 49 | + </Head> |
| 50 | + <OAuthConsent /> |
| 51 | + </div> |
| 52 | + </div> |
| 53 | + ); |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +### `e2e/features/oauth-consent.test.ts` |
| 58 | + |
| 59 | +Error message text changes to match the new component's wording. Happy path assertion changes from hidden inputs (old hidden forms) to the Allow/Deny buttons the new component renders. |
| 60 | + |
| 61 | +| Old assertion | New assertion | |
| 62 | +| --------------------------------------------------------- | ----------------------------------------- | |
| 63 | +| `'Error: Authorization failed: The client ID is missing'` | `'The client ID is missing.'` | |
| 64 | +| `'Error: Redirect URI not found'` | `'The redirect URI is missing.'` | |
| 65 | +| `input[name="consented"][value="true"]` | `button[name="consented"][value="true"]` | |
| 66 | +| `input[name="consented"][value="false"]` | `button[name="consented"][value="false"]` | |
| 67 | + |
| 68 | +### `e2e/unauthenticated/oauth-consent.test.ts` |
| 69 | + |
| 70 | +The old component returned an explicit `"Error: No session found"` div. The new component is wrapped with `withCoreUserGuard` which renders `null` for unauthenticated users. Update both tests to assert that the Allow button is not visible instead. |
| 71 | + |
| 72 | +```ts |
| 73 | +// Before |
| 74 | +await expect(page.getByText('Error: No session found')).toBeVisible(); |
| 75 | + |
| 76 | +// After |
| 77 | +await expect(page.getByRole('button', { name: 'Allow' })).not.toBeVisible(); |
| 78 | +``` |
| 79 | + |
| 80 | +--- |
| 81 | + |
| 82 | +## What Is Not Changing |
| 83 | + |
| 84 | +- `types/constants.ts` — stays, used by `utils/devBrowser.ts`, `utils/settings/environment.ts`, `utils/settings/accountPortal.ts` |
| 85 | +- `utils/devBrowser.ts` — stays, unrelated to OAuth consent |
| 86 | +- The page URL (`/oauth-consent`) and its Next.js route — unchanged |
| 87 | +- The referrer meta tag — kept |
| 88 | +- CSS class names (`pageContainer`, `componentContainer`) — unchanged |
0 commit comments