Passed
Push — master ( b1ca46...93ace5 )
by Andrew
29:49 queued 28:17
created

RedirectUriValidator::matchExactUri()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 1
c 1
b 1
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
/**
3
 * @author      Sebastiano Degan <[email protected]>
4
 * @copyright   Copyright (c) Alex Bilbie
5
 * @license     http://mit-license.org/
6
 *
7
 * @link        https://github.com/thephpleague/oauth2-server
8
 */
9
10
namespace League\OAuth2\Server\RedirectUriValidators;
11
12
class RedirectUriValidator implements RedirectUriValidatorInterface
13
{
14
    /**
15
     * @var array
16
     */
17
    private $allowedRedirectUris;
18
19
    /**
20
     * New validator instance for the given uri
21
     *
22
     * @param string|array $allowedRedirectUris
23
     */
24 36
    public function __construct($allowedRedirectUri)
25
    {
26 36
        if (\is_string($allowedRedirectUri)) {
27 28
            $this->allowedRedirectUris = [$allowedRedirectUri];
28 8
        } elseif (\is_array($allowedRedirectUri)) {
29 8
            $this->allowedRedirectUris = $allowedRedirectUri;
30
        } else {
31
            $this->allowedRedirectUris = [];
32
        }
33 36
    }
34
35
    /**
36
     * Validates the redirect uri.
37
     *
38
     * @param string $redirectUri
39
     *
40
     * @return bool Return true if valid, false otherwise
41
     */
42 36
    public function validateRedirectUri($redirectUri)
43
    {
44 36
        if ($this->isLoopbackUri($redirectUri)) {
45 3
            return $this->matchUriExcludingPort($redirectUri);
46
        }
47
48 33
        return $this->matchExactUri($redirectUri);
49
    }
50
51
    /**
52
     * According to section 7.3 of rfc8252, loopback uris are:
53
     *   - "http://127.0.0.1:{port}/{path}" for IPv4
54
     *   - "http://[::1]:{port}/{path}" for IPv6
55
     *
56
     * @param string $redirectUri
57
     *
58
     * @return bool
59
     */
60 36
    private function isLoopbackUri($redirectUri)
61
    {
62 36
        $parsedUrl = \parse_url($redirectUri);
63
64 36
        return $parsedUrl['scheme'] === 'http'
65 36
            && (\in_array($parsedUrl['host'], ['127.0.0.1', '[::1]'], true));
66
    }
67
68
    /**
69
     * Find an exact match among allowed uris
70
     *
71
     * @param string $redirectUri
72
     *
73
     * @return bool Return true if an exact match is found, false otherwise
74
     */
75 33
    private function matchExactUri($redirectUri)
76
    {
77 33
        return \in_array($redirectUri, $this->allowedRedirectUris, true);
78
    }
79
80
    /**
81
     * Find a match among allowed uris, allowing for different port numbers
82
     *
83
     * @param string $redirectUri
84
     *
85
     * @return bool Return true if a match is found, false otherwise
86
     */
87 3
    private function matchUriExcludingPort($redirectUri)
88
    {
89 3
        $parsedUrl = $this->parseUrlAndRemovePort($redirectUri);
90
91 3
        foreach ($this->allowedRedirectUris as $allowedRedirectUri) {
92 3
            if ($parsedUrl === $this->parseUrlAndRemovePort($allowedRedirectUri)) {
93 2
                return true;
94
            }
95
        }
96
97 1
        return false;
98
    }
99
100
    /**
101
     * Parse an url like \parse_url, excluding the port
102
     *
103
     * @param string $url
104
     *
105
     * @return array
106
     */
107 3
    private function parseUrlAndRemovePort($url)
108
    {
109 3
        $parsedUrl = \parse_url($url);
110 3
        unset($parsedUrl['port']);
111
112 3
        return $parsedUrl;
113
    }
114
}
115