Issues (37)

src/Extension/Pkce.php (2 issues)

Labels
Severity
1
<?php
2
3
namespace Parroauth2\Client\Extension;
4
5
use Base64Url\Base64Url;
6
use Parroauth2\Client\EndPoint\Authorization\AuthorizationEndPoint;
7
use Parroauth2\Client\EndPoint\EndPointTransformerTrait;
8
use Parroauth2\Client\EndPoint\Token\TokenEndPoint;
9
10
/**
11
 * Extension for enable Proof Key for Code Exchange
12
 * This extension may be register even if the provider do not supports PKCE
13
 *
14
 * Client options :
15
 * - code_challenge_method : "plain" | "S256" Configure the code challenge method. This option is case sensitive
16
 *
17
 * @see https://tools.ietf.org/html/rfc7636
18
 */
19
final class Pkce extends AbstractEndPointTransformerExtension
20
{
21
    use EndPointTransformerTrait;
22
23
    public const METHOD_PLAIN = 'plain';
24
    public const METHOD_S256 = 'S256';
25
26
    /**
27
     * {@inheritdoc}
28
     */
29 6
    public function onAuthorization(AuthorizationEndPoint $endPoint): AuthorizationEndPoint
30
    {
31 6
        $codeVerifier = Base64Url::encode(random_bytes(96));
32 6
        $this->client()->storage()->store('code_verifier', $codeVerifier);
33
34 6
        $codeChallengeMethod = $this->codeChallengeMethod();
35
36
        switch ($codeChallengeMethod) {
37 6
            case self::METHOD_PLAIN:
38 2
                $codeChallenge = $codeVerifier;
39 2
                break;
40
41 4
            case self::METHOD_S256:
42 3
                $codeChallenge = Base64Url::encode(hash('sha256', $codeVerifier, true));
43 3
                break;
44
45
            default:
46 1
                throw new \LogicException('Unsupported code challenge method ' . $codeChallengeMethod);
47
        }
48
49
        return $endPoint
50 5
            ->set('code_challenge', $codeChallenge)
51 5
            ->set('code_challenge_method', $codeChallengeMethod)
52
        ;
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58 1
    public function onToken(TokenEndPoint $endPoint): TokenEndPoint
59
    {
60 1
        if ($codeVerifier = $this->client()->storage()->remove('code_verifier')) {
61 1
            return $endPoint->set('code_verifier', $codeVerifier);
62
        }
63
64
        return $endPoint;
65
    }
66
67
    /**
68
     * Get the supported code challenge method
69
     *
70
     * @return string
71
     */
72 6
    private function codeChallengeMethod(): string
73
    {
74 6
        if ($method = $this->client()->clientConfig()->option('code_challenge_method')) {
75 2
            return $method;
76
        }
77
78
        // Provider supports S256
79
        if (
80 4
            in_array(
81 4
                self::METHOD_S256,
82 4
                $this->client()->provider()->metadata('code_challenge_methods_supported', [self::METHOD_S256])
0 ignored issues
show
$this->client()->provide...ray(self::METHOD_S256)) of type Parroauth2\Client\Provider\T|null is incompatible with the type array expected by parameter $haystack of in_array(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
                /** @scrutinizer ignore-type */ $this->client()->provider()->metadata('code_challenge_methods_supported', [self::METHOD_S256])
Loading history...
array(self::METHOD_S256) of type array<integer,string> is incompatible with the type Parroauth2\Client\Provider\T|null expected by parameter $default of Parroauth2\Client\Provid...erInterface::metadata(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
                $this->client()->provider()->metadata('code_challenge_methods_supported', /** @scrutinizer ignore-type */ [self::METHOD_S256])
Loading history...
83
            )
84
        ) {
85 3
            return self::METHOD_S256;
86
        }
87
88 1
        return self::METHOD_PLAIN;
89
    }
90
}
91