AuthorizationCodeFlow   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 60
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 6
eloc 19
c 1
b 0
f 0
dl 0
loc 60
ccs 21
cts 21
cp 1
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A authorizationUri() 0 10 1
A handleAuthorizationResponse() 0 20 4
A __construct() 0 3 1
1
<?php
2
3
namespace Parroauth2\Client\Flow;
4
5
use BadMethodCallException;
6
use InvalidArgumentException;
7
use Parroauth2\Client\ClientInterface;
8
use Parroauth2\Client\EndPoint\Authorization\AuthorizationCodeResponse;
9
use Parroauth2\Client\EndPoint\Token\TokenResponse;
10
use Parroauth2\Client\Exception\OAuthServerException;
11
12
/**
13
 * The authorization code grant flow
14
 *
15
 * - Generates the authorization URI with a state (cf: AuthorizationCodeFlow::authorizationUri())
16
 * - The client redirect the user agent to the generated URI
17
 * - The authorization provider validates the requests and redirect the user agent to the client
18
 * - Validates the provider's response (cf: AuthorizationCodeFlow::authorizationUri())
19
 * - Get an access token from the provider using the code response
20
 *
21
 * <code>
22
 * $flow = new AuthorizationCodeFlow($client);
23
 *
24
 * if (!$this->isLogged()) {
25
 *     if ($request->path() !== '/connect') {
26
 *         return $this->redirectTo($flow->authorizationUri($baseUrl.'/connect'));
27
 *     }
28
 *
29
 *     $this->setToken($flow->handleAuthorizationResponse($request->query());
30
 *     return $this->redirectTo($baseUrl);
31
 * }
32
 *
33
 * // Use token
34
 * </code>
35
 *
36
 * @see https://tools.ietf.org/html/rfc6749#section-4.1
37
 */
38
class AuthorizationCodeFlow implements AuthorizationFlowInterface
39
{
40
    /**
41
     * @var ClientInterface
42
     */
43
    private $client;
44
45
46
    /**
47
     * AuthorizationCodeFlow constructor.
48
     *
49
     * @param ClientInterface $client
50
     */
51 16
    public function __construct(ClientInterface $client)
52
    {
53 16
        $this->client = $client;
54 16
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59 14
    public function authorizationUri(?string $redirectUri = null): string
60
    {
61 14
        $endpoint = $this->client->endPoints()
62 14
            ->authorization()
63 14
            ->code($redirectUri, $this->client->clientConfig()->scopes())
64
        ;
65
66 14
        $this->client->storage()->store('authorization', $endpoint->parameters());
67
68 14
        return $endpoint->uri();
69
    }
70
71
    /**
72
     * {@inheritdoc}
73
     *
74
     * @throws \Http\Client\Exception When an HTTP error occurs
75
     *
76
     * @psalm-suppress InvalidThrow
77
     */
78 12
    public function handleAuthorizationResponse(array $queryParameters): TokenResponse
79
    {
80 12
        if (!$this->client->storage()->has('authorization')) {
81 2
            throw new BadMethodCallException('The authorization flow is not started');
82
        }
83
84 10
        $request = $this->client->storage()->remove('authorization');
85 10
        $response = new AuthorizationCodeResponse($queryParameters);
86
87 10
        if (!hash_equals($request['state'], $response->state())) {
88 4
            throw new InvalidArgumentException('Invalid state');
89
        }
90
91 6
        if ($response->isError()) {
92 2
            throw OAuthServerException::create($response->error(), $response->errorDescription());
93
        }
94
95 4
        return $this->client->endPoints()->token()
96 4
            ->code($response->code(), $request['redirect_uri'] ?? null)
97 4
            ->call()
98
        ;
99
    }
100
}
101