Passed
Push — 2.0 ( 790ac5...99dfe3 )
by Samuel
02:05
created

MultiAuthenticate::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
namespace SMartins\PassportMultiauth\Http\Middleware;
4
5
use Closure;
6
use League\OAuth2\Server\ResourceServer;
7
use Illuminate\Auth\AuthenticationException;
8
use Illuminate\Auth\Middleware\Authenticate;
9
use Illuminate\Contracts\Auth\Authenticatable;
10
use Illuminate\Contracts\Auth\Factory as Auth;
11
use SMartins\PassportMultiauth\PassportMultiauth;
12
use SMartins\PassportMultiauth\Provider as Token;
13
use SMartins\PassportMultiauth\ProviderRepository;
14
use SMartins\PassportMultiauth\Guards\GuardChecker;
15
use SMartins\PassportMultiauth\Facades\ServerRequest;
16
use League\OAuth2\Server\Exception\OAuthServerException;
17
18
class MultiAuthenticate extends Authenticate
19
{
20
    /**
21
     * @var \League\OAuth2\Server\ResourceServer
22
     */
23
    protected $server;
24
25
    /**
26
     * @var \SMartins\PassportMultiauth\ProviderRepository
27
     */
28
    protected $providers;
29
30
    /**
31
     * Create a new middleware instance.
32
     *
33
     * @param ResourceServer $server
34
     * @param ProviderRepository $providers
35
     * @param Auth $auth
36
     */
37 13
    public function __construct(
38
        ResourceServer $server,
39
        ProviderRepository $providers,
40
        Auth $auth
41
    ) {
42 13
        parent::__construct($auth);
43
44 13
        $this->server = $server;
45 13
        $this->providers = $providers;
46 13
    }
47
48
    /**
49
     * Handle an incoming request. Authenticates the guard from access token
50
     * used on request.
51
     *
52
     * @param \Illuminate\Http\Request $request
53
     * @param \Closure                 $next
54
     * @param string[]                 ...$guards
55
     * @return mixed
56
     *
57
     * @throws \Illuminate\Auth\AuthenticationException
58
     */
59 13
    public function handle($request, Closure $next, ...$guards)
60
    {
61
        // If don't has any guard follow the flow
62 13
        if (empty($guards)) {
63 2
            $this->authenticate($guards);
64
65
            // Stop laravel from checking for a token if session is not set
66
            return $next($request);
67
        }
68
69 11
        $psrRequest = ServerRequest::createRequest($request);
70
71
        try {
72 11
            $psrRequest = $this->server->validateAuthenticatedRequest($psrRequest);
73
74 4
            if (! $tokenId = $psrRequest->getAttribute('oauth_access_token_id')) {
75 1
                throw new AuthenticationException('Unauthenticated', $guards);
76
            }
77
78 3
            if (! $accessToken = $this->providers->findForToken($tokenId)) {
79 1
                throw new AuthenticationException('Unauthenticated', $guards);
80
            }
81
82 2
            $this->authenticateTokenGuard($accessToken, $guards);
83 10
        } catch (OAuthServerException $e) {
84
            // If has an OAuthServerException check if has unit tests and fake
85
            // user authenticated.
86 7
            if ($user = PassportMultiauth::userActing()) {
87 6
                if ($this->canBeAuthenticated($user, $guards)) {
88 4
                    return $next($request);
89
                }
90
            }
91
92
            // @todo Check if it's the best way to handle with OAuthServerException
93 3
            throw new AuthenticationException('Unauthenticated', $guards);
94
        }
95
96 1
        return $next($request);
97
    }
98
99
    /**
100
     * Check if user acting has the required guards and scopes on request.
101
     *
102
     * @param Authenticatable $user
103
     * @param  array $guards
104
     * @return bool
105
     */
106 6
    public function canBeAuthenticated(Authenticatable $user, $guards)
107
    {
108 6
        $userGuard = PassportMultiauth::getUserGuard($user);
109
110 6
        return in_array($userGuard, $guards);
111
    }
112
113
    /**
114
     * Authenticate correct guard based on token.
115
     *
116
     * @param \SMartins\PassportMultiauth\Provider $token
117
     * @param  array $guards
118
     * @return void
119
     *
120
     * @throws \Illuminate\Auth\AuthenticationException
121
     */
122 2
    public function authenticateTokenGuard(Token $token, $guards)
123
    {
124 2
        $providers = GuardChecker::getGuardsProviders($guards);
125
126
        // use only guard associated to access token provider
127 2
        $authGuards = $providers->has($token->provider) ? [$providers->get($token->provider)] : [];
128
129 2
        $this->authenticate($authGuards);
130 1
    }
131
}
132