Skip to content

Instantly share code, notes, and snippets.

@rodriigomedeiros
Created July 9, 2019 11:40
Show Gist options
  • Save rodriigomedeiros/37783dc318061482defe4846f1d851bc to your computer and use it in GitHub Desktop.
Save rodriigomedeiros/37783dc318061482defe4846f1d851bc to your computer and use it in GitHub Desktop.
Route::group(['prefix' => 'profile', 'middleware' => 'scopes:profile'], function () {
Route::get('photos', 'ProfileController@photos');
});
<?php
namespace App\Http\Middleware;
use App\OAuth2\OAuthServerException;
use Closure;
use Illuminate\Auth\AuthenticationException;
use App\OAuth2\Storage\AccessTokenEntity;
use App\OAuth2\Storage\ClientEntity;
use Lcobucci\JWT\Parser;
class CheckScopes
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param array $scopes
*
* @return mixed
* @throws AuthenticationException
*/
public function handle($request, Closure $next, ... $scopes)
{
$tokenId = (new Parser())->parse(request()->bearerToken())->getHeader('jti');
$accessTokenEntity = AccessTokenEntity::find($tokenId);
/** @var \Illuminate\Support\Collection $clientScopes */
$clientScopes = ClientEntity::where('client_id', $accessTokenEntity->client_id)
->first()
->scopes()
->get()
->pluck('scope');
// todo: This condition should exit with time. All clients should implements scopes in your requests.
if($clientScopes->isEmpty()){
return $next($request);
}
$scopesDiff = (collect($scopes))->diff($accessTokenEntity->scopes);
if($scopesDiff->isNotEmpty()){
throw OAuthServerException::insufficientScope();
}
return $next($request);
}
}
<?php
namespace App\Http\Controllers;
use App\OAuth2\OAuthServerException;
use App\OAuth2\Storage\ClientEntity;
use App\OpenIdAuth;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use League\OAuth2\Server\AuthorizationServer;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response as Psr7Response;
class OAuthController extends Controller
{
use HandlesOAuthErrors;
/**
* @param ServerRequestInterface $request
*
* @return Response
* @throws \Throwable
*/
public function accessToken(ServerRequestInterface $request)
{
return $this->withErrorHandling(function () use ($request) {
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = app()->make(AuthorizationServer::class);
$response = new Psr7Response();
// Try to respond to the request
return $server->respondToAccessTokenRequest($request, $response);
});
}
/**
* @param ServerRequestInterface $request
*
* @return Response
* @throws \Throwable
*/
public function oauthAuthorize(ServerRequestInterface $request)
{
return $this->withErrorHandling(function () use ($request) {
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = app()->make(AuthorizationServer::class);
$response = new Psr7Response();
// Validate the HTTP request and return an AuthorizationRequest object.
$authRequest = $server->validateAuthorizationRequest($request);
/** @var ClientEntity $client */
$client = $authRequest->getClient();
$scopesEnabledForClient = $client->scopes()->get()->pluck('scope');
// Checks whether the client has any scope configured.
if($scopesEnabledForClient->isNotEmpty()) {
$scopesRequested = collect( $authRequest->getScopes() )->pluck( 'scope' );
$scopesDiff = $scopesRequested->diff($scopesEnabledForClient);
if($scopesDiff->isNotEmpty()){
throw OAuthServerException::invalidScope($scopesDiff->implode(', '));
}
}
if(!$authRequest->getState()) {
throw OAuthServerException::requiredState();
}
// The auth request object can be serialized and saved into a user's session.
// You will probably want to redirect the user at this point to a login endpoint.
/* @var $user \App\User */
$user = Auth::user();
$serverParams = $request->getServerParams();
$authid = new OpenIdAuth();
$authid->authid = uniqid("", true);
$authid->service = $client->authid_service;
$authid->client_id = $client->getIdentifier();
$authid->redirect_uri = $request->getUri();
$authid->ip_created = $serverParams['REMOTE_ADDR'];
$authid->save();
return redirect()->route('openid.home', [
'authid' => $authid->authid,
]);
// Once the user has logged in set the user on the AuthorizationRequest
$authRequest->setUser($user); // an instance of UserEntityInterface
// At this point you should redirect the user to an authorization page.
// This form will ask the user to approve the client and the scopes requested.
// Once the user has approved or denied the client update the status
// (true = approved, false = denied)
$authRequest->setAuthorizationApproved(true);
// Return the HTTP redirect response
$reponse = $server->completeAuthorizationRequest($authRequest, $response);
return $reponse;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment