Exchange clientSecret for tokens after app registration + bump canary (#19582)

## Summary

- **Fix `createApplicationRegistration` flow**: The server's
`createApplicationRegistration` mutation returns a `clientSecret`, not
`accessToken`/`refreshToken` directly. The SDK now correctly requests
`clientSecret` and immediately performs an OAuth `client_credentials`
exchange to obtain `appAccessToken` and `appRefreshToken`, then stores
them in config.
- **New `exchangeCredentialsForTokens` helper**: Shared by both `dev`
and `dev --once` flows. Takes `clientId` + `clientSecret`, calls
`/oauth/token` with `client_credentials` grant, and persists the
resulting tokens.
- **Bump `twenty-sdk`, `twenty-client-sdk`, `create-twenty-app` to
`1.22.0-canary.2`**

## Context

The `1.22.0-canary.1` SDK release expected
`createApplicationRegistration` to return `accessToken`/`refreshToken`
directly, but the `v1.22.0` server returns `clientSecret`. This caused
`yarn twenty dev` and `yarn twenty dev --once` to fail with "No
registration found" errors.
This commit is contained in:
Charles Bochet
2026-04-11 12:26:18 +02:00
committed by GitHub
parent 300be990b0
commit 53065f241f
8 changed files with 72 additions and 19 deletions
@@ -1,5 +1,8 @@
import { type ApiService } from '@/cli/utilities/api/api-service';
import { ensureValidAppAccessTokenOrRefresh } from '@/cli/utilities/auth/resolve-app-access-token';
import {
ensureValidAppAccessTokenOrRefresh,
exchangeCredentialsForTokens,
} from '@/cli/utilities/auth/resolve-app-access-token';
import { type ConfigService } from '@/cli/utilities/config/config-service';
import { type OrchestratorState } from '@/cli/utilities/dev/orchestrator/dev-mode-orchestrator-state';
import { type Manifest } from 'twenty-shared/application';
@@ -55,14 +58,16 @@ export class RegisterAppOrchestratorStep {
return;
}
const { applicationRegistration, accessToken, refreshToken } =
createResult.data;
const { applicationRegistration, clientSecret } = createResult.data;
await this.configService.setConfig({
appRegistrationId: applicationRegistration.id,
appRegistrationClientId: applicationRegistration.oAuthClientId,
appAccessToken: accessToken,
appRefreshToken: refreshToken,
});
await exchangeCredentialsForTokens(this.configService, {
clientId: applicationRegistration.oAuthClientId,
clientSecret,
});
this.state.applyStepEvents([