Skip to content

Instantly share code, notes, and snippets.

@realshadow
Last active March 27, 2019 18:12
Show Gist options
  • Save realshadow/f01b7bc781e089a21c64f56c565e29e2 to your computer and use it in GitHub Desktop.
Save realshadow/f01b7bc781e089a21c64f56c565e29e2 to your computer and use it in GitHub Desktop.
<?php
/*
|--------------------------------------------------------------------------
| Authentication Providers
|--------------------------------------------------------------------------
|
| The authentication providers that should be used when attempting to
| authenticate an incoming API request.
|
*/
'auth' => [
'oauth' => App\Auth\Providers\Dingo\PassportProvider::class,
],
<?php
$this->app->make(\Dingo\Api\Auth\Auth::class)->extend('oauth', function (Application $app) {
$provider = new PassportProvider(
$app->make(ResourceServer::class),
$app->make(TokenRepository::class)
);
$provider->setClientResolver(function (Token $token) {
return $token->client_id;
});
$provider->setUserResolver(function (Token $token) use ($app) {
/** @var LoginService $service */
$service = $app->make(LoginService::class);
return $service->loginUsingPassport($token);
});
return $provider;
});
<?php
namespace App\Auth\Providers\Dingo;
use Dingo\Api\Auth\Provider\Authorization;
use Dingo\Api\Routing\Route;
use Illuminate\Http\Request;
use Laravel\Passport\Passport;
use Laravel\Passport\Token;
use Laravel\Passport\TokenRepository;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\ResourceServer;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class PassportProvider extends Authorization
{
/**
* @var ResourceServer $server
*/
protected $server;
/**
* @var TokenRepository $tokenRepository
*/
protected $tokenRepository;
/**
* @var $userResolver
*/
protected $userResolver;
/**
* @var $clientResolver
*/
protected $clientResolver;
/**
* Set the resolver to fetch a user.
*
* @param callable $resolver
*
* @return \Dingo\Api\Contract\Auth\Provider
*/
public function setUserResolver(callable $resolver)
{
$this->userResolver = $resolver;
return $this;
}
/**
* Set the resolver to fetch a client.
*
* @param callable $resolver
*
* @return \Dingo\Api\Contract\Auth\Provider
*/
public function setClientResolver(callable $resolver)
{
$this->clientResolver = $resolver;
return $this;
}
/**
* Validate a route has any scopes.
*
* @param Token $token
* @param array $scopes
*
* @return bool
* @throws OAuthServerException
*/
protected function validateAnyRouteScopes(Token $token, array $scopes)
{
if (count($scopes) === 0) {
return true;
}
foreach ($scopes as $scope) {
if ($token->can($scope)) {
return true;
}
}
throw OAuthServerException::invalidRequest('scope');
}
/**
* Validate a route has all scopes
*
* @param Token $token
* @param array $scopes
*
* @return bool
* @throws OAuthServerException
*/
protected function validateAllRouteScopes(Token $token, array $scopes)
{
foreach ($scopes as $scope) {
if (! $token->can($scope)) {
throw OAuthServerException::invalidScope($scope);
}
}
return true;
}
/**
* Resolve the resource owner
*
* @param Token $token
*
* @return mixed
*/
protected function resolveResourceOwner(Token $token)
{
if ( ! $token->user_id) {
return call_user_func($this->clientResolver, $token);
}
return call_user_func($this->userResolver, $token);
}
/**
* @param ResourceServer $server
* @param TokenRepository $tokenRepository
*/
public function __construct(ResourceServer $server, TokenRepository $tokenRepository)
{
$this->server = $server;
$this->tokenRepository = $tokenRepository;
}
/**
* Get the expected authentification method
*
* @return string
*/
public function getAuthorizationMethod()
{
return 'bearer';
}
/**
* Authenticate the request
*
* @param Request $request
* @param Route $route
*
* @return mixed
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*/
public function authenticate(Request $request, Route $route)
{
$this->validateAuthorizationHeader($request);
$psr7request = (new DiactorosFactory)->createRequest($request);
try {
$oauthRequest = $this->server->validateAuthenticatedRequest($psr7request);
$scopes = $route->scopes();
$token = $this->tokenRepository->find($oauthRequest->getAttribute('oauth_access_token_id'));
if ($token->revoked) {
throw OAuthServerException::accessDenied();
}
if ($route->scopeStrict()) {
$this->validateAllRouteScopes($token, $scopes);
} else {
$this->validateAnyRouteScopes($token, $scopes);
}
return $this->resolveResourceOwner($token);
} catch (OAuthServerException $exception) {
throw new UnauthorizedHttpException(
ucfirst($this->getAuthorizationMethod()),
$exception->getMessage(),
$exception
);
}
}
}
@craigwillis85
Copy link

craigwillis85 commented May 3, 2017

@realshadow Do you have an example of your LoginService class? I'd be interested in seeing how you authenticate your users.

@timbroder
Copy link

@realshadow I'd also love a peak at your LoginService class. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment