Created
December 4, 2018 10:03
-
-
Save T0miii/ba63f2154b3a9c03140f5c20daadebec to your computer and use it in GitHub Desktop.
Laravel Passport Code Grant return User when login.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers; | |
use Psr\Http\Message\ServerRequestInterface; | |
use App\Http\Controllers\Traits\UserByAccessToken; | |
use League\OAuth2\Server\Exception\OAuthServerException; | |
use Illuminate\Database\Eloquent\ModelNotFoundException; | |
use \Laravel\Passport\Http\Controllers\AccessTokenController as ATC; | |
class AccessTokenController extends ATC | |
{ | |
use UserByAccessToken; | |
/** | |
* @param ServerRequestInterface $request | |
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Illuminate\Http\Response | |
*/ | |
public function issueToken(ServerRequestInterface $request) | |
{ | |
try { | |
$tokenResponse = parent::issueToken($request); | |
$content = $tokenResponse->getContent(); | |
$data = json_decode($content, true); | |
if (isset($data["error"])) { | |
throw new OAuthServerException('The user credentials were incorrect.', 6, 'invalid_credentials', 401); | |
} | |
$userId = $this->updateSSOCache($data['access_token']); | |
$data['user_id'] = $userId; | |
return response()->json($data); | |
} catch (ModelNotFoundException $e) { | |
//return error message | |
return response(["message" => "User not found"], 500); | |
} catch (OAuthServerException $e) { | |
//return error message | |
return response(["message" => "The user credentials were incorrect.', 6, 'invalid_credentials"], 500); | |
} catch (\Exception $e) { | |
////return error message | |
return response(["message" => "Internal server error"], 500); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers\Traits; | |
use App\User; | |
use Lcobucci\JWT\Parser; | |
use Laravel\Passport\Token; | |
use Illuminate\Support\Facades\Cache; | |
use Laravel\Passport\TokenRepository; | |
trait UserByAccessToken | |
{ | |
/** | |
* @param string $accessToken | |
* @return \Laravel\Passport\Token | |
*/ | |
protected function getTokenByAccessToken(string $accessToken): Token | |
{ | |
$tokenRepository = new TokenRepository(); | |
$jwt = (new Parser())->parse($accessToken); | |
return $tokenRepository->find($jwt->getClaim('jti')); | |
} | |
/** | |
* @param string $accessToken | |
* @return User | |
* @throws \Exception | |
*/ | |
protected function getTokenUser(string $accessToken): User | |
{ | |
$token = $this->getTokenByAccessToken($accessToken); | |
if (!$token) throw new \Exception('Access Token not set'); | |
return User::findOrFail($token->user_id); | |
} | |
/** | |
* @param string $accessToken | |
* @return int | |
* @throws \Exception | |
*/ | |
protected function updateSSOCache(string $accessToken): int | |
{ | |
$user = $this->getTokenUser($accessToken); | |
if (!$user) { | |
throw new \Exception('No User found for Access Token'); | |
} | |
$this->alterCache($user->user_id, $accessToken); | |
return $user->user_id; | |
} | |
/** | |
* @param int $userId | |
* @param string $accessToken | |
* @return Void | |
*/ | |
protected function alterCache(int $userId, string $accessToken): Void | |
{ | |
$userCacheKey = 'user_tokens_' . $userId; | |
$defaultPrefix = Cache::getPrefix(); | |
Cache::setPrefix('sso_auth:'); | |
$cachedData = Cache::get($userCacheKey); | |
if ($cachedData) { | |
$cachedData[] = $accessToken; | |
} else { | |
$cachedData = [$accessToken]; | |
} | |
Cache::add($userCacheKey, $cachedData, 10); | |
Cache::setPrefix($defaultPrefix); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Inspired by a similar Usecase (laravel/passport#143) where someone wanted to get the User returned via Password Grant.
I had similar issue when using Code Grant , that i needed the User more explicit the User ID (for my own "fake SSO" implementation).
Basically after we get the access_token from
$tokenResponse = parent::issueToken($request);
we could call thegetTokenUser
function to get our associated User. After this you just need to return the User as an array with the access_token, refresh and expire_in.Further i needed some kind of SSO implementation. Here we used redis. On the Auth server side i store the access_token associated with the User in redis as an array.
On my Client application i have a middleware wich checks if the User got any tokens in the redis that is equal with that one in the Cookie.
If yess go on, if not check the auth server, and refresh the token in redis.
This is basically just to make less server calls to the auth server. Ofc i destroy the keys in redis when i logout, and beside that they Time To Live is set to like 10 minutes, could be shorter.
Hope this could save some time for some one, some day. Cheers.