Skip to content

Commit 079d853

Browse files
authored
Merge pull request #1040 from alshf89/alshf
Fix exception will thrown if token belongs to first party clients
2 parents 6f4c1f0 + 9fa0bff commit 079d853

4 files changed

+192
-22
lines changed

src/Http/Middleware/CheckClientCredentials.php

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Closure;
66
use Zend\Diactoros\StreamFactory;
77
use Zend\Diactoros\ResponseFactory;
8+
use Laravel\Passport\TokenRepository;
89
use Zend\Diactoros\UploadedFileFactory;
910
use League\OAuth2\Server\ResourceServer;
1011
use Zend\Diactoros\ServerRequestFactory;
@@ -22,15 +23,24 @@ class CheckClientCredentials
2223
*/
2324
protected $server;
2425

26+
/**
27+
* Token Repository.
28+
*
29+
* @var \Laravel\Passport\TokenRepository
30+
*/
31+
protected $repository;
32+
2533
/**
2634
* Create a new middleware instance.
2735
*
2836
* @param \League\OAuth2\Server\ResourceServer $server
37+
* @param \Laravel\Passport\TokenRepository $repository
2938
* @return void
3039
*/
31-
public function __construct(ResourceServer $server)
40+
public function __construct(ResourceServer $server, TokenRepository $repository)
3241
{
3342
$this->server = $server;
43+
$this->repository = $repository;
3444
}
3545

3646
/**
@@ -57,27 +67,33 @@ public function handle($request, Closure $next, ...$scopes)
5767
throw new AuthenticationException;
5868
}
5969

60-
$this->validateScopes($psr, $scopes);
70+
$this->validate($psr, $scopes);
6171

6272
return $next($request);
6373
}
6474

6575
/**
66-
* Validate the scopes on the incoming request.
76+
* Validate the scopes and token on the incoming request.
6777
*
6878
* @param \Psr\Http\Message\ServerRequestInterface $psr
6979
* @param array $scopes
7080
* @return void
71-
* @throws \Laravel\Passport\Exceptions\MissingScopeException
81+
* @throws \Laravel\Passport\Exceptions\MissingScopeException|\Illuminate\Auth\AuthenticationException
7282
*/
73-
protected function validateScopes($psr, $scopes)
83+
protected function validate($psr, $scopes)
7484
{
75-
if (in_array('*', $tokenScopes = $psr->getAttribute('oauth_scopes'))) {
85+
$token = $this->repository->find($psr->getAttribute('oauth_access_token_id'));
86+
87+
if (! $token || $token->client->firstParty()) {
88+
throw new AuthenticationException;
89+
}
90+
91+
if (in_array('*', $token->scopes)) {
7692
return;
7793
}
7894

7995
foreach ($scopes as $scope) {
80-
if (! in_array($scope, $tokenScopes)) {
96+
if ($token->cant($scope)) {
8197
throw new MissingScopeException($scope);
8298
}
8399
}

src/Http/Middleware/CheckClientCredentialsForAnyScope.php

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Closure;
66
use Zend\Diactoros\StreamFactory;
77
use Zend\Diactoros\ResponseFactory;
8+
use Laravel\Passport\TokenRepository;
89
use Zend\Diactoros\UploadedFileFactory;
910
use League\OAuth2\Server\ResourceServer;
1011
use Zend\Diactoros\ServerRequestFactory;
@@ -22,15 +23,24 @@ class CheckClientCredentialsForAnyScope
2223
*/
2324
private $server;
2425

26+
/**
27+
* Token Repository.
28+
*
29+
* @var \Laravel\Passport\TokenRepository
30+
*/
31+
protected $repository;
32+
2533
/**
2634
* Create a new middleware instance.
2735
*
2836
* @param \League\OAuth2\Server\ResourceServer $server
37+
* @param \Laravel\Passport\TokenRepository $repository
2938
* @return void
3039
*/
31-
public function __construct(ResourceServer $server)
40+
public function __construct(ResourceServer $server, TokenRepository $repository)
3241
{
3342
$this->server = $server;
43+
$this->repository = $repository;
3444
}
3545

3646
/**
@@ -57,28 +67,35 @@ public function handle($request, Closure $next, ...$scopes)
5767
throw new AuthenticationException;
5868
}
5969

60-
if ($this->validateScopes($psr, $scopes)) {
70+
if ($this->validate($psr, $scopes)) {
6171
return $next($request);
6272
}
6373

6474
throw new MissingScopeException($scopes);
6575
}
6676

6777
/**
68-
* Validate the scopes on the incoming request.
78+
* Validate the scopes and token on the incoming request.
6979
*
7080
* @param \Psr\Http\Message\ServerRequestInterface $psr
7181
* @param array $scopes
7282
* @return bool
83+
* @throws \Illuminate\Auth\AuthenticationException
7384
*/
74-
protected function validateScopes($psr, $scopes)
85+
protected function validate($psr, $scopes)
7586
{
76-
if (in_array('*', $tokenScopes = $psr->getAttribute('oauth_scopes'))) {
87+
$token = $this->repository->find($psr->getAttribute('oauth_access_token_id'));
88+
89+
if (! $token || $token->client->firstParty()) {
90+
throw new AuthenticationException;
91+
}
92+
93+
if (in_array('*', $token->scopes)) {
7794
return true;
7895
}
7996

8097
foreach ($scopes as $scope) {
81-
if (in_array($scope, $tokenScopes)) {
98+
if ($token->can($scope)) {
8299
return true;
83100
}
84101
}

tests/CheckClientCredentialsForAnyScopeTest.php

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
namespace Laravel\Passport\Tests;
44

55
use Mockery as m;
6+
use Laravel\Passport\Token;
67
use Illuminate\Http\Request;
8+
use Laravel\Passport\Client;
79
use PHPUnit\Framework\TestCase;
10+
use Laravel\Passport\TokenRepository;
811
use League\OAuth2\Server\ResourceServer;
912
use League\OAuth2\Server\Exception\OAuthServerException;
1013
use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope;
@@ -25,7 +28,17 @@ public function test_request_is_passed_along_if_token_is_valid()
2528
$psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token');
2629
$psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']);
2730

28-
$middleware = new CheckClientCredentialsForAnyScope($resourceServer);
31+
$client = m::mock(Client::class);
32+
$client->shouldReceive('firstParty')->andReturnFalse();
33+
34+
$token = m::mock(Token::class);
35+
$token->shouldReceive('getAttribute')->with('client')->andReturn($client);
36+
$token->shouldReceive('getAttribute')->with('scopes')->andReturn(['*']);
37+
38+
$tokenRepository = m::mock(TokenRepository::class);
39+
$tokenRepository->shouldReceive('find')->with('token')->andReturn($token);
40+
41+
$middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository);
2942

3043
$request = Request::create('/');
3144
$request->headers->set('Authorization', 'Bearer token');
@@ -46,7 +59,19 @@ public function test_request_is_passed_along_if_token_has_any_required_scope()
4659
$psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token');
4760
$psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['foo', 'bar', 'baz']);
4861

49-
$middleware = new CheckClientCredentialsForAnyScope($resourceServer);
62+
$client = m::mock(Client::class);
63+
$client->shouldReceive('firstParty')->andReturnFalse();
64+
65+
$token = m::mock(Token::class);
66+
$token->shouldReceive('getAttribute')->with('client')->andReturn($client);
67+
$token->shouldReceive('getAttribute')->with('scopes')->andReturn(['foo', 'bar', 'baz']);
68+
$token->shouldReceive('can')->with('notfoo')->andReturnFalse();
69+
$token->shouldReceive('can')->with('bar')->andReturnTrue();
70+
71+
$tokenRepository = m::mock(TokenRepository::class);
72+
$tokenRepository->shouldReceive('find')->with('token')->andReturn($token);
73+
74+
$middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository);
5075

5176
$request = Request::create('/');
5277
$request->headers->set('Authorization', 'Bearer token');
@@ -63,12 +88,13 @@ public function test_request_is_passed_along_if_token_has_any_required_scope()
6388
*/
6489
public function test_exception_is_thrown_when_oauth_throws_exception()
6590
{
91+
$tokenRepository = m::mock(TokenRepository::class);
6692
$resourceServer = m::mock(ResourceServer::class);
6793
$resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow(
6894
new OAuthServerException('message', 500, 'error type')
6995
);
7096

71-
$middleware = new CheckClientCredentialsForAnyScope($resourceServer);
97+
$middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository);
7298

7399
$request = Request::create('/');
74100
$request->headers->set('Authorization', 'Bearer token');
@@ -90,7 +116,19 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scope()
90116
$psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token');
91117
$psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['foo', 'bar']);
92118

93-
$middleware = new CheckClientCredentialsForAnyScope($resourceServer);
119+
$client = m::mock(Client::class);
120+
$client->shouldReceive('firstParty')->andReturnFalse();
121+
122+
$token = m::mock(Token::class);
123+
$token->shouldReceive('getAttribute')->with('client')->andReturn($client);
124+
$token->shouldReceive('getAttribute')->with('scopes')->andReturn(['foo', 'bar']);
125+
$token->shouldReceive('can')->with('baz')->andReturnFalse();
126+
$token->shouldReceive('can')->with('notbar')->andReturnFalse();
127+
128+
$tokenRepository = m::mock(TokenRepository::class);
129+
$tokenRepository->shouldReceive('find')->with('token')->andReturn($token);
130+
131+
$middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository);
94132

95133
$request = Request::create('/');
96134
$request->headers->set('Authorization', 'Bearer token');
@@ -99,4 +137,35 @@ public function test_exception_is_thrown_if_token_does_not_have_required_scope()
99137
return 'response';
100138
}, 'baz', 'notbar');
101139
}
140+
141+
/**
142+
* @expectedException \Illuminate\Auth\AuthenticationException
143+
*/
144+
public function test_exception_is_thrown_if_token_belongs_to_first_party_client()
145+
{
146+
$resourceServer = m::mock(ResourceServer::class);
147+
$resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock());
148+
$psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1);
149+
$psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1);
150+
$psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token');
151+
$psr->shouldReceive('getAttribute')->with('oauth_scopes')->andReturn(['*']);
152+
153+
$client = m::mock(Client::class);
154+
$client->shouldReceive('firstParty')->andReturnTrue();
155+
156+
$token = m::mock(Token::class);
157+
$token->shouldReceive('getAttribute')->with('client')->andReturn($client);
158+
159+
$tokenRepository = m::mock(TokenRepository::class);
160+
$tokenRepository->shouldReceive('find')->with('token')->andReturn($token);
161+
162+
$middleware = new CheckClientCredentialsForAnyScope($resourceServer, $tokenRepository);
163+
164+
$request = Request::create('/');
165+
$request->headers->set('Authorization', 'Bearer token');
166+
167+
$response = $middleware->handle($request, function () {
168+
return 'response';
169+
});
170+
}
102171
}

0 commit comments

Comments
 (0)