Skip to content

Commit

Permalink
Merge pull request #1188 from laravel/auth-token
Browse files Browse the repository at this point in the history
[8.x] Implement auth token for access requests
  • Loading branch information
taylorotwell authored Feb 11, 2020
2 parents e560aa8 + bf6b57d commit b46829b
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 0 deletions.
2 changes: 2 additions & 0 deletions resources/views/authorize.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@

<input type="hidden" name="state" value="{{ $request->state }}">
<input type="hidden" name="client_id" value="{{ $client->id }}">
<input type="hidden" name="auth_token" value="{{ $authToken }}">
<button type="submit" class="btn btn-success btn-approve">Authorize</button>
</form>

Expand All @@ -79,6 +80,7 @@

<input type="hidden" name="state" value="{{ $request->state }}">
<input type="hidden" name="client_id" value="{{ $client->id }}">
<input type="hidden" name="auth_token" value="{{ $authToken }}">
<button class="btn btn-danger">Cancel</button>
</form>
</div>
Expand Down
18 changes: 18 additions & 0 deletions src/Exceptions/InvalidAuthTokenException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Laravel\Passport\Exceptions;

use Illuminate\Auth\Access\AuthorizationException;

class InvalidAuthTokenException extends AuthorizationException
{
/**
* Create a new InvalidAuthTokenException for different auth tokens.
*
* @return static
*/
public static function different()
{
return new static('The provided auth token for the request is different from the session auth token.');
}
}
2 changes: 2 additions & 0 deletions src/Http/Controllers/ApproveAuthorizationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public function __construct(AuthorizationServer $server)
*/
public function approve(Request $request)
{
$this->assertValidAuthToken($request);

$authRequest = $this->getAuthRequestFromSession($request);

return $this->convertResponse(
Expand Down
3 changes: 3 additions & 0 deletions src/Http/Controllers/AuthorizationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Laminas\Diactoros\Response as Psr7Response;
use Laravel\Passport\Bridge\User;
use Laravel\Passport\ClientRepository;
Expand Down Expand Up @@ -73,13 +74,15 @@ public function authorize(ServerRequestInterface $psrRequest,
return $this->approveRequest($authRequest, $user);
}

$request->session()->put('authToken', $authToken = Str::random());
$request->session()->put('authRequest', $authRequest);

return $this->response->view('passport::authorize', [
'client' => $client,
'user' => $user,
'scopes' => $scopes,
'request' => $request,
'authToken' => $authToken,
]);
}

Expand Down
2 changes: 2 additions & 0 deletions src/Http/Controllers/DenyAuthorizationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public function __construct(ResponseFactory $response)
*/
public function deny(Request $request)
{
$this->assertValidAuthToken($request);

$authRequest = $this->getAuthRequestFromSession($request);

$clientUris = Arr::wrap($authRequest->getClient()->getRedirectUri());
Expand Down
16 changes: 16 additions & 0 deletions src/Http/Controllers/RetrievesAuthRequestFromSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,25 @@
use Exception;
use Illuminate\Http\Request;
use Laravel\Passport\Bridge\User;
use Laravel\Passport\Exceptions\InvalidAuthTokenException;

trait RetrievesAuthRequestFromSession
{
/**
* Make sure the auth token matches the one in the session.
*
* @param \Illuminate\Http\Request $request
* @return void
*
* @throws \Laravel\Passport\Exceptions\InvalidAuthTokenException
*/
protected function assertValidAuthToken(Request $request)
{
if ($request->has('auth_token') && $request->session()->get('authToken') !== $request->get('auth_token')) {
throw InvalidAuthTokenException::different();
}
}

/**
* Get the authorization request from the session.
*
Expand Down
6 changes: 6 additions & 0 deletions tests/ApproveAuthorizationControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,17 @@ public function test_complete_authorization_request()

$request = m::mock(Request::class);
$request->shouldReceive('session')->andReturn($session = m::mock());
$request->shouldReceive('has')->with('auth_token')->andReturn(true);
$request->shouldReceive('get')->with('auth_token')->andReturn('foo');

$session->shouldReceive('get')->once()->with('authToken')->andReturn('foo');
$session->shouldReceive('get')
->once()
->with('authRequest')
->andReturn($authRequest = m::mock(AuthorizationRequest::class));

$request->shouldReceive('user')->andReturn(new ApproveAuthorizationControllerFakeUser);

$authRequest->shouldReceive('getClient->getIdentifier')->andReturn(1);
$authRequest->shouldReceive('getUser->getIdentifier')->andReturn(2);
$authRequest->shouldReceive('setUser')->once();
Expand Down
1 change: 1 addition & 0 deletions tests/AuthorizationControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public function test_authorization_view_is_presented()

$request = m::mock(Request::class);
$request->shouldReceive('session')->andReturn($session = m::mock());
$session->shouldReceive('put')->withSomeOfArgs('authToken');
$session->shouldReceive('put')->with('authRequest', $authRequest);
$request->shouldReceive('user')->andReturn($user = m::mock());

Expand Down
15 changes: 15 additions & 0 deletions tests/DenyAuthorizationControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ public function test_authorization_can_be_denied()
$request->shouldReceive('session')->andReturn($session = m::mock());
$request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser);
$request->shouldReceive('input')->with('state')->andReturn('state');
$request->shouldReceive('has')->with('auth_token')->andReturn(true);
$request->shouldReceive('get')->with('auth_token')->andReturn('foo');

$session->shouldReceive('get')->once()->with('authToken')->andReturn('foo');
$session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock(
AuthorizationRequest::class
));
Expand Down Expand Up @@ -56,6 +59,8 @@ public function test_authorization_can_be_denied_with_multiple_redirect_uris()
$request->shouldReceive('session')->andReturn($session = m::mock());
$request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser);
$request->shouldReceive('input')->with('state')->andReturn('state');
$request->shouldReceive('has')->with('auth_token')->andReturn(true);
$request->shouldReceive('get')->with('auth_token')->andReturn('foo');

$session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock(
AuthorizationRequest::class
Expand All @@ -67,6 +72,7 @@ public function test_authorization_can_be_denied_with_multiple_redirect_uris()
$authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost');
$authRequest->shouldReceive('getClient->getRedirectUri')->andReturn(['http://localhost.localdomain', 'http://localhost']);

$session->shouldReceive('get')->once()->with('authToken')->andReturn('foo');
$response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) {
return $url;
});
Expand All @@ -85,7 +91,10 @@ public function test_authorization_can_be_denied_implicit()
$request->shouldReceive('session')->andReturn($session = m::mock());
$request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser);
$request->shouldReceive('input')->with('state')->andReturn('state');
$request->shouldReceive('has')->with('auth_token')->andReturn(true);
$request->shouldReceive('get')->with('auth_token')->andReturn('foo');

$session->shouldReceive('get')->once()->with('authToken')->andReturn('foo');
$session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock(
AuthorizationRequest::class
));
Expand Down Expand Up @@ -114,7 +123,10 @@ public function test_authorization_can_be_denied_with_existing_query_string()
$request->shouldReceive('session')->andReturn($session = m::mock());
$request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser);
$request->shouldReceive('input')->with('state')->andReturn('state');
$request->shouldReceive('has')->with('auth_token')->andReturn(true);
$request->shouldReceive('get')->with('auth_token')->andReturn('foo');

$session->shouldReceive('get')->once()->with('authToken')->andReturn('foo');
$session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock(
AuthorizationRequest::class
));
Expand Down Expand Up @@ -146,7 +158,10 @@ public function test_auth_request_should_exist()
$request->shouldReceive('session')->andReturn($session = m::mock());
$request->shouldReceive('user')->never();
$request->shouldReceive('input')->never();
$request->shouldReceive('has')->with('auth_token')->andReturn(true);
$request->shouldReceive('get')->with('auth_token')->andReturn('foo');

$session->shouldReceive('get')->once()->with('authToken')->andReturn('foo');
$session->shouldReceive('get')->once()->with('authRequest')->andReturnNull();

$response->shouldReceive('redirectTo')->never();
Expand Down

0 comments on commit b46829b

Please sign in to comment.