I'm following this tutorial https://medium.com/tech-tajawal/jwt-authentication-for-lumen-5-6-2376fd38d454 to learn how to setup a tokenbased authentication for my lumen backend.
So far, everything worked fine. Only in the end it turns out that I cant get a token Oo
I don't think that theres anything wrong with my code.
When using RESTClient to do an http-Request to: "http://localhost:8080/users"
I get the desired "'error' : 'Token not provided'"
However, when I try to get the token as described in the tutorial, I get errors that the name and e-mail field aren't provided.
Here is my controller code (or the code from the tutorial) which evaluates the request for the transmitted name and email values:
<?php
namespace App\Http\Controllers;
use Validator;
use App\User;
use Firebase\JWT\JWT;
use Illuminate\Http\Request;
use Firebase\JWT\ExpiredException;
use Illuminate\Support\Facades\Hash;
use Laravel\Lumen\Routing\Controller as BaseController;
class AuthController extends BaseController
{
/**
* The request instance.
*
* #var \Illuminate\Http\Request
*/
private $request;
/**
* Create a new controller instance.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
public function __construct(Request $request) {
$this->request = $request;
}
/**
* Create a new token.
*
* #param \App\User $user
* #return string
*/
protected function jwt(User $user) {
$payload = [
'iss' => "lumen-jwt", // Issuer of the token
'sub' => $user->id, // Subject of the token
'iat' => time(), // Time when JWT was issued.
'exp' => time() + 60*60 // Expiration time
];
// As you can see we are passing `JWT_SECRET` as the second parameter that will
// be used to decode the token in the future.
return JWT::encode($payload, env('JWT_SECRET'));
}
/**
* Authenticate a user and return the token if the provided credentials are correct.
*
* #param \App\User $user
* #return mixed
*/
public function authenticate(User $user) {
$this->validate($this->request, [
'email' => 'required|email',
'password' => 'required'
]);
// Find the user by email
$user = User::where('email', $this->request->input('email'))->first();
if (!$user) {
// You wil probably have some sort of helpers or whatever
// to make sure that you have the same response format for
// differents kind of responses. But let's return the
// below respose for now.
return response()->json([
'error' => 'Email does not exist.'
], 400);
}
// Verify the password and generate the token
if (Hash::check($this->request->input('password'), $user->password)) {
return response()->json([
'token' => $this->jwt($user)
], 200);
}
// Bad Request response
return response()->json([
'error' => 'Email or password is wrong.'
], 400);
}
}
And here is the code of the middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Exception;
use App\User;
use Firebase\JWT\JWT;
use Firebase\JWT\ExpiredException;
class JwtMiddleware
{
public function handle($request, Closure $next, $guard = null)
{
$token = $request->get('token');
if(!$token) {
// Unauthorized response if token not there
return response()->json([
'error' => 'Token not provided.'
], 401);
}
try {
$credentials = JWT::decode($token, env('JWT_SECRET'), ['HS256']);
} catch(ExpiredException $e) {
return response()->json([
'error' => 'Provided token is expired.'
], 400);
} catch(Exception $e) {
return response()->json([
'error' => 'An error while decoding token.'
], 400);
}
$user = User::find($credentials->sub);
// Now let's put the user in the request class so that you can grab it from there
$request->auth = $user;
return $next($request);
}
}
Which I have registered in bootstrap/app.php:
$app->routeMiddleware([
'jwt.auth' => App\Http\Middleware\JwTMiddleware::class,
]);
But my JSON Payload looks like this so it SHOULD work.
[
{
"email": "ibeier#hotmail.com,
"name": "Eusebio Dach",
}
]
However I must admit that the tutorial in this section was a bit lacking in the details.
Here is that (last) part which I cant get to work:
"
To make this privious request successful we need to provide the token as query parameter. We can get the token by hitting the following route http://localhost:8000/auth/login inside Postman application. Now that you have the token open the priviously failed request and this time in the Params section create a key token and set it’s value to the token that you received in previous request. And after that send the request to http://localhost/users route and you will get the users list in response.
(Screenshot with userdata, see tutorial)
And that about wraps it up. If you have any questions feel free to leave your comments below.
"
I'm not sure whether I provided the correct request data and if I have set all headers correctly.
Maybe someone with a bit more knowledge in this can help me understanding what I am missing.
I already tried looking into other tutorials but these take different jwt extensions for their lumen and also seem to take other approaches in their controller code etc..
I'd very much like to follow this tutorial since its approach seemed pretty straight-forward to me.
It would also help if someone could tell me that the tutorial worked for them, and maybe also tell me what they did in addition to the instructions provided through the tutorial.
Because then I would just do the tutorial again and see if I can get it working.
Related
I'm currently working on a Laravel 8 project, I have two projects:
A Laravel 8 project used as an API, it exposes some endpoints
A Laravel Lumen 8 project which runs on it's own domain.
Both have Cors enabled, and both run on the same domain, I'm having issues with Guzzle in my Lumen project connecting to an endpoint that exists on my Laravel API, here's the scenario and request flow:
A request comes in to: /hub/microservice/fudge-api-reports on the Laravel api, this is it's controller method:
/**
* Route the microservice
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function microservice(Request $request, $service)
{
$validator = Validator::make($request->all(), [
'endpoint' => 'required|string',
'method' => 'required|string|in:post,get',
'data' => 'nullable|array'
]);
if ($validator->fails()) {
return response()->json([
'message' => "One or more fields has been missed or is invalid.",
'errors' => $validator->messages()
], 400);
}
$microservice = Microservice::where('microservice', $service)->first();
if (!$microservice) {
return response()->json([
'message' => "The microservice you're trying to access is invalid or doesn't exist"
], 404);
}
// auth
$auth = 'Bearer ' . $microservice->hub_access_token;
// the url
$url = $microservice->hub_domain . $request->input('endpoint');
// define how to communicate with the microservice
if ($request->input('method') == 'post') {
if ($microservice->hub_access_token) {
$response = Http::timeout(60)->withHeaders([
'Authorization' => $auth
])->post($url, $request->input('data'));
} else {
$response = Http::timeout(60)->post($url, $request->input('data'));
}
} else {
if ($microservice->hub_access_token) {
$response = Http::timeout(60)->withHeaders([
'Authorization' => $auth
])->get($url);
} else {
$response = Http::timeout(60)->get($url);
}
}
// the response from the microservice
return response()->json($response->json(), $response->status());
}
The request then (based on the endpoint and method) goes to the microservice which runs on it's own domain, mine is: http://localhost:8001/, my URL would be a GET request, and would have an access token, so it makes it into the else statement above and into the first if, e.g: http://localhost:8001/api/reports?report=MyReport and has a token as the header.
The request comes into the fudge-api-reports Laravel Lumen project, and goes to a controller method, but first passes through my BeforeMiddleware where it performs a "log in" request back to the Laravel API to authenticate and check the abilities, this part of the middleware is:
<?php
namespace App\Http\Middleware;
use Closure;
use GuzzleHttp\Client;
class BeforeMiddleware
{
/**
* Request attributes
*
*/
public $attributes;
/**
* Get API url
*/
protected function getApiUrl()
{
return rtrim(config('fudge.fudge_api_domain'), '/');
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $ability)
{
$api = $this->getApiUrl();
$token = $request->input('token');
if (!$token && $request->header('Authorization')) {
$token = explode(' ', $request->header('Authorization'))[1];
}
// TODO: this part appears to ALWAYS time out, despite
// http://localhost:8000/api/hub/login working just fine via Postman
$client = new Client([
'base_uri' => $api,
'timeout' => 5
]);
$res = $client->request('POST', '/api/hub/login', [
'token' => $token,
'ability' => "reports:$ability"
]);
// the response
$res = $res->json();
$hasAbility = isset($res['has_ability']) && !empty($res['has_ability']) ? $res['has_ability'] : false;
// not authorised
if (!$hasAbility) {
return response()->json([
'message' => "You aren't authorised"
], 200);
}
// add the hub's user to the request
$request->attributes->add(['has_ability' => $hasAbility]);
// Post-Middleware Action
return $next($request);
}
}
If the Hub log in is successful, then a has_ability is returned with the value of true back to the the middleware, which then goes through the controller method and finally returns the response back to the initial request of: /hub/microservice/fudge-api-reports
My issue
in my BeforeMiddleware my Guzzle POST request always fails, and never returns a response, it always seems to time out accessing my /api/hub/login endpoint that exists in my Laravel project.
It works perfectly fine through Postman, and Cors is enabled, why would this always timeout in the context of the Middleware, what am I missing?
I'm using external identity provider to authenticate users, created a SPA client (got client_id & client_secret), configured API with audience & scope, so once users authenticated they will get access_token (will be authorized) to access multiple custom micro-services (APIs).
When my custom API receives a request with a bearer Access Token (JWT) the first thing to do is to validate the token. In order to validate JWT I need to follow these steps:
Check that the JWT is well formed (Parse the JWT)
Check the signature. My external identity provider only supports RS256 via the JWKS (JSON Web Key Set) URL (https://{domain}/.well-known/jwks.json), so I can get my public key following this URL.
Validate the standard claims
Check the Application permissions (scopes)
There are a lot of packages/libraries (i.e. https://github.com/tymondesigns/jwt-auth) to create JWT tokens but I can't find any to validate it using those steps above. Could anyone please help to find suitable Laravel/PHP package/library or move me to the right direction in order to achieve my goals (especially point #2).
I did something similar in the past, I don't know if this may help but I'll give it a try. To use a public key, you should download it, put it somewhere on the disk (storage/jwt/public.pem for example) and then link it in the jwt config config/jwt.php with the ALGO (you can see supported algorithms here
'keys' => [
// ...
'public' => 'file://'.storage_path('jwt/public.pem'),
// ...
],
'algo' => 'RS256',
Then, you should have a custom Guard, let's call it JWTGuard:
<?php
namespace App\Guard;use App\Models\User;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Tymon\JWTAuth\JWT;class JWTGuard implements Guard
{
use GuardHelpers;
/**
* #var JWT $jwt
*/
protected JWT $jwt;
/**
* #var Request $request
*/
protected Request $request;
/**
* JWTGuard constructor.
* #param JWT $jwt
* #param Request $request
*/
public function __construct(JWT $jwt, Request $request) {
$this->jwt = $jwt;
$this->request = $request;
}
public function user() {
if (! is_null($this->user)) {
return $this->user;
}
if ($this->jwt->setRequest($this->request)->getToken() && $this->jwt->check()) {
$id = $this->jwt->payload()->get('sub');
$this->user = new User();
$this->user->id = $id;
// Set data from custom claims
return $this->user;
}
return null;
}
public function validate(array $credentials = []) { }
}
This should do all your logic of validation, I used a custom user implementation, the class signature was like:
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements AuthenticatableContract {
// custom implementation
}
Finally, you should register the guard in the AuthServiceProvider and in the auth config
public function boot()
{
$this->registerPolicies();
$this->app['auth']->extend(
'jwt-auth',
function ($app, $name, array $config) {
$guard = new JWTGuard(
$app['tymon.jwt'],
$app['request']
);
$app->refresh('request', $guard, 'setRequest');
return $guard;
}
);
}
then allow it in the config
<?php
return [
'defaults' => [
'guard' => 'jwt',
'passwords' => 'users',
],
'guards' => [
// ...
'jwt' => [
'driver' => 'jwt-auth',
'provider' => 'users'
],
],
// ...
];
You can then use it as a middleware like this:
Route::middleware('auth:jwt')->get('/user', function() {
return Auth::user();
}
Does this sound good to you?
In the end I've used the Auth0 SDK for Laravel - https://auth0.com/docs/quickstart/backend/laravel/01-authorization. Nice and clean solution.
I am building an API and I am using Laravel Passport for authentication.
The API is being used for our mobile app so we're using the Password Grant Client.
Everything works great, and a user can login to get an access token. We have created a register endpoint which allows a user to sign up. We need the API to return an access token at this point too.
Looking through the docs there is no way to create an access token programmatically.
How can I create an access token for a Password Grant Client in my controller? I obviously don't want to do a HTTP request to my own API to get it.
I know I can use a Personal Access Grant Client and call createToken on the user model, but that means the access token is associated with a different Client. This doesn't seem right to me.
Try something like this
class UserController extends Controller
{
protected function login(Request $request)
{
$request->request->add([
'grant_type' => 'password',
'client_id' => '3',
'client_secret' => '6BHCRpB4tpXnQvC1DmpT7CXCSz7ukdw7IeZofiKn',
'scope' => '*'
]);
// forward the request to the oauth token request endpoint
$tokenRequest = Request::create('/oauth/token','post');
return Route::dispatch($tokenRequest);
}
}
I've been toying with Passport for a couple of weeks now and from what I've seen in the documentation it doesn't expose many of the methods it uses for creating tokens. While you may not easily be able to "create an access token for a Password Grant Client in my controller" - what you can do is use Route::dispatch to forward the request for a token to your Passport Password Grant route.
To do this in the controller you are using to issue tokens, use the AuthenticatesUsers trait so you have access to the Password Grant route, create a request, and dispatch that request to the Password Grant route:
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class IssueTokensController extends Controller
{
use AuthenticatesUsers;
protected function issueApiToken(Request $request)
{
// forward the request to the oauth token request endpoint
$tokenRequest = Request::create(
'/oauth/token',
'post'
);
return Route::dispatch($tokenRequest);
}
}
This method of course requires you to have set up Passport and a Password Grant Client.
This answer is based off of another answer to a similar question by Raymond Lagonda - see https://stackoverflow.com/a/40433000/4991377
Patrick has got the right idea, and this is what I ended up doing:
(I don't think Sanju's answer is right because you need to make a http request)
<?php
namespace MyApp\Http\Controllers\API;
use Illuminate\Http\Request;
use Laravel\Passport\Http\Controllers\ConvertsPsrResponses;
use League\OAuth2\Server\AuthorizationServer;
use MyApp\Http\Controllers\APIController;
use Illuminate\Auth\AuthenticationException;
use Zend\Diactoros\ServerRequest;
use Zend\Diactoros\Response as Psr7Response;
class LoginController extends APIController
{
use ConvertsPsrResponses;
/**
*
* #param Request $request
* #param AuthorizationServer $authServer
* #return \Illuminate\Http\JsonResponse
* #throws AuthenticationException
* #throws \League\OAuth2\Server\Exception\OAuthServerException
*/
public function login(Request $request, AuthorizationServer $authServer)
{
$token = $this->getPasswordToken($request, $authServer);
$data = [
"token_details" => $token,
];
return $this->successResponse(
'Successful Login',
200,
$data
);
}
/**
* #param $request
* #param AuthorizationServer $authServer
* #return mixed
* #throws \League\OAuth2\Server\Exception\OAuthServerException
*/
private function getPasswordToken($request, AuthorizationServer $authServer)
{
$parsedBody = [
'grant_type' => 'password',
'client_id' => config('app.client_id'),
'client_secret' => config('app.client_secret'),
'username' => $request->username,
'password' => $request->password,
'scope' => '',
];
$serverRequest = new ServerRequest(
$request->server(),
[],
null,
$request->method(),
'php://input',
$request->header(),
[],
[],
$parsedBody
);
$response = $this->convertResponse(
$authServer->respondToAccessTokenRequest($serverRequest, new Psr7Response)
);
return json_decode($response->getContent());
}
}
I know I can use a Personal Access Grant Client and call createToken on the user model, but that means the access token is associated with a different Client
not sure what you mean by that, could you explain more?
Now this is not ideal but you might be able to inject \League\OAuth2\Server\Grant\PasswordGrant and use
respondToAccessTokenRequest(ServerRequestInterface $request
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL)
you would have to build all those objects, but this is the only public method for password that returns any token information.
I'm writing a tiny sms gateway to be consumed by a couple of projects,
I implemented laravel passport authentication (client credentials grant token)
Then I've added CheckClientCredentials to api middleware group:
protected $middlewareGroups = [
'web' => [
...
],
'api' => [
'throttle:60,1',
'bindings',
\Laravel\Passport\Http\Middleware\CheckClientCredentials::class
],
];
The logic is working fine, now in my controller I need to get client associated with a valid token.
routes.php
Route::post('/sms', function(Request $request) {
// save the sms along with the client id and send it
$client_id = ''; // get the client id somehow
sendSms($request->text, $request->to, $client_id);
});
For obvious security reasons I can never send the client id with the consumer request e.g. $client_id = $request->client_id;.
I use this, to access the authenticated client app...
$bearerToken = $request->bearerToken();
$tokenId = (new \Lcobucci\JWT\Parser())->parse($bearerToken)->getHeader('jti');
$client = \Laravel\Passport\Token::find($tokenId)->client;
$client_id = $client->id;
$client_secret = $client->secret;
Source
However the answer is quite late, i got some errors extracting the JTI header
in Laravel 6.x because the JTI is no longer in the header, but only in the payload/claim. (Using client grants)
local.ERROR: Requested header is not configured {"exception":"[object] (OutOfBoundsException(code: 0): Requested header is not configured at /..somewhere/vendor/lcobucci/jwt/src/Token.php:112)
Also, adding it in a middleware was not an option for me. As i needed it on several places in my app.
So i extended the original Laravel Passport Client (oauth_clients) model.
And check the header as well as the payload. Allowing to pass a request, or use
the request facade, if no request was passed.
<?php
namespace App\Models;
use Illuminate\Support\Facades\Request as RequestFacade;
use Illuminate\Http\Request;
use Laravel\Passport\Client;
use Laravel\Passport\Token;
use Lcobucci\JWT\Parser;
class OAuthClient extends Client
{
public static function findByRequest(?Request $request = null) : ?OAuthClient
{
$bearerToken = $request !== null ? $request->bearerToken() : RequestFacade::bearerToken();
$parsedJwt = (new Parser())->parse($bearerToken);
if ($parsedJwt->hasHeader('jti')) {
$tokenId = $parsedJwt->getHeader('jti');
} elseif ($parsedJwt->hasClaim('jti')) {
$tokenId = $parsedJwt->getClaim('jti');
} else {
Log::error('Invalid JWT token, Unable to find JTI header');
return null;
}
$clientId = Token::find($tokenId)->client->id;
return (new static)->findOrFail($clientId);
}
}
Now you can use it anywhere inside your laravel app like this:
If you have $request object available, (for example from a controller)
$client = OAuthClient::findByRequest($request);
Or even if the request is not available somehow, you can use it without, like this:
$client = OAuthClient::findByRequest();
Hopefully this useful for anyone, facing this issue today.
There is a tricky method.
You can modify the method of handle in the middleware CheckClientCredentials, just add this line.
$request["oauth_client_id"] = $psr->getAttribute('oauth_client_id');
Then you can get client_id in controller's function:
public function info(\Illuminate\Http\Request $request)
{
var_dump($request->oauth_client_id);
}
The OAuth token and client information are stored as a protected variable in the Laravel\Passport\HasApiTokens trait (which you add to your User model).
So simply add a getter method to your User model to expose the OAuth information:
public function get_oauth_client(){
return $this->accessToken->client;
}
This will return an Eloquent model for the oauth_clients table
In the latest implementation you can use:
use Laravel\Passport\Token;
use Lcobucci\JWT\Configuration;
$bearerToken = request()->bearerToken();
$tokenId = Configuration::forUnsecuredSigner()->parser()->parse($bearerToken)->claims()->get('jti');
$client = Token::find($tokenId)->client;
as suggested here: https://github.com/laravel/passport/issues/124#issuecomment-784731969
So, no answers ...
I was able to resolve the issue by consuming my own API, finally I came up with simpler authentication flow, the client need to send their id & secret with each request, then I consumed my own /oauth/token route with the sent credentials, inspired by Esben Petersen blog post.
Once the access token is generated, I append it to the headers of Symfony\Request instance which is under processing.
My final output like this:
<?php
namespace App\Http\Middleware;
use Request;
use Closure;
class AddAccessTokenHeader
{
/**
* Octipus\ApiConsumer
* #var ApiConsumer
*/
private $apiConsumer;
function __construct() {
$this->apiConsumer = app()->make('apiconsumer');
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$response = $this->apiConsumer->post('/oauth/token', $request->input(), [
'content-type' => 'application/json'
]);
if (!$response->isSuccessful()) {
return response($response->getContent(), 401)
->header('content-type', 'application/json');
}
$response = json_decode($response->getContent(), true);
$request->headers->add([
'Authorization' => 'Bearer ' . $response['access_token'],
'X-Requested-With' => 'XMLHttpRequest'
]);
return $next($request);
}
}
I used the above middleware in conjunction with Passport's CheckClientCredentials.
protected $middlewareGroups = [
'web' => [
...
],
'api' => [
'throttle:60,1',
'bindings',
\App\Http\Middleware\AddAccessTokenHeader::class,
\Laravel\Passport\Http\Middleware\CheckClientCredentials::class
],
];
This way, I was able to insure that $request->input('client_id') is reliable and can't be faked.
I dug into CheckClientCredentials class and extracted what I needed to get the client_id from the token. aud claim is where the client_id is stored.
<?php
Route::middleware('client')->group(function() {
Route::get('/client-id', function (Request $request) {
$jwt = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $request->header('authorization')));
$token = (new \Lcobucci\JWT\Parser())->parse($jwt);
return ['client_id' => $token->getClaim('aud')];
});
});
Few places to refactor this to in order to easily access but that will be up to your application
As I can see the above answer are old and most importantly it dose not work with laravel 8 and php 8, so I have found a way to get the client id of the access token ( current request )
the answer is basically making a middleware, and add it to all routes you want to get the client id.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Nyholm\Psr7\Factory\Psr17Factory;
use Laravel\Passport\TokenRepository;
use League\OAuth2\Server\ResourceServer;
use Illuminate\Auth\AuthenticationException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
class SetPassportClient
{
/**
* The Resource Server instance.
*
* #var \League\OAuth2\Server\ResourceServer
*/
protected $server;
/**
* Token Repository.
*
* #var \Laravel\Passport\TokenRepository
*/
protected $repository;
/**
* Create a new middleware instance.
*
* #param \League\OAuth2\Server\ResourceServer $server
* #param \Laravel\Passport\TokenRepository $repository
* #return void
*/
public function __construct(ResourceServer $server, TokenRepository $repository)
{
$this->server = $server;
$this->repository = $repository;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
$psr = (new PsrHttpFactory(
new Psr17Factory,
new Psr17Factory,
new Psr17Factory,
new Psr17Factory
))->createRequest($request);
try {
$psr = $this->server->validateAuthenticatedRequest($psr);
} catch (OAuthServerException $e) {
throw new AuthenticationException;
}
$token = $this->repository->find($psr->getAttribute('oauth_access_token_id'));
if (!$token)
abort(401);
$request->merge(['passportClientId' => $token->client_id]);
return $next($request);
}
}
Add the middleware to app\Http\Kernel.php
protected $routeMiddleware = [
.
.
'passport.client.set' => \App\Http\Middleware\SetPassportClient::class
];
Finaly in the routes add the middleware
Route::middleware(['client', 'passport.client.set'])->get('/test-client-id', function (Request $request){
dd($request->passportClientId); // this the client id
});
Sorry for the long answer, but I want it to be very clear to any all.
All of the code was inspired by laravel CheckCredentials.php
public function handle($request, Closure $next, $scope)
{
if (!empty($scope)) {
$psr = (new DiactorosFactory)->createRequest($request);
$psr = $this->server->validateAuthenticatedRequest($psr);
$clientId = $psr->getAttribute('oauth_client_id');
$request['oauth_client_id'] = intval($clientId);
}
return $next($request);
}
put above to your middleware file, then you can access client_id by request()->oauth_client_id
In a method you can easily get by:
$token = $request->user()->token();
$clientId = $token['client_id'];
Trying to get the header authorization key in controller for making an API. Request is making from fiddler.
$headers = apache_request_headers();
And the $header contains an array.
Array
(
[User-Agent] => Fiddler
[Host] => localhost:8000
[Content-Length] => 102
[Authorization] => TestKey
)
If am trying like this to fetch the Authorization , its throwing error.
$header['Authorization]
Error :
Undefined index: Authorization
Tried many ways to get the authorization, but not working anything. Is there any way to fetch this?
To get headers from the request you should use the Request class
public function yourControllerFunction(\Illuminate\Http\Request $request)
{
$header = $request->header('Authorization');
// do some stuff
}
See https://laravel.com/api/5.5/Illuminate/Http/Request.html#method_header
Though it's an old topic, it might be useful for somebody...
In new Laravel versions, it's possible to get bearer Authorization token directly by calling Illuminate\Http\Request's bearerToken() method:
Auth::viaRequest('costom-token', function (Request $request) {
$token = $request->bearerToken();
// ...
});
Or directly from a controller:
public function index(Request $request) {
Log::info($request->bearerToken());
// ...
}
If you use a specific package like "JWT" or "sanctum" you can use their own middleware to retrieve user information.
Also, Laravel provides many ways to get the authorization key like :
$request->bearerToken(); to get only token without 'Bearer' word the result will be like 44|9rJp2TWvTTpWy535S1Rq2DF0AEmYbEotwydkYCZ3.
$request->header('Authorization'); to get the full key like Bearer 44|9rJp2TWvTTpWy535S1Rq2DF0AEmYbEotwydkYCZ3
P.S. you can use request() shortcut instead of using $request variable
You can try install the jwt(JSON Web Token Authentication for Laravel & Lumen) http://jwt-auth.com via composer.
And create a middleware that verify if exists yours token key in the header request.
After to install jwt, Your middleware it could be as follows
<?php
namespace App\Http\Middleware;
use Closure;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class VerifyJWTToken
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
try {
$user = JWTAuth::toUser($request->header('token'));
} catch (JWTException $e) {
if ($e instanceof TokenExpiredException) {
return response()->json([
'error' => 'token_expired',
'code' => $e->getStatusCode()
], $e->getStatusCode());
}
else if($e instanceof TokenInvalidException){
return response()->json([
'error' => "token_invalid",
'code' => $e->getStatusCode()
], $e->getStatusCode());
}
else {
return response()->json([
'error' => 'Token is required',
'code' => $e->getStatusCode(),
], $e->getStatusCode());
}
}
return $next($request);
}
}
I used token for example for a header key, but you can name it, as you like.
Then you could use this on any controller
There is a simple way to get headers in any file or controller with $_SERVER.
print_r($_SERVER); // check your header here
then, you can simply get your header:
$AuthToken = $_SERVER['HTTP_AUTHORIZATION'];