Skip to content

Commit 16f15a2

Browse files
Merge pull request #9 from maks-rafalko/feature/symofny-docs
Add documentation for usage in Symfony application with custom Grant Type and Redis cache
2 parents 5f1d6b9 + ea26818 commit 16f15a2

File tree

1 file changed

+125
-1
lines changed

1 file changed

+125
-1
lines changed

README.md

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,128 @@ You can use the HeaderRequestSigner to add the access token in another header, o
7272

7373
A class in charge of checking if the API call failed because of a token expiration.
7474
By default, the decorator uses StatusCode401ResponseChecker that identifies 401 response codes as the signal the access token needs to be renewed.
75-
It can lead to false positives (401 response code can be returned for other reasons than token expiration), so you can implement the interface if your OAuth server returns exploitable fine-grained error reasons.
75+
It can lead to false positives (401 response code can be returned for other reasons than token expiration), so you can implement the interface if your OAuth server returns exploitable fine-grained error reasons.
76+
77+
## Full Symfony-specific example
78+
79+
Here is a full example of how to use this library inside a Symfony application.
80+
81+
- with custom Grant Type
82+
- with Redis as a cache layer
83+
- with [scoped](https://symfony.com/doc/current/http_client.html#scoping-client) HTTP Client definition
84+
- with different URLs for the OAuth server and the API
85+
86+
First of all, we need to define 2 HTTP Clients: one for the OAuth server and one for the API.
87+
88+
```yaml
89+
framework:
90+
http_client:
91+
scoped_clients:
92+
sharepoint_oauth.client:
93+
scope: '%env(resolve:SHAREPOINT_OAUTH_URL)%'
94+
headers:
95+
Accept: 'application/json;odata=verbose'
96+
# other specific headers or settings if needed
97+
sharepoint_api.client:
98+
scope: '%env(resolve:SHAREPOINT_API_URL)%'
99+
headers:
100+
Accept: 'application/json;odata=verbose'
101+
# other specific headers or settings if needed
102+
```
103+
104+
Second, we need to define a custom Grant Type that will fetch the access token from the OAuth server to connect to SharePoint and will use `sharepoint_oauth.client` defined above.
105+
106+
It differs from a built-in `ClientCredentialsGrantType` on purpose, to show how we can customize the authentication process:
107+
108+
```php
109+
<?php
110+
111+
declare(strict_types=1);
112+
113+
namespace App\Sharepoint;
114+
115+
use BenjaminFavre\OAuthHttpClient\GrantType\GrantTypeInterface;
116+
use BenjaminFavre\OAuthHttpClient\GrantType\Tokens;
117+
use BenjaminFavre\OAuthHttpClient\GrantType\TokensExtractor;
118+
use Symfony\Component\HttpFoundation\Request;
119+
use Symfony\Contracts\HttpClient\HttpClientInterface;
120+
121+
final class CustomClientCredentialsGrantType implements GrantTypeInterface
122+
{
123+
use TokensExtractor;
124+
125+
public function __construct(
126+
private HttpClientInterface $client,
127+
private string $sharepointOauthClientId,
128+
private string $sharepointOauthClientSecret,
129+
private string $sharepointOauthUrl,
130+
private string $sharepointOauthResource,
131+
) {
132+
}
133+
134+
public function getTokens(): Tokens
135+
{
136+
$response = $this->client->request(Request::METHOD_POST, $this->sharepointOauthUrl, [
137+
'body' => http_build_query([
138+
'grant_type' => 'client_credentials',
139+
'client_id' => $this->sharepointOauthClientId,
140+
'client_secret' => $this->sharepointOauthClientSecret,
141+
'resource' => $this->sharepointOauthResource,
142+
]),
143+
]);
144+
145+
return $this->extractTokens($response);
146+
}
147+
}
148+
```
149+
150+
In order to pass the required parameters to the Grant Type, we need to define the service in `service.yaml` and bind parameters:
151+
152+
```yaml
153+
services:
154+
App\Sharepoint\CustomClientCredentialsGrantType:
155+
bind:
156+
$client: '@sharepoint_oauth.client'
157+
string $sharepointOauthClientId: '%env(SHAREPOINT_OAUTH_CLIENT_ID)%'
158+
string $sharepointOauthClientSecret: '%env(SHAREPOINT_OAUTH_CLIENT_SECRET)%'
159+
string $sharepointOauthResource: '%env(SHAREPOINT_OAUTH_RESOURCE)%'
160+
string $sharepointOauthUrl: '%env(SHAREPOINT_OAUTH_URL)%'
161+
```
162+
163+
Then, we need to define our cache layer instead of default `in-memory`, by adding the following service definition to `services.yaml`:
164+
165+
```yaml
166+
BenjaminFavre\OAuthHttpClient\TokensCache\SymfonyTokensCacheAdapter:
167+
bind:
168+
$cache: '@cache.app'
169+
$cacheKey: 'sharepoint'
170+
```
171+
172+
`@cache.app` is an application cache, configured in your system. In our example, this is a Redis cache:
173+
174+
```yaml
175+
framework:
176+
cache:
177+
app: cache.adapter.redis
178+
default_redis_provider: '%env(REDIS_URL)%'
179+
```
180+
181+
Finally, we can define our `OAuthHttpClient` service in `services.yaml` that uses `sharepoint_api.client` and sets configured Redis cache:
182+
183+
```yaml
184+
BenjaminFavre\OAuthHttpClient\OAuthHttpClient:
185+
bind:
186+
$client: '@sharepoint_api.client'
187+
$grant: '@App\Sharepoint\CustomClientCredentialsGrantType'
188+
calls:
189+
- [ setCache, [ '@BenjaminFavre\OAuthHttpClient\TokensCache\SymfonyTokensCacheAdapter' ] ]
190+
```
191+
192+
After this, `OAuthHttpClient` service is ready to be used in your application in any other classes:
193+
194+
```php
195+
public function __construct(
196+
private OAuthHttpClient $sharepointClient,
197+
) {
198+
}
199+
```

0 commit comments

Comments
 (0)