aboutsummaryrefslogtreecommitdiff
path: root/lib/classes/JsonApi/Middlewares/Auth/OAuth1Strategy.php
blob: 113ee09afe62ae429a4ccbe1fedeec75d550e325 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php

namespace JsonApi\Middlewares\Auth;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

class OAuth1Strategy implements Strategy
{
    /** @var callable */
    protected $authenticator;

    /** @var Request */
    protected $request;

    /** @var ?\User */
    protected $user;

    /**
     * @param callable $authenticator
     */
    public function __construct(Request $request, $authenticator)
    {
        $this->request = $request;
        $this->authenticator = $authenticator;

        \OAuthStore::instance('PDO', ['conn' => \DBManager::get()]);
    }

    public function check()
    {
        return !is_null($this->user());
    }

    public function user()
    {
        if (!is_null($this->user)) {
            return $this->user;
        }

        $this->user = $this->detect();

        return $this->user;
    }

    public function addChallenge(Response $response)
    {
        return $response; //->withHeader('WWW-Authenticate', sprintf('Basic realm="%s"', 'Stud.IP JSON-API'));
    }

    private function detect(): ?\User
    {
        if (!\OAuthRequestVerifier::requestIsSigned()) {
            return null;
        }

        $uri = (string) $this->request->getUri();
        $method = $this->request->getMethod();

        if ('GET' === strtoupper(($method))) {
            $parameters = (array) $this->request->getQueryParams();
        } elseif ('POST' === strtoupper(($method))) {
            $parameters = (array) $this->request->getParsedBody();
        } else {
            $parameters = [];
        }
        $parameters = $this->getParamsFromAuthorizationHeader($this->request, $parameters);

        $req = new \OAuthRequestVerifier($uri, $method, $parameters);

        // Check oauth timestamp and deny access if timestamp is outdated
        if ($req->getParam('oauth_timestamp') < strtotime('-6 hours')) {
            return null;
        }

        $result = $req->verifyExtended('access');

        $query = 'SELECT user_id FROM api_oauth_user_mapping WHERE oauth_id = ?';
        $statement = \DBManager::get()->prepare($query);
        $statement->execute([$result['user_id']]);

        if (!$userId = $statement->fetchColumn()) {
            return null;
        }

        /** @var \User */
        return \User::find($userId);
    }

    private function getParamsFromAuthorizationHeader(Request $request, array $params): array
    {
        if ($request->hasHeader('Authorization')) {
            $auth = $request->getHeaderLine('Authorization');
            if (0 == strncasecmp($auth, 'OAuth', 4)) {
                foreach (explode(',', substr($auth, 6)) as $v) {
                    if (!strpos($v, '=')) {
                        continue;
                    }
                    $v = trim($v);
                    list($name, $value) = explode('=', $v, 2);
                    if (!empty($value) && '"' == $value[0] && '"' == substr($value, -1)) {
                        $value = substr(substr($value, 1), 0, -1);
                    }

                    if (0 != strcasecmp($name, 'realm')) {
                        $params[$name] = $value;
                    }
                }
            }
        }

        return $params;
    }
}