Passed
Push — main ( 5831d8...8d1028 )
by Breno
01:54
created

GovBr::getEnvironment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace BrenoRoosevelt\OAuth2\Client;
5
6
use League\OAuth2\Client\Provider\AbstractProvider;
7
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
8
use League\OAuth2\Client\Token\AccessToken;
9
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
10
use Psr\Http\Message\ResponseInterface;
11
use UnexpectedValueException;
12
13
class GovBr extends AbstractProvider
14
{
15
    const STAGING = 'https://sso.staging.acesso.gov.br';
16
    const PRODUCTION = 'https://sso.acesso.gov.br';
17
18
    use BearerAuthorizationTrait;
19
20
    protected $urlAuthorize;
21
    protected $urlAccessToken;
22
    protected $urlResourceOwnerDetails;
23
    protected $urlLogout;
24
25
    /** @var string */
26
    protected $redirectUriLogout = "";
27
28
    final public function __construct(array $options = [], array $collaborators = [])
29
    {
30
        list(
31
            $this->urlAuthorize,
32
            $this->urlAccessToken,
33
            $this->urlResourceOwnerDetails,
34
            $this->urlLogout
35
        ) = array_values(self::getEnvironment(GovBr::PRODUCTION));
36
37
        parent::__construct($options, $collaborators);
38
    }
39
40
    /**
41
     * Cria uma instância para ambiente de homologação
42
     *
43
     * @param array $options
44
     * @param array $collaborators
45
     * @return self
46
     */
47
    public static function staging(array $options, array $collaborators = []): self
48
    {
49
        $staging = new self($options, $collaborators);
50
        list(
51
            $staging->urlAuthorize,
52
            $staging->urlAccessToken,
53
            $staging->urlResourceOwnerDetails,
54
            $staging->urlLogout
55
        ) = array_values(self::getEnvironment(GovBr::STAGING));
56
57
        return $staging;
58
    }
59
60
    /**
61
     * Cria uma instância para ambiente de produção
62
     * Pode ser criado diretamente via construtor
63
     *
64
     * @param array $options
65
     * @param array $collaborators
66
     * @return self
67
     */
68
    public static function production(array $options, array $collaborators = []): self
69
    {
70
        return new self($options, $collaborators);
71
    }
72
73
    public function getDefaultScopes(): array
74
    {
75
        return [
76
            'openid',
77
            'email',
78
            'phone',
79
            'profile',
80
            'govbr_confiabilidades'
81
        ];
82
    }
83
84
    public function getScopeSeparator(): string
85
    {
86
        return '+';
87
    }
88
89
    protected function getAuthorizationParameters(array $options): array
90
    {
91
        if (!isset($options['nonce'])) {
92
            $options['nonce'] = md5(uniqid('govbr', true));
93
        }
94
95
        return parent::getAuthorizationParameters($options);
96
    }
97
    /**
98
     * @inheritDoc
99
     */
100
    protected function createResourceOwner(array $response, AccessToken $token)
101
    {
102
        return new GovBrUser($response, $token);
103
    }
104
105
    public function getAvatar(GovBrUser $govBrUser): ?Avatar
106
    {
107
        $request = $this->getAuthenticatedRequest(
108
            self::METHOD_GET,
109
            $govBrUser->getAvatarUrl(),
110
            $govBrUser->token()
111
        );
112
113
        $response = $this->getResponse($request);
114
115
        return
116
            new Avatar(
117
                (string) $response->getBody(),
118
                $response->getHeaderLine('Content-type')
119
            );
120
    }
121
122
    public function getBaseAuthorizationUrl(): string
123
    {
124
        return $this->urlAuthorize;
125
    }
126
127
    public function getBaseAccessTokenUrl(array $params): string
128
    {
129
        return $this->urlAccessToken;
130
    }
131
132
    public function getResourceOwnerDetailsUrl(AccessToken $token): string
133
    {
134
        return $this->urlResourceOwnerDetails;
135
    }
136
137
    public function getLogoutUrl(): string
138
    {
139
        if (empty($this->redirectUriLogout)) {
140
            throw new UnexpectedValueException("Parâmetro redirectUriLogout não foi definido");
141
        }
142
143
        $query  = $this->buildQueryString(['post_logout_redirect_uri' => $this->redirectUriLogout]);
144
        return $this->appendQuery($this->urlLogout, $query);
145
    }
146
147
    /**
148
     * @param ResponseInterface $response
149
     * @param array|string $data
150
     * @throws IdentityProviderException
151
     * @see https://manual-roteiro-integracao-login-unico.servicos.gov.br/pt/stable/iniciarintegracao.html#resultados-esperados-ou-erros-do-acesso-ao-servicos-do-login-unico
152
     */
153
    protected function checkResponse(ResponseInterface $response, $data)
154
    {
155
        $code = $response->getStatusCode();
156
        $errorResponse = ($code >= 400 && $code <= 599);
157
158
        if (isset($data['error']) || $errorResponse) {
159
            $error = $data['descricao'] ?? $data['error'] ?? (string) $response->getBody();
160
            if (!is_string($error)) {
161
                $error = var_export($error, true);
162
            }
163
164
            $errorCode = $data['codigo'] ?? $code;
165
            throw new IdentityProviderException($error, $errorCode, $data);
166
        }
167
    }
168
169
    final public static function getEnvironment(string $env): array
170
    {
171
        return [
172
            'urlAuthorize'            => $env . '/authorize',
173
            'urlAccessToken'          => $env . '/token',
174
            'urlResourceOwnerDetails' => $env . '/userinfo',
175
            'urlLogout'               => $env . '/logout',
176
        ];
177
    }
178
}
179