-
-
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 ?