Passed
Push — master ( f82e79...44b9b8 )
by Samuel
02:12
created

MultiAuthenticate::canBeAuthenticated()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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