-
-
Save messi89/489473c053e3ea8d9e034b0032effb1d to your computer and use it in GitHub Desktop.
| <?php | |
| /** | |
| * Laravel Passport - Customize Token response. | |
| * | |
| * @author Messi89 OVERGEN <@messi89minou> | |
| * @link https://github.com/messi89 | |
| */ | |
| namespace App\Http\Controllers\Api; | |
| use App\Models\User; | |
| use Exception; | |
| use Illuminate\Database\Eloquent\ModelNotFoundException; | |
| use League\OAuth2\Server\Exception\OAuthServerException; | |
| use Psr\Http\Message\ServerRequestInterface; | |
| use Response; | |
| class AccessTokenController extends \Laravel\Passport\Http\Controllers\AccessTokenController | |
| { | |
| public function issueToken(ServerRequestInterface $request) | |
| { | |
| try { | |
| //get username (default is :email) | |
| $username = $request->getParsedBody()['username']; | |
| //get user | |
| $user = User::where('email', '=', $username)->firstOrFail(); | |
| //issuetoken | |
| $tokenResponse = parent::issueToken($request); | |
| //convert response to json string | |
| $content = $tokenResponse->getBody()->__toString(); | |
| //convert json to array | |
| $data = json_decode($content, true); | |
| if(isset($data["error"])) | |
| throw new OAuthServerException('The user credentials were incorrect.', 6, 'invalid_credentials', 401); | |
| //add access token to user | |
| $user = collect($user); | |
| $user->put('access_token', $data['access_token']); | |
| return Response::json(array($user)); | |
| } | |
| catch (ModelNotFoundException $e) { // email notfound | |
| //return error message | |
| } | |
| catch (OAuthServerException $e) { //password not correct..token not granted | |
| //return error message | |
| } | |
| catch (Exception $e) { | |
| ////return error message | |
| } | |
| } | |
| } |
Call to undefined method Illuminate\Http\Response::getBody()
Work for me (Laravel 5.4)
- Add new route in your
api.phpfile.
Route::post('oauth/token', 'AccessTokenController@issueToken');- Create new file in
YourProject/app/Http/Controllers/API/AccessTokenController.php
<?php
namespace App\Http\Controllers\API;
use App\User;
use Exception;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Psr\Http\Message\ServerRequestInterface;
use Response;
use \Laravel\Passport\Http\Controllers\AccessTokenController as ATC;
class AccessTokenController extends ATC
{
public function issueToken(ServerRequestInterface $request)
{
try {
//get username (default is :email)
$username = $request->getParsedBody()['username'];
//get user
//change to 'email' if you want
$user = User::where('username', '=', $username)->first();
//generate token
$tokenResponse = parent::issueToken($request);
//convert response to json string
$content = $tokenResponse->getContent();
//convert json to array
$data = json_decode($content, true);
if(isset($data["error"]))
throw new OAuthServerException('The user credentials were incorrect.', 6, 'invalid_credentials', 401);
//add access token to user
$user = collect($user);
$user->put('access_token', $data['access_token']);
return Response::json(array($user));
}
catch (ModelNotFoundException $e) { // email notfound
//return error message
return response(["message" => "User not found"], 500);
}
catch (OAuthServerException $e) { //password not correct..token not granted
//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);
}
}
}- Testing (JavaScript XHR)
var data = new FormData();
data.append("grant_type", '{your_grant_type}');
data.append("client_id", '{your_client_id}');
data.append("client_secret", "{your_client_secret}");
data.append("username", "{your_username}");
data.append("password", "{your_password}");
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "http://youdomain/api/oauth/token");
xhr.setRequestHeader("accept", "application/json");
xhr.send(data);Hope this helps!
for some reason, when add the route with the custom controller in 5.5 mess up when you type: php artisan route:list, he literally prints the router class at console
This solution still works on Laravel Framework 5.5.26 as of 2018-01-17. Thank you, saved my day.
@njxqlus use the facade Response...like in my Controller
use Response;
Thanks this is works for me. what about refreshToken? if you know then share.
thanks is works... and if you want add refreshToken or expires_is , just add in line 43
//add access token to user
$user = collect($user);
$user->put('access_token', $data['access_token']);
->> $user->put('expires_in', $data['expires_in']);
->> $user->put('refresh_token', $data['refresh_token']);
Is there a way to do the same with Code Grant? I dont have the username, nor the password in the request.
The best way I have found to do this is by extending the BearerTokenResponse class - see this answer on stack overflow
Thanks for the solution!
for some reason, when add the route with the custom controller in 5.5 mess up when you type:
php artisan route:list, he literally prints the router class at console
You can find the new route at /api/oauth/token
is there a way to override the original AccessTokenController so that i do not have to create a new api/oauth/token route?
i just want to override the issueToken method in AccessTokenController so that i still hit the oauth/token endpoint. I have already created a new class AccessTokenController that extends from \Laravel\Passport\Http\Controllers\AccessTokenController but that does not override the method.. am i missing something? @messi89
The best way I have found to do this is by extending the
BearerTokenResponseclass - see this answer on stack overflow
I would say, this is a clean solution. I tested in laravel 5.8 and it is working.
Hello everybody.
Please give an answer you are 100% sure is a real, well tested and accepted solution. Otherwise you make a mess and confusion among people who wants to learn implementing OAuth in a good and secure way. Some writings make a lot of confusion and misunderstanding. All things related to implementation and customizing OAuth token are already present in laravel/passports package. You need nothing more than that. Just exam the package and documentation on Laravel official site.
Hi Messi, it worked for me. Thanks for the help.
Hi there ๐, Laravel 8.54 with Passport 10.1, nice job Messi!!!
<?php
namespace App\Http\Controllers\Auth;
use Exception;
use App\Models\User;
use Psr\Http\Message\ServerRequestInterface;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Laravel\Passport\Exceptions\OAuthServerException;
use Laravel\Passport\Http\Controllers\AccessTokenController as AuthController;
class AccessTokenController extends AuthController
{
public function issueToken(ServerRequestInterface $request)
{
try {
$data = json_decode(parent::issueToken($request)->content(), true);
$user = User::select(["name", "email"])
->where('email', '=', $request->getParsedBody()['username'])
->firstOrFail()
->toArray();
return response()->json(array_merge(["user" => $user], $data));
} catch (ModelNotFoundException $e) {
return response()->json(array(
'error' => array(
'msg' => $e->getMessage(),
'code' => $e->getCode(),
),
), 401);
} catch (OAuthServerException $e) {
return response()->json(array(
'error' => array(
'msg' => $e->getMessage(),
'code' => $e->getCode(),
),
), 401);
} catch (Exception $e) {
return response()->json(array(
'error' => array(
'msg' => $e->getMessage(),
'code' => $e->getCode(),
),
), 500);
}
}
}
@bakiro is that running on Laravel 8.83.27? the route on /oauth/token always retrun null
Hi Messi , Thank you for sharing , I am facing same issue and want to add user info with token response , I will try this gist soon .
did you try it somewhere ?