Skip to content

Commit f65713b

Browse files
gjtorikianclaude
andauthored
feat(pkce): Default clientId to the client's configured client ID (#423)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 34ee64f commit f65713b

2 files changed

Lines changed: 60 additions & 8 deletions

File tree

lib/PKCEHelper.php

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public static function generate(): array
7575
* Generate an AuthKit authorization URL with auto-generated PKCE parameters and state.
7676
*
7777
* @param string $redirectUri The redirect URI.
78-
* @param string $clientId The WorkOS client ID.
78+
* @param string|null $clientId The WorkOS client ID. Defaults to the client's configured client ID.
7979
* @param string|null $state Optional state parameter. Auto-generated if null.
8080
* @param string|null $provider Optional auth provider.
8181
* @param string|null $connectionId Optional connection ID.
@@ -87,7 +87,7 @@ public static function generate(): array
8787
*/
8888
public function getAuthKitAuthorizationUrl(
8989
string $redirectUri,
90-
string $clientId,
90+
?string $clientId = null,
9191
?string $state = null,
9292
?string $provider = null,
9393
?string $connectionId = null,
@@ -96,6 +96,7 @@ public function getAuthKitAuthorizationUrl(
9696
?string $loginHint = null,
9797
?string $screenHint = null,
9898
): array {
99+
$clientId ??= $this->client->requireClientId();
99100
$pkce = self::generate();
100101
$state ??= bin2hex(random_bytes(16));
101102

@@ -134,14 +135,16 @@ public function getAuthKitAuthorizationUrl(
134135
*
135136
* @param string $code The authorization code.
136137
* @param string $codeVerifier The PKCE code verifier.
137-
* @param string $clientId The WorkOS client ID.
138+
* @param string|null $clientId The WorkOS client ID. Defaults to the client's configured client ID.
138139
* @return array The authentication response.
139140
*/
140141
public function authKitCodeExchange(
141142
string $code,
142143
string $codeVerifier,
143-
string $clientId,
144+
?string $clientId = null,
144145
): array {
146+
$clientId ??= $this->client->requireClientId();
147+
145148
return $this->client->request(
146149
method: 'POST',
147150
path: 'user_management/authenticate',
@@ -160,7 +163,7 @@ public function authKitCodeExchange(
160163
* Generate an SSO authorization URL with auto-generated PKCE parameters and state.
161164
*
162165
* @param string $redirectUri The redirect URI.
163-
* @param string $clientId The WorkOS client ID.
166+
* @param string|null $clientId The WorkOS client ID. Defaults to the client's configured client ID.
164167
* @param string|null $state Optional state parameter. Auto-generated if null.
165168
* @param string|null $domain Optional SSO domain.
166169
* @param string|null $provider Optional SSO provider.
@@ -172,7 +175,7 @@ public function authKitCodeExchange(
172175
*/
173176
public function getSsoAuthorizationUrl(
174177
string $redirectUri,
175-
string $clientId,
178+
?string $clientId = null,
176179
?string $state = null,
177180
?string $domain = null,
178181
?string $provider = null,
@@ -181,6 +184,7 @@ public function getSsoAuthorizationUrl(
181184
?string $domainHint = null,
182185
?string $loginHint = null,
183186
): array {
187+
$clientId ??= $this->client->requireClientId();
184188
$pkce = self::generate();
185189
$state ??= bin2hex(random_bytes(16));
186190

@@ -219,14 +223,16 @@ public function getSsoAuthorizationUrl(
219223
*
220224
* @param string $code The authorization code.
221225
* @param string $codeVerifier The PKCE code verifier.
222-
* @param string $clientId The WorkOS client ID.
226+
* @param string|null $clientId The WorkOS client ID. Defaults to the client's configured client ID.
223227
* @return array The SSO token response.
224228
*/
225229
public function ssoCodeExchange(
226230
string $code,
227231
string $codeVerifier,
228-
string $clientId,
232+
?string $clientId = null,
229233
): array {
234+
$clientId ??= $this->client->requireClientId();
235+
230236
return $this->client->request(
231237
method: 'POST',
232238
path: 'sso/token',

tests/PKCEHelperTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,41 @@ public function testGetAuthKitAuthorizationUrl(): void
8686
$this->assertSame('S256', $query['code_challenge_method']);
8787
}
8888

89+
public function testGetAuthKitAuthorizationUrlFallsBackToConfiguredClientId(): void
90+
{
91+
$client = $this->createMockClient([['status' => 200, 'body' => ['url' => 'https://auth.workos.com/...']]]);
92+
$client->pkce()->getAuthKitAuthorizationUrl(
93+
redirectUri: 'https://example.com/callback',
94+
);
95+
$query = [];
96+
parse_str($this->getLastRequest()->getUri()->getQuery(), $query);
97+
$this->assertSame('test_client_id', $query['client_id']);
98+
}
99+
100+
public function testGetAuthKitAuthorizationUrlExplicitClientIdWins(): void
101+
{
102+
$client = $this->createMockClient([['status' => 200, 'body' => ['url' => 'https://auth.workos.com/...']]]);
103+
$client->pkce()->getAuthKitAuthorizationUrl(
104+
redirectUri: 'https://example.com/callback',
105+
clientId: 'client_override',
106+
);
107+
$query = [];
108+
parse_str($this->getLastRequest()->getUri()->getQuery(), $query);
109+
$this->assertSame('client_override', $query['client_id']);
110+
}
111+
112+
public function testGetAuthKitAuthorizationUrlThrowsWithoutAnyClientId(): void
113+
{
114+
$client = $this->createMockClient(
115+
[['status' => 200, 'body' => []]],
116+
clientId: null,
117+
);
118+
$this->expectException(\WorkOS\Exception\ConfigurationException::class);
119+
$client->pkce()->getAuthKitAuthorizationUrl(
120+
redirectUri: 'https://example.com/callback',
121+
);
122+
}
123+
89124
// -- H11: AuthKit PKCE code exchange --
90125

91126
public function testAuthKitCodeExchange(): void
@@ -105,6 +140,17 @@ public function testAuthKitCodeExchange(): void
105140
$this->assertSame('verifier_123', $body['code_verifier']);
106141
}
107142

143+
public function testAuthKitCodeExchangeFallsBackToConfiguredClientId(): void
144+
{
145+
$client = $this->createMockClient([['status' => 200, 'body' => ['access_token' => 'at_123']]]);
146+
$client->pkce()->authKitCodeExchange(
147+
code: 'auth_code_123',
148+
codeVerifier: 'verifier_123',
149+
);
150+
$body = json_decode((string) $this->getLastRequest()->getBody(), true);
151+
$this->assertSame('test_client_id', $body['client_id']);
152+
}
153+
108154
// -- H15: SSO PKCE authorization URL --
109155

110156
public function testGetSsoAuthorizationUrl(): void

0 commit comments

Comments
 (0)