GovBr::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 7
nc 1
nop 2
dl 0
loc 10
rs 10
c 2
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 buildQueryString(array $params)
85
    {
86
        return http_build_query($params);
87
    }
88
89
    public function getScopeSeparator(): string
90
    {
91
        return ' ';
92
    }
93
94
    protected function getAuthorizationParameters(array $options): array
95
    {
96
        if (!isset($options['nonce'])) {
97
            $options['nonce'] = md5(uniqid('govbr', true));
98
        }
99
100
        return parent::getAuthorizationParameters($options);
101
    }
102
    /**
103
     * @inheritDoc
104
     */
105
    protected function createResourceOwner(array $response, AccessToken $token)
106
    {
107
        return new GovBrUser($response, $token);
108
    }
109
110
    public function getAvatar(GovBrUser $govBrUser): ?Avatar
111
    {
112
        $request = $this->getAuthenticatedRequest(
113
            self::METHOD_GET,
114
            $govBrUser->getAvatarUrl(),
115
            $govBrUser->token()
116
        );
117
118
        $response = $this->getResponse($request);
119
120
        return
121
            new Avatar(
122
                (string) $response->getBody(),
123
                $response->getHeaderLine('Content-type')
124
            );
125
    }
126
127
    public function getBaseAuthorizationUrl(): string
128
    {
129
        return $this->urlAuthorize;
130
    }
131
132
    public function getBaseAccessTokenUrl(array $params): string
133
    {
134
        return $this->urlAccessToken;
135
    }
136
137
    public function getResourceOwnerDetailsUrl(AccessToken $token): string
138
    {
139
        return $this->urlResourceOwnerDetails;
140
    }
141
142
    public function getLogoutUrl(): string
143
    {
144
        if (empty($this->redirectUriLogout)) {
145
            throw new UnexpectedValueException("Parâmetro redirectUriLogout não foi definido");
146
        }
147
148
        $query  = $this->buildQueryString(['post_logout_redirect_uri' => $this->redirectUriLogout]);
149
        return $this->appendQuery($this->urlLogout, $query);
150
    }
151
152
    /**
153
     * @param ResponseInterface $response
154
     * @param array|string $data
155
     * @throws IdentityProviderException
156
     * @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
157
     */
158
    protected function checkResponse(ResponseInterface $response, $data)
159
    {
160
        $code = $response->getStatusCode();
161
        $errorResponse = ($code >= 400 && $code <= 599);
162
163
        if (isset($data['error']) || $errorResponse) {
164
            $error = $data['descricao'] ?? $data['error'] ?? (string) $response->getBody();
165
            if (!is_string($error)) {
166
                $error = var_export($error, true);
167
            }
168
169
            $errorCode = $data['codigo'] ?? $code;
170
            throw new IdentityProviderException($error, $errorCode, $data);
171
        }
172
    }
173
174
    final public static function getEnvironment(string $env): array
175
    {
176
        return [
177
            'urlAuthorize'            => $env . '/authorize',
178
            'urlAccessToken'          => $env . '/token',
179
            'urlResourceOwnerDetails' => $env . '/userinfo',
180
            'urlLogout'               => $env . '/logout',
181
        ];
182
    }
183
}
184