Passed
Push — new-feature-manage-tokens ( 4ada05...379f40 )
by Samuel
01:59
created

MultiAuthenticate::handle()   B

Complexity

Conditions 7
Paths 10

Size

Total Lines 36
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7.0119

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 10
nop 3
dl 0
loc 36
ccs 15
cts 16
cp 0.9375
crap 7.0119
rs 8.8333
c 0
b 0
f 0
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 SMartins\PassportMultiauth\Config\AuthConfigHelper;
17
use League\OAuth2\Server\Exception\OAuthServerException;
18
19
class MultiAuthenticate extends Authenticate
20
{
21
    /**
22
     * @var ResourceServer
23
     */
24
    protected $server;
25
26
    /**
27
     * @var ProviderRepository
28
     */
29
    protected $providers;
30
31
    /**
32
     * Create a new middleware instance.
33
     *
34
     * @param ResourceServer $server
35
     * @param ProviderRepository $providers
36
     * @param Auth $auth
37
     */
38 13
    public function __construct(
39
        ResourceServer $server,
40
        ProviderRepository $providers,
41
        Auth $auth
42
    ) {
43 13
        parent::__construct($auth);
44
45 13
        $this->server = $server;
46 13
        $this->providers = $providers;
47 13
    }
48
49
    /**
50
     * Handle an incoming request. Authenticates the guard from access token
51
     * used on request.
52
     *
53
     * @param \Illuminate\Http\Request $request
54
     * @param \Closure $next
55
     * @param string[] ...$guards
56
     * @return mixed
57
     *
58
     * @throws \Illuminate\Auth\AuthenticationException
59
     * @throws \SMartins\PassportMultiauth\Exceptions\MissingConfigException
60
     */
61 13
    public function handle($request, Closure $next, ...$guards)
62
    {
63
        // If don't has any guard follow the flow
64 13
        if (empty($guards)) {
65 2
            $this->authenticate($guards);
66
67
            // Stop laravel from checking for a token if session is not set
68
            return $next($request);
69
        }
70
71 11
        $psrRequest = ServerRequest::createRequest($request);
72
73
        try {
74 11
            $psrRequest = $this->server->validateAuthenticatedRequest($psrRequest);
75
76 4
            if (! ($tokenId     = $psrRequest->getAttribute('oauth_access_token_id')) ||
77 4
                ! ($accessToken = $this->providers->findForToken($tokenId))
78
            ) {
79 2
                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 7
                $this->canBeAuthenticated($user, $guards)
88
            ) {
89 4
                return $next($request);
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
     * @throws \SMartins\PassportMultiauth\Exceptions\MissingConfigException
106
     */
107 6
    public function canBeAuthenticated(Authenticatable $user, $guards)
108
    {
109 6
        $userGuard = AuthConfigHelper::getUserGuard($user);
110
111 6
        return in_array($userGuard, $guards);
112
    }
113
114
    /**
115
     * Authenticate correct guard based on token.
116
     *
117
     * @param \SMartins\PassportMultiauth\Provider $token
118
     * @param  array $guards
119
     * @return void
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