Skip to content

Commit ab66cb2

Browse files
authored
feat(auth): add scopeSeparator parameter to GenericOAuthConfig (#2119)
1 parent 3340f95 commit ab66cb2

3 files changed

Lines changed: 44 additions & 0 deletions

File tree

docs/2-features/17-oauth.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ return new GenericOAuthConfig(
204204
urlAccessToken: 'https://provider.com/oauth/token',
205205
urlResourceOwnerDetails: 'https://provider.com/api/user',
206206
scopes: ['read:user'],
207+
scopeSeparator: ' ', // Optional: If omitted the default `,` will be used. OIDC uses a space as separator.
207208
);
208209
```
209210

packages/auth/src/OAuth/Config/GenericOAuthConfig.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ public function __construct(
5858
* Identifier for this OAuth configuration.
5959
*/
6060
public null|string|UnitEnum $tag = null,
61+
62+
/**
63+
* Separator for the scopes, defaults to `,` if omitted.
64+
*/
65+
public ?string $scopeSeparator = null,
6166
) {}
6267

6368
public function createProvider(): AbstractProvider
@@ -68,6 +73,7 @@ public function createProvider(): AbstractProvider
6873
'urlAuthorize' => $this->urlAuthorize,
6974
'urlAccessToken' => $this->urlAccessToken,
7075
'urlResourceOwnerDetails' => $this->urlResourceOwnerDetails,
76+
'scopeSeparator' => $this->scopeSeparator,
7177
]);
7278
}
7379

packages/auth/tests/OAuthTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,43 @@ public function generic_config_maps_user_data(): void
232232
$this->assertSame('https://example.com/himmel.jpg', $user->avatar);
233233
$this->assertSame('generic', $user->provider);
234234
}
235+
236+
#[Test]
237+
public function generic_config_creates_provider_correctly(): void
238+
{
239+
$config = new GenericOAuthConfig(
240+
clientId: 'client-123',
241+
clientSecret: 'secret-456', // @mago-expect lint:no-literal-password
242+
redirectTo: 'https://example.com/callback',
243+
urlAuthorize: 'https://provider.com/authorize',
244+
urlAccessToken: 'https://provider.com/token', // @mago-expect lint:no-literal-password
245+
urlResourceOwnerDetails: 'https://provider.com/user',
246+
);
247+
248+
$provider = $config->createProvider();
249+
250+
$url = $provider->getAuthorizationUrl(['scope' => ['scope1', 'scope2']]);
251+
$this->assertStringContainsString('https://provider.com/authorize?', $url);
252+
$this->assertStringContainsString('scope=scope1%2Cscope2', $url);
253+
$this->assertStringContainsString('client_id=client-123', $url);
254+
255+
$config = new GenericOAuthConfig(
256+
clientId: 'client-123',
257+
clientSecret: 'secret-456', // @mago-expect lint:no-literal-password
258+
redirectTo: 'https://example.com/callback',
259+
urlAuthorize: 'https://provider.com/authorize',
260+
urlAccessToken: 'https://provider.com/token', // @mago-expect lint:no-literal-password
261+
urlResourceOwnerDetails: 'https://provider.com/user',
262+
scopeSeparator: ' ',
263+
);
264+
265+
$provider = $config->createProvider();
266+
267+
$url = $provider->getAuthorizationUrl(['scope' => ['scope1', 'scope2']]);
268+
$this->assertStringContainsString('https://provider.com/authorize?', $url);
269+
$this->assertStringContainsString('scope=scope1%20scope2', $url);
270+
$this->assertStringContainsString('client_id=client-123', $url);
271+
}
235272
}
236273

237274
final class ResourceOwner implements ResourceOwnerInterface

0 commit comments

Comments
 (0)