AbstractAuthentication::getRequestBody()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 7
rs 10
cc 2
nc 2
nop 1
1
<?php declare(strict_types=1);
2
3
namespace ncryptf\middleware;
4
5
use DateTime;
6
use Exception;
7
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\ServerRequestInterface;
10
use Psr\Http\Server\MiddlewareInterface;
11
use Psr\Http\Server\RequestHandlerInterface;
12
use ncryptf\Authorization;
13
use ncryptf\Response;
14
use ncryptf\Token;
15
16
/**
17
 * PSR-15 Authentication middleware for handling ncryptf Authorization requests
18
 * Abstract class should be extended and implement `getTokenFromAccessToken` and `getRequestBody`
19
 */
20
abstract class AbstractAuthentication implements MiddlewareInterface
21
{
22
    use \Middlewares\Utils\Traits\HasResponseFactory;
23
24
    // The date header
25
    const DATE_HEADER = 'X-DATE';
26
27
    // The authorization header
28
    const AUTHORIZATION_HEADER = 'Authorization';
29
30
    // The amount of the seconds the request is permitted to differ from the server time
31
    const DRIFT_TIME_ALLOWANCE = 90;
32
33
    /**
34
     * Process a request
35
     * @param ServerRequestInterface $request
36
     * @param RequestHandlerInterface $handler
37
     * @return ResponseInterface
38
     */
39
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
40
    {
41
        $params = Authorization::extractParamsFromHeaderString(
42
            $request->getHeaderLine(self::AUTHORIZATION_HEADER)
43
        );
44
45
        if ($params) {
46
            if ($token = $this->getTokenFromAccessToken($params['access_token'])) {
47
                try {
48
                    $date = new DateTime($params['date'] ?? $request->getHeaderLine(self::DATE_HEADER));
49
50
                    $auth = new Authorization(
51
                        $request->getMethod(),
52
                        $this->getRequestUri($request),
53
                        $token,
54
                        $date,
55
                        $this->getRequestBody(clone $request),
56
                        $params['v'],
57
                        \base64_decode($params['salt'])
58
                    );
59
60
                    if ($auth->verify(\base64_decode($params['hmac']), $auth, static::DRIFT_TIME_ALLOWANCE)) {
61
                        return $handler->handle(
62
                            $request->withAttribute('ncryptf-token', $token)
63
                                ->withAttribute('ncryptf-user', $this->getUserFromToken($token))
64
                        );
65
                    }
66
                } catch (Exception $e) {
67
                    return $this->createResponse(401);
68
                }
69
            }
70
        }
71
72
        return $this->createResponse(401);
73
    }
74
75
    /**
76
     * Returns the full URI
77
     * @param ServerRequestInterface $request
78
     * @return string
79
     */
80
    private function getRequestUri(ServerRequestInterface $request) : string
81
    {
82
        $uri = $request->getUri()->getPath();
83
        $query = $request->getUri()->getQuery();
84
85
        if (!empty($query)) {
86
            return $uri . '?' . \urldecode($query);
87
        }
88
89
        return $uri;
90
    }
91
92
    /**
93
     * Returns the plaintext request body.
94
     *
95
     * @param ServerRequestInterface $request
96
     * @return string
97
     */
98
    protected function getRequestBody(ServerRequestInterface $request) : string
99
    {
100
        if ($decryptedBody = $request->getAttribute('ncryptf-decrypted-body', false)) {
101
            return $decryptedBody;
102
        }
103
104
        return $request->getBody()->getContents();
105
    }
106
107
    /**
108
     * Returns the \ncryptf\Token associated to the given access token.
109
     * If the access token is not found, `NULL` should be returned
110
     *
111
     * @param string $accessToken
112
     * @return \ncryptf\Token
113
     */
114
    abstract protected function getTokenFromAccessToken(string $accessToken) :? Token;
115
116
    /**
117
     * Given a particular token, returns an object, array, or integer representing the user
118
     *
119
     * @param \ncryptf\Token $token
120
     * @return integer|array|object
121
     */
122
    abstract protected function getUserFromToken(Token $token);
123
}
124