Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save messi89/489473c053e3ea8d9e034b0032effb1d to your computer and use it in GitHub Desktop.
Save messi89/489473c053e3ea8d9e034b0032effb1d to your computer and use it in GitHub Desktop.
Laravel Passport - Customize The Token Response
<?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
}
}
}
@subtainishfaq7175
Copy link

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 ?

@njxqlus
Copy link

njxqlus commented Sep 27, 2017

Call to undefined method Illuminate\Http\Response::getBody()

@nauvalazhar
Copy link

Work for me (Laravel 5.4)

  1. Add new route in your api.php file.
Route::post('oauth/token', 'AccessTokenController@issueToken');
  1. 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);
        }
    }
}
  1. 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!

@leandroruel
Copy link

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

@imphinite
Copy link

This solution still works on Laravel Framework 5.5.26 as of 2018-01-17. Thank you, saved my day.

@messi89
Copy link
Author

messi89 commented Apr 13, 2018

@njxqlus use the facade Response...like in my Controller
use Response;

@ponnuchamy51
Copy link

Thanks this is works for me. what about refreshToken? if you know then share.

@ilhamsa1
Copy link

ilhamsa1 commented Jul 26, 2018

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']);

@T0miii
Copy link

T0miii commented Nov 26, 2018

Is there a way to do the same with Code Grant? I dont have the username, nor the password in the request.

@hallids
Copy link

hallids commented Jan 4, 2019

The best way I have found to do this is by extending the BearerTokenResponse class - see this answer on stack overflow

@xlcrr
Copy link

xlcrr commented Jan 5, 2019

Thanks for the solution!

@leandroruel

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

@juanm18
Copy link

juanm18 commented Mar 7, 2019

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

@rubanraj54
Copy link

The best way I have found to do this is by extending the BearerTokenResponse class - see this answer on stack overflow

I would say, this is a clean solution. I tested in laravel 5.8 and it is working.

@mikizdr
Copy link

mikizdr commented Dec 1, 2019

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.

@chakravarthykalyan90
Copy link

Hi Messi, it worked for me. Thanks for the help.

@bakiro
Copy link

bakiro commented Oct 9, 2021

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);
        }
    }
}

@zendi014
Copy link

@bakiro is that running on Laravel 8.83.27? the route on /oauth/token always retrun null

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