Skip to content

Commit 583c605

Browse files
committed
Initial commit
0 parents  commit 583c605

22 files changed

+715
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
vendor/
2+
tests/
3+
composer.lock
4+
.phpunit.result.cache

composer.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "benjaminfavre/oauth-http-client",
3+
"autoload": {
4+
"psr-4": {"BenjaminFavre\\OAuthHttpClient\\": "src/"}
5+
},
6+
"require": {
7+
"php": "^7.2.5 || ^8.0.0",
8+
"ext-json": "*",
9+
"symfony/http-client-contracts": "^2.3.1",
10+
"symfony/cache-contracts": "^2.2.0"
11+
},
12+
"require-dev": {
13+
"phpunit/phpunit": "^9.4.3",
14+
"symfony/cache": "5.2.0",
15+
"symfony/http-client": "^5.2",
16+
"phpstan/phpstan": "^0.12.64"
17+
},
18+
"scripts": {
19+
"phpstan": "vendor/bin/phpstan analyse --level max src tests"
20+
}
21+
}

phpunit.xml.dist

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/9.4/phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
>
6+
7+
</phpunit>

src/Exception/OAuthException.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace BenjaminFavre\OAuthHttpClient\Exception;
4+
5+
use RuntimeException;
6+
7+
/**
8+
* Represents errors during OAuth protocol.
9+
*
10+
* @author Benjamin Favre <[email protected]>
11+
*/
12+
class OAuthException extends RuntimeException implements OAuthExceptionInterface
13+
{
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace BenjaminFavre\OAuthHttpClient\Exception;
4+
5+
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
6+
7+
/**
8+
* Represents errors during OAuth protocol.
9+
*
10+
* @author Benjamin Favre <[email protected]>
11+
*/
12+
interface OAuthExceptionInterface extends ExceptionInterface
13+
{
14+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace BenjaminFavre\OAuthHttpClient\GrantType;
4+
5+
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
6+
use Symfony\Contracts\HttpClient\HttpClientInterface;
7+
8+
/**
9+
* Implementation of the OAuth authorization grant type.
10+
*
11+
* @author Benjamin Favre <[email protected]>
12+
*/
13+
class AuthorizationCodeGrantType implements RefreshableGrantTypeInterface
14+
{
15+
use TokensExtractor;
16+
17+
/** @var HttpClientInterface */
18+
private $client;
19+
/** @var string */
20+
private $tokenUrl;
21+
/** @var string */
22+
private $code;
23+
/** @var string */
24+
private $clientId;
25+
/** @var string */
26+
private $clientSecret;
27+
28+
/**
29+
* @param HttpClientInterface $client A HTTP client to be used to communicate with the OAuth server.
30+
* @param string $tokenUrl The full URL of the token endpoint of the OAuth server.
31+
* @param string $code The code received from the OAuth server during the authentication step.
32+
* @param string $clientId The OAuth client ID.
33+
* @param string $clientSecret The OAuth client secret.
34+
*/
35+
public function __construct(
36+
HttpClientInterface $client,
37+
string $tokenUrl,
38+
string $code,
39+
string $clientId,
40+
string $clientSecret
41+
) {
42+
$this->client = $client;
43+
$this->tokenUrl = $tokenUrl;
44+
$this->code = $code;
45+
$this->clientId = $clientId;
46+
$this->clientSecret = $clientSecret;
47+
}
48+
49+
/**
50+
* {@inheritDoc}
51+
*
52+
* @return Tokens
53+
* @throws TransportExceptionInterface
54+
*/
55+
public function getTokens(): Tokens
56+
{
57+
$response = $this->client->request('POST', $this->tokenUrl, [
58+
'body' => http_build_query([
59+
'grant_type' => 'authorization_code',
60+
'client_id' => $this->clientId,
61+
'client_secret' => $this->clientSecret,
62+
'code' => $this->code,
63+
])
64+
]);
65+
66+
return $this->extractTokens($response);
67+
}
68+
69+
public function getRefreshTokenGrant(string $refreshToken): GrantTypeInterface
70+
{
71+
return new RefreshTokenGrantType($this->client, $this->tokenUrl, $refreshToken, $this->clientId, $this->clientSecret);
72+
}
73+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace BenjaminFavre\OAuthHttpClient\GrantType;
4+
5+
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
6+
use Symfony\Contracts\HttpClient\HttpClientInterface;
7+
8+
/**
9+
* Implementation of the OAuth client credentials grant type.
10+
*
11+
* @author Benjamin Favre <[email protected]>
12+
*/
13+
class ClientCredentialsGrantType implements GrantTypeInterface
14+
{
15+
use TokensExtractor;
16+
17+
/** @var HttpClientInterface */
18+
private $client;
19+
/** @var string */
20+
private $tokenUrl;
21+
/** @var string */
22+
private $clientId;
23+
/** @var string */
24+
private $clientSecret;
25+
26+
/**
27+
* @param HttpClientInterface $client A HTTP client to be used to communicate with the OAuth server.
28+
* @param string $tokenUrl The full URL of the token endpoint of the OAuth server.
29+
* @param string $clientId The OAuth client ID.
30+
* @param string $clientSecret The OAuth client secret.
31+
*/
32+
public function __construct(
33+
HttpClientInterface $client,
34+
string $tokenUrl,
35+
string $clientId,
36+
string $clientSecret
37+
) {
38+
$this->client = $client;
39+
$this->tokenUrl = $tokenUrl;
40+
$this->clientId = $clientId;
41+
$this->clientSecret = $clientSecret;
42+
}
43+
44+
/**
45+
* {@inheritDoc}
46+
*
47+
* @return Tokens
48+
* @throws TransportExceptionInterface
49+
*/
50+
public function getTokens(): Tokens
51+
{
52+
$response = $this->client->request('POST', $this->tokenUrl, [
53+
'headers' => ['Authorization' => sprintf('Basic %s', base64_encode("{$this->clientId}:{$this->clientSecret}"))],
54+
'body' => http_build_query(['grant_type' => 'client_credentials']),
55+
]);
56+
57+
return $this->extractTokens($response);
58+
}
59+
}

src/GrantType/GrantTypeInterface.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace BenjaminFavre\OAuthHttpClient\GrantType;
4+
5+
use BenjaminFavre\OAuthHttpClient\Exception\OAuthException;
6+
7+
/**
8+
* Implementation of one OAuth grant type.
9+
*
10+
* @author Benjamin Favre <[email protected]>
11+
*/
12+
interface GrantTypeInterface
13+
{
14+
/**
15+
* Retrieves tokens from an OAuth server.
16+
*
17+
* @return Tokens The tokens retrieved from the OAuth server.
18+
* @throws OAuthException When the tokens could not be retrieved.
19+
*/
20+
public function getTokens(): Tokens;
21+
}

src/GrantType/PasswordGrantType.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
namespace BenjaminFavre\OAuthHttpClient\GrantType;
4+
5+
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
6+
use Symfony\Contracts\HttpClient\HttpClientInterface;
7+
8+
/**
9+
* Implementation of the OAuth password grant type.
10+
*
11+
* @author Benjamin Favre <[email protected]>
12+
*/
13+
class PasswordGrantType implements GrantTypeInterface
14+
{
15+
use TokensExtractor;
16+
17+
/** @var HttpClientInterface */
18+
private $client;
19+
/** @var string */
20+
private $tokenUrl;
21+
/** @var string */
22+
private $username;
23+
/** @var string */
24+
private $password;
25+
/** @var ?string */
26+
private $clientId;
27+
/** @var ?string */
28+
private $clientSecret;
29+
30+
/**
31+
* @param HttpClientInterface $client A HTTP client to be used to communicate with the OAuth server.
32+
* @param string $tokenUrl The full URL of the token endpoint of the OAuth server.
33+
* @param string $username The OAuth user username.
34+
* @param string $password The OAuth user password.
35+
* @param ?string $clientId The OAuth client ID.
36+
* @param ?string $clientSecret The OAuth client secret.
37+
*/
38+
public function __construct(
39+
HttpClientInterface $client,
40+
string $tokenUrl,
41+
string $username,
42+
string $password,
43+
?string $clientId = null,
44+
?string $clientSecret = null
45+
) {
46+
$this->client = $client;
47+
$this->tokenUrl = $tokenUrl;
48+
$this->username = $username;
49+
$this->password = $password;
50+
$this->clientId = $clientId;
51+
$this->clientSecret = $clientSecret;
52+
}
53+
54+
/**
55+
* {@inheritDoc}
56+
*
57+
* @return Tokens
58+
* @throws TransportExceptionInterface
59+
*/
60+
public function getTokens(): Tokens
61+
{
62+
$parameters = [
63+
'grant_type' => 'password',
64+
'username' => $this->username,
65+
'password' => $this->password,
66+
];
67+
68+
if ($this->clientId !== null && $this->clientSecret !== null) {
69+
$parameters = array_merge($parameters, [
70+
'client_id' => $this->clientId,
71+
'client_secret' => $this->clientSecret,
72+
]);
73+
}
74+
75+
$response = $this->client->request('POST', $this->tokenUrl, [
76+
'body' => http_build_query($parameters),
77+
]);
78+
79+
return $this->extractTokens($response);
80+
}
81+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace BenjaminFavre\OAuthHttpClient\GrantType;
4+
5+
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
6+
use Symfony\Contracts\HttpClient\HttpClientInterface;
7+
8+
/**
9+
* Implementation of the OAuth refresh token grant type.
10+
*
11+
* @author Benjamin Favre <[email protected]>
12+
*/
13+
class RefreshTokenGrantType implements GrantTypeInterface
14+
{
15+
use TokensExtractor;
16+
17+
/** @var HttpClientInterface */
18+
private $client;
19+
/** @var string */
20+
private $tokenUrl;
21+
/** @var string */
22+
private $refresh_token;
23+
/** @var string */
24+
private $clientId;
25+
/** @var string */
26+
private $clientSecret;
27+
28+
/**
29+
* @param HttpClientInterface $client A HTTP client to be used to communicate with the OAuth server.
30+
* @param string $tokenUrl The full URL of the token endpoint of the OAuth server.
31+
* @param string $refresh_token A refresh token previously obtained from the OAuth server.
32+
* @param string $clientId The OAuth client ID.
33+
* @param string $clientSecret The OAuth client secret.
34+
*/
35+
public function __construct(
36+
HttpClientInterface $client,
37+
string $tokenUrl,
38+
string $refresh_token,
39+
string $clientId,
40+
string $clientSecret
41+
) {
42+
$this->client = $client;
43+
$this->tokenUrl = $tokenUrl;
44+
$this->refresh_token = $refresh_token;
45+
$this->clientId = $clientId;
46+
$this->clientSecret = $clientSecret;
47+
}
48+
49+
/**
50+
* {@inheritDoc}
51+
*
52+
* @return Tokens
53+
* @throws TransportExceptionInterface
54+
*/
55+
public function getTokens(): Tokens
56+
{
57+
$response = $this->client->request('POST', $this->tokenUrl, [
58+
'body' => http_build_query([
59+
'grant_type' => 'refresh_token',
60+
'client_id' => $this->clientId,
61+
'client_secret' => $this->clientSecret,
62+
'refresh_token' => $this->refresh_token,
63+
])
64+
]);
65+
66+
return $this->extractTokens($response);
67+
}
68+
}

0 commit comments

Comments
 (0)