Passed
Push — 2.0 ( 50a782...790ac5 )
by Samuel
02:26 queued 19s
created

MultiAuthenticate::canBeAuthenticated()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
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
        // stop laravel from checking for a token if session is not set
63 13
        if (empty($guards)) {
64 2
            $this->authenticate($guards);
65
            return $next($request);
66
        }
67
68 11
        $psrRequest = ServerRequest::createRequest($request);
69
70
        try {
71 11
            $psrRequest = $this->server->validateAuthenticatedRequest($psrRequest);
72
73 4
            if (! $tokenId = $psrRequest->getAttribute('oauth_access_token_id')) {
74 1
                throw new AuthenticationException('Unauthenticated', $guards);
75
            }
76
77 3
            if (! $accessToken = $this->providers->findForToken($tokenId)) {
78 1
                throw new AuthenticationException('Unauthenticated', $guards);
79
            }
80
81 2
            $this->authenticateTokenGuard($accessToken, $guards);
82 10
        } catch (OAuthServerException $e) {
83
            // If has an OAuthServerException check if has unit tests and fake
84
            // user authenticated.
85 7
            if ($user = PassportMultiauth::userActing()) {
86 6
                if ($this->canBeAuthenticated($user, $guards)) {
87 4
                    return $next($request);
88
                }
89
            }
90
91
            // @todo Check if it's the best way to handle with OAuthServerException
92 3
            throw new AuthenticationException('Unauthenticated', $guards);
93
        }
94
95 1
        return $next($request);
96
    }
97
98
    /**
99
     * Check if user acting has the required guards and scopes on request.
100
     *
101
     * @param Authenticatable $user
102
     * @param  array $guards
103
     * @return bool
104
     */
105 6
    public function canBeAuthenticated(Authenticatable $user, $guards)
106
    {
107 6
        $userGuard = PassportMultiauth::getUserGuard($user);
108
109 6
        return in_array($userGuard, $guards);
110
    }
111
112
    /**
113
     * Authenticate correct guard based on token.
114
     *
115
     * @param \SMartins\PassportMultiauth\Provider $token
116
     * @param  array $guards
117
     * @return mixed
118
     *
119
     * @throws \Illuminate\Auth\AuthenticationException
120
     */
121 2
    public function authenticateTokenGuard(Token $token, $guards)
122
    {
123 2
        $providers = GuardChecker::getGuardsProviders($guards);
124
125
        // use only guard associated to access token provider
126 2
        $authGuards = $providers->has($token->provider) ? [$providers->get($token->provider)] : [];
127
128 2
        return $this->authenticate($authGuards);
129
    }
130
}
131