tymon/jwt-auth for laravel 5.4 refresh token - laravel-5

I recently using laravel 5.4 and I want to use tymon/jwt-auth package to secure my APIs by sending the access token but my issues happened when token expired I can't refresh it before expired and I expected the token will be refreshed automatically
public function handle($request, Closure $next)
{
try{
$user = JWTAuth::parseToken()->authenticate();
}catch (JWTException $e) {
if($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException) {
return response()->json(['token_expired'], $e->getStatusCode());
}else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException) {
return response()->json(['token_invalid'], $e->getStatusCode());
}else{
return response()->json(['error'=>'Token is required']);
}
}
return $next($request);
}

You only need this snippet to do authentication:
$credentials = request(['email', 'password']);
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
Make sure you include jwt.auth & jwt.refresh on middleware at route as follow:
Route::Group(['middleware' => [
'jwt.auth',
'jwt.refresh',
]], function() {
//list your route here
....
....
....
jwt.refresh do refresh your token each time you access the route. And also added this in your .env
JWT_BLACKLIST_GRACE_PERIOD=60
you can adjust the number from 60 seconds to any other values. This setting will set how long the token will valid before refreshed again.

Related

Laravel:Error when Implementing JWT authentication

I am experiencing an error when trying to post the API through Postman to authenticate users in the site.
login function:
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if ($token = $this->guard()->attempt($credentials)) {
return $this->respondWithToken($token);
}
return response()->json(['error' => 'Unauthorized'], 401);
}
the guard function
public function guard()
{
return Auth::guard();
}
The error shown on postman
"message": "Call to undefined method Tymon\\JWTAuth\\Contracts\\Providers\\Auth::guard()",
"exception": "Symfony\\Component\\Debug\\Exception\\FatalThrowableError",
How to solve this?
You can use \JWTAuth::attempt function in order to get token if the user inserts valid email and password like:
....
use Tymon\JWTAuth\Exceptions\JWTException;
....
try {
$token = \JWTAuth::attempt($request->only('email', 'password'));
return $this->respondWithToken($token);
} catch (JWTException $exception) {
return response()->json([
'status' => false,
'data' => null,
'message' => 'Could not create token'
]);
}
EDIT 1
The above answer you submitted is correct.
try replacing Auth::guard() to Auth::guard('api')
public function guard()
{
return Auth::guard('api');
}
For more information there is a similar issue in GitHub for reference
Use a construct method like
public function __construct(){
auth()->setDefaultDriver('api');
}
and your login function like
public function login(){
$credentials = request(['email', 'password']);
if(!$token = auth()->attempt($credentials)){
return response()->json(['error' => 'Incorrect email/password'], 401);
}
return $this->respondWithToken($token);
}
And comment out your guard function
I have faced this problem continuously. But the solution was when I used bcrypt() on the password.
bcrypt($password);
Use dependency injection and inject the Auth interface into your class. Code example below.
From the Tymon package import the Auth interface.
use Tymon\JWTAuth\Contracts\Providers\Auth;
In your constructor
public function __construct(Auth $auth)
{
$this->_authentication = $auth;
}
Then use the "byCredentials" method
if (! $token = $this->_authentication->byCredentials($credentials))
{
return response()->json(['message' => 'Unauthorized'], 401);
}

How to verifiy JWT on a single route in Laravel

I have a single route in Laravel on which I need to verify the JWT on header if it is authorized and not expired. How can I do that?
In Javascript its really easy, but don`t know how in Laravel.
Here's the code:
public function update(Request $request){
$header = $request->header('Authorization');
$token = $request->bearerToken();
$secret = env('EXAMPLE_SECRETE');
$verified = here i want to verify the jtw /$token
if (!verified)
return 'something here'
else
>>code here after verified
}
First of install below package
composer require firebase/php-jwt
And then you can create a middleware in order to verify Token or expired, below is a complete code of middlware
namespace App\Http\Middleware;
use Closure;
use Exception;
use App\User;
use Firebase\JWT\JWT;
use Firebase\JWT\ExpiredException;
class JwtTokenMiddleware
{
public function handle($request, Closure $next, $guard = null)
{
$token = $request->bearerToken();
if (!$token) {
// Unauthorized response if token not there\
}
try {
$credentials = JWT::decode($token, env('JWT_SECRET'), ['HS256']);
//You can get credentials that you have set up while generating token
$user = User::findOrFail($credentials->sub)->setAuthUser();
$request->auth = $user;
} catch (ExpiredException $e) {
// Token expired response
} catch (Exception $e) {
// Handle unknow error while decoding token
return response()->json([
}
return $next($request);
}
}

Accessing Laravel Api using POSTMAN (404 not found)

I wrote an API for User Login using Laravel 5.8
When I tested the Login on Postman, it generated an error.
Status: 404 Not Found.
The File Path is Http->Controllers->UserController->Login
The project is laravelapi. I used POST in Postman and added this:
http://localhost/laravelapi/public/user/api/login
But when I run php artisan serve and used:
http://localhost:8000/api/login
Status was OK.
Controller
public function login(Request $request)
{
$credentials = $request->json()->all();
try {
if(! $token == JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 400);
}
} catch(JWTException $e) {
return response()->json(['error' => 'could_not_create_token'], 500);
}
return response()->json(compact('token'));
}
api.php
use Illuminate\Http\Request;
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::post('login', 'UserController#login');
What do I do to make http://localhost/laravelapi/public/user/api/login work and have Status: OK
Thanks.
link must be localhost/laravelapi/public/api/login

JWT Authentication user_not_found Tymon

I have set up Tymon Package for JWT Authentication. In case of new user sign up or login I get the token successfully. But when I pass the token to the Laravel JWT I get an error as user not found.
controller code
public function authenticate()
{
$credentials = request()->only('user_name','password');
try{
$token = JWTAuth::attempt($credentials);
if(!$token){
return response()->json(['error'=>'invalid_credentials'],401);
}
}
catch(JWTException $e){
return response()->json(['error'=>'something went wrong'],500);
}
return response()->json(['token'=>$token],200);
}
public function register()
{
$user_name = request()->user_name;
$c_name = request()->company_name;
$accessibility_level = request()->accessability_level;
$password = request()->password;
$contact_number = request()->contact_number;
$address = request()->address;
$user = User::create([
'user_name'=>$user_name,
'c_name'=>$c_name,
'accessibility_level'=>$accessibility_level,
'password'=>bcrypt($password),
'contact_number'=>$contact_number,
'address'=>$address
]);
$token = JWTAuth::fromUser($user);
return response()->json(['token'=>$token],200);
}
no problem with the above code works fine.
But when I try to access some data with JWT validation I get an error as USER_NOT_FOUND. I have passed the Token which I have got as an header through Postman.
Route Code
Route::get('/some_route','some_controller#index')->middleware('jwt.auth');
And the jwt.php is also set with the correct identifier which I have used in the model(Primary key)
'identifier' => 'user_name',
The JWT identifier doesn't work by simply modifying the config because it's hardcoded as id in the code for some reason
You can of course use the setIdentifier method before calling any other JWTAuth methods to set the identifier.
Here's how:
public function authenticate()
{
$credentials = request()->only('user_name','password');
try{
$token = JWTAuth::setIdentifier('user_name')->attempt($credentials);
if(!$token){
return response()->json(['error'=>'invalid_credentials'],401);
}
}
catch(JWTException $e){
return response()->json(['error'=>'something went wrong'],500);
}
return response()->json(['token'=>$token],200);
}
Then create a custom middleware for jwt authentication:
public function handle($request, \Closure $next)
{
if (! $token = $this->auth->setIdentifier('user_name')->setRequest($request)->getToken()) {
return $this->respond('tymon.jwt.absent', 'token_not_provided', 400);
}
try {
$user = $this->auth->authenticate($token);
} catch (TokenExpiredException $e) {
return $this->respond('tymon.jwt.expired', 'token_expired', $e->getStatusCode(), [$e]);
} catch (JWTException $e) {
return $this->respond('tymon.jwt.invalid', 'token_invalid', $e->getStatusCode(), [$e]);
}
if (! $user) {
return $this->respond('tymon.jwt.user_not_found', 'user_not_found', 404);
}
$this->events->fire('tymon.jwt.valid', $user);
return $next($request);
}

Laravel 5.2 session cookie driver

I have a problem with the cookie session driver. I need to create an app that works with only cookies. With my configuration, the session is not persisting in Laravel 5.2 with the cookie driver. If I use the file session driver, it works.
.env file:
SESSION_DRIVER=cookie
I also created a middleware that checks if a custom session value exists (only handle() function):
public function handle($request, Closure $next)
{
//dd(session('auth')) // null
if (!session('auth')) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect('/');
}
}
return $next($request);
}
I added the middleware to the $routeMiddleware array in app/Http/Kernel.php:
'cookies' => \App\Http\Middleware\CheckCookies::class,
My routes are:
Route::group(['middleware' => ['web']], function () {
Route::get('/', 'LoginController#index');
Route::post('login', 'LoginController#login');
Route::group(['middleware' => 'cookies'], function () {
Route::get('home','HomeController#index');
Route::get('logout','HomeController#logout');
});
});
Here's my LoginController#login method:
public function login()
{
session([
'auth' => ['name' => 'John Doe']
]);
return redirect('/home');
}
How can I fix this?
Just use Cookie Facades in laravel.
Cookie::queue('key', 'value', $minutes);
To make cookie forever
Cookie::forever('key', 'value');
Modify your code and try this.
LoginController#login
public function login(){
$cookieValue=json_encode(array('name'=>'John Dow'));
Cookie::queue('auth', $cookieValue, 60);
return redirect('/home');
}
CheckCookies Middleware
public function handle($request, Closure $next){
if (!Cookie::get('auth'))
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect('/');
}
return $next($request);
}
}

Resources