Update Connection provider path (#21678)

## Before

After connecting to oAuth linear app connection:

<img width="1512" height="851" alt="image"
src="https://github.com/user-attachments/assets/39b94aaf-648f-46a6-8f4d-deb1cb7e22c5"
/>

## After

Redirects to Linear

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21678?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
martmull
2026-06-16 15:53:13 +02:00
committed by GitHub
parent 16a92f52a4
commit 306a1454aa
8 changed files with 11 additions and 11 deletions
@@ -40,8 +40,8 @@ this — the OAuth credentials are already configured.
### 1. Register an OAuth app in Linear
1. Visit https://linear.app/settings/api/applications/new.
2. Set the **Redirect URI** to `<SERVER_URL>/apps/oauth/callback` (for
local dev: `http://localhost:3000/apps/oauth/callback`).
2. Set the **Redirect URI** to `<SERVER_URL>/auth/apps/callback` (for
local dev: `http://localhost:3000/auth/apps/callback`).
3. Copy the generated **Client ID** and **Client Secret**.
### 2. Wire the credentials into Twenty
@@ -79,7 +79,7 @@ Both routes require an authenticated Twenty user and use the same shared Slack c
reinstall the Slack app to the workspace) so the token picks up new scopes.
3. Set the **Redirect URL** on the Slack app to
`<YOUR_TWENTY_SERVER_URL>/apps/oauth/callback` — the same origin your
`<YOUR_TWENTY_SERVER_URL>/auth/apps/callback` — the same origin your
Twenty **server** uses for API routes (the callback is not served by the SPA
alone). Local monorepo dev often uses `http://localhost:3000` (confirm the
port your `twenty-server` / `SERVER_URL` actually uses).
@@ -122,7 +122,7 @@ Use plain product language:
- Name the Twenty objects and views users will actually interact with.
- Explain setup variables by their exact names.
- Distinguish server admin setup from workspace member usage.
- For OAuth connections, mention the provider redirect URI: `<SERVER_URL>/apps/oauth/callback`.
- For OAuth connections, mention the provider redirect URI: `<SERVER_URL>/auth/apps/callback`.
- Document permissions in terms of user risk: read, create, update, soft delete, destroy, third-party send.
Avoid:
@@ -82,7 +82,7 @@ Key points:
The OAuth callback URL your provider needs to whitelist is:
```
https://<your-twenty-server>/apps/oauth/callback
https://<your-twenty-server>/auth/apps/callback
```
</Accordion>
@@ -182,7 +182,7 @@ Multiple connections per (user, provider) are allowed, so the same user can hold
For each connection provider, the server admin needs to register an OAuth app at the third party first.
1. Go to the provider's developer settings (e.g. https://linear.app/settings/api/applications/new).
2. Set the **Redirect URI** to `<SERVER_URL>/apps/oauth/callback`.
2. Set the **Redirect URI** to `<SERVER_URL>/auth/apps/callback`.
3. Copy the generated **Client ID** and **Client Secret**.
4. Open the installed app in Twenty as a server admin → set the values on the corresponding `serverVariables`.
5. Workspace members can then add connections from the per-app **Connections** section.
@@ -7,7 +7,7 @@ import { GenerateTransientTokenDocument } from '~/generated-metadata/graphql';
// Mints a transient token then redirects to the generic app OAuth endpoint.
// Mirrors `useTriggerApisOAuth` for Google/Microsoft, but the URL template is
// /apps/oauth/authorize and works for any app-declared OAuth provider.
// /auth/apps/authorize and works for any app-declared OAuth provider.
export const useTriggerAppOAuth = () => {
const [generateTransientToken] = useMutation(GenerateTransientTokenDocument);
const { redirect } = useRedirect();
@@ -58,7 +58,7 @@ export const useTriggerAppOAuth = () => {
}
redirect(
`${REACT_APP_SERVER_BASE_URL}/apps/oauth/authorize?${params.toString()}`,
`${REACT_APP_SERVER_BASE_URL}/auth/apps/authorize?${params.toString()}`,
);
},
[generateTransientToken, redirect],
@@ -172,7 +172,7 @@ describe('ConnectionProviderOAuthFlowService', () => {
expect(url.searchParams.get('scope')).toBe('read write');
expect(url.searchParams.get('state')).toBe('signed-state-token');
expect(url.searchParams.get('redirect_uri')).toBe(
'https://api.example.com/apps/oauth/callback',
'https://api.example.com/auth/apps/callback',
);
expect(url.searchParams.has('code_challenge')).toBe(false);
@@ -23,7 +23,7 @@ import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.ent
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
import { PublicEndpointGuard } from 'src/engine/guards/public-endpoint.guard';
@Controller('apps/oauth')
@Controller('auth/apps')
@UseGuards(PublicEndpointGuard, NoPermissionGuard)
export class ConnectionProviderOAuthController {
private readonly logger = new Logger(ConnectionProviderOAuthController.name);
@@ -2,4 +2,4 @@
// signed `state` parameter, so a single redirect URL configured at the
// OAuth provider serves every workspace.
export const buildAppOAuthCallbackUrl = (serverUrl: string): string =>
new URL('/apps/oauth/callback', serverUrl).toString();
new URL('/auth/apps/callback', serverUrl).toString();