|
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
|
|
|
// throw new AuthenticationException('Unauthenticated', $guards); |
|
|
|
|
|
|
84
|
|
|
} |
|
85
|
|
|
} |
|
86
|
|
|
|
|
87
|
|
|
// @todo Check if it's the best way to handle with OAuthServerException |
|
88
|
3 |
|
throw new AuthenticationException('Unauthenticated', $guards); |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
1 |
|
return $next($request); |
|
92
|
|
|
} |
|
93
|
|
|
|
|
94
|
|
|
/** |
|
95
|
|
|
* Check if user acting has the required guards and scopes on request. |
|
96
|
|
|
* |
|
97
|
|
|
* @param \Illuminate\Foundation\Auth\User $user |
|
98
|
|
|
* @param array $guards |
|
99
|
|
|
* @return bool |
|
100
|
|
|
*/ |
|
101
|
6 |
|
public function canBeAuthenticated(Authenticatable $user, $guards) |
|
102
|
|
|
{ |
|
103
|
6 |
|
$userGuard = PassportMultiauth::getUserGuard($user); |
|
104
|
|
|
|
|
105
|
6 |
|
return in_array($userGuard, $guards); |
|
106
|
|
|
} |
|
107
|
|
|
|
|
108
|
|
|
/** |
|
109
|
|
|
* Authenticate correct guard based on token. |
|
110
|
|
|
* |
|
111
|
|
|
* @param \SMartins\PassportMultiauth\Provider $token |
|
112
|
|
|
* @param array $guards |
|
113
|
|
|
* @return void |
|
114
|
|
|
* |
|
115
|
|
|
* @throws \Illuminate\Auth\AuthenticationException |
|
116
|
|
|
*/ |
|
117
|
2 |
|
public function authenticateTokenGuard(Token $token, $guards) |
|
118
|
|
|
{ |
|
119
|
2 |
|
$providers = GuardChecker::getGuardsProviders($guards); |
|
120
|
|
|
|
|
121
|
|
|
// use only guard associated to access token provider |
|
122
|
2 |
|
$authGuards = $providers->has($token->provider) ? [$providers->get($token->provider)] : []; |
|
123
|
|
|
|
|
124
|
2 |
|
return $this->authenticate($authGuards); |
|
125
|
|
|
} |
|
126
|
|
|
} |
|
127
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.