Completed
Push — master ( 81ca7f...cfe488 )
by Andrii
11:21
created

OAuth2Middleware::buildIdentity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace hiapi\Core\Auth;
4
5
use GuzzleHttp\RequestOptions;
6
use hiapi\exceptions\NotAuthenticatedException;
7
use Psr\Http\Message\ServerRequestInterface;
8
use yii\web\User;
9
use GuzzleHttp\Client;
10
use yii\web\IdentityInterface;
11
12
/**
13
 * XXX Think if authentication can be done deferred?
14
 * XXX Does it make sence?
15
 */
16
class OAuth2Middleware extends AuthMiddleware
17
{
18
    public $userinfoUrl;
19
20
    /**
21
     * @var User
22
     */
23
    private $user;
24
25
    public function __construct(User $user)
26
    {
27
        $this->user = $user;
28
    }
29
30
    public function authenticate(ServerRequestInterface $request)
31
    {
32
        $identity = $this->findIdentity($request);
33
34
        if (empty($identity)) {
35
            return $this->buildUnathorizedIdentity();
36
        }
37
38
        $ok = $this->user->login($identity);
39
        if ($ok !== true) {
40
            throw new NotAuthenticatedException('failed login by token');
41
        }
42
    }
43
44
    private function findIdentity(ServerRequestInterface $request): ?IdentityInterface
45
    {
46
        $token = $this->getAccessToken($request);
47
        if (empty($token)) {
48
            return null;
49
        }
50
51
        try {
52
            $info = $this->getUserInfo($token);
53
        } catch (\Throwable $e) {
54
            throw new NotAuthenticatedException($e->getMessage());
55
        }
56
57
        return $this->buildIdentity($info);
58
    }
59
60
    private function buildUnathorizedIdentity(): IdentityInterface
61
    {
62
        return $this->buildIdentity([
63
            'sub' => -1,
64
            'username' => 'unauthorized',
65
            'state' => 'disabled',
66
            'roles' => 'role:unauthorized',
67
        ]);
68
    }
69
70
    private function buildIdentity(array $info): IdentityInterface
71
    {
72
        $class = $this->user->identityClass;
73
74
        return $class::fromArray($info);
75
    }
76
77
    private function getUserInfo(string $token)
78
    {
79
        $res = $this->getClient()->request('GET', '', [
80
            RequestOptions::HEADERS => [
81
                'Authorization' => 'Bearer ' . $token,
82
            ],
83
        ]);
84
85
        return \json_decode((string)$res->getBody(), true);
86
    }
87
88
    private function getClient(): Client
89
    {
90
        return new Client([
91
            'base_uri' => $this->userinfoUrl,
92
            'timeout' => 5.0,
93
        ]);
94
    }
95
}
96