0 Shares 22473 Views

LARAVEL API- JWT Examples

LARAVEL API- Some JWT Examples

Today we will develop an API (Application Programming Interface) application via Laravel and provide security through JWT.

So what is JWT primarily? Let’s address this issue.

JWT (JSON WEB TOKEN)

JWT is a Token format standardized by the IETF organization. Detailed information about the standard can be found here. Among the JWT communication systems (eg Mobile, Web, Cloud, IoT, etc.), user identification, verification, and information security, etc. matter.

The Structure of JWT

JWT is composed of 3 separate parts encoded in Base64. These parts are ‘.’ separated by. Separated by “. These parts are:

  • Header
  • Payload
  • Signature

HEADER

This is where JWT’s cookies are located. The standard is defined as follows.

{ 
"alg": "HS256",
"typ": "JWT"
}

Alg : Where it determines the Cryptographic Algorithm for JWT. Supported Algorithms vary depending on the language you use. You can review supported Algorithms via jwt.io.

Typ : Indicates that the Header type used is JWT.

PAYLOAD

Although there are some standards here, it is the part that contains the data we want to carry in general. To mention some standard keys;

  • iss (issuer): Publisher
  • sub (subject): Subject
  • exp (expiration time): Expiration date
  • nbf (not before time): Before this Date
  • iat (issued at the time): Created on

We’ll be talking about these areas in the future, as many of the standard switches available are much more than enough.

SIGNATURE

This is the part where the Key is used to create the JWT. The header is encrypted with the specified encryption method.

~~~

Except for the signature part of the JWT you produce, the data can be read in it. Simply decode the Base64. But you cannot make any changes to the information in the content because the key will become unusable.

JWT Advantages

Since they are stateless, database operations are not required for users’ information.

  • Session management can be done without in-house cookies.
  • A single switch can operate on multiple servers.
  • Database and so on are much faster because no operations are performed.

JWT Drawbacks

  • If your secret key is not strong enough, it can be easily manipulated.
  • There is no way to override the server-side because they are stateless. (We can prevent it from working with several methods.)

In general, we talked about JWT. Now let’s examine how it works on a simple Laravel API. Generally, two different libraries are used:

  • firebase / PHP-jwt
  • Tymon / jwt-auth

We will use “tymon / jwt-auth üzerinde on our application. We are primarily involved with Composer in our project.

composer require tymon/jwt-auth:1.0.0

At Medianova, we are developing the project with Laravel 6, which will be explained in section 5.4 and above. After installing the package through Artisan CLI

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

You will then see jwt.php in app/config/ Then we proceed to the step of setting the password for JWT. Again via the terminal

php artisan jwt:secret

After that, the JWT_SECRET key will be created in your .env file. Since it is a sample application, we will describe it as if there is a database connection. There will be no difference as you can run through your model if you want, which will tell you through the User model that comes as standard. First of all, we make the following changes on /App/User.php.

use Tymon\JWTAuth\Contracts\JWTSubject;

...class User extends Authenticatable implements JWTSubject{

public function getJWTIdentifier()

{

return $this->getKey();

}

public function getJWTCustomClaims()

{

return [];

}

...

after these changes, our model file should look like this;

<?php

namespace App;

use Tymon\JWTAuth\Contracts\JWTSubject;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Illuminate\Notifications\Notifiable;

class User extends Authenticatable implements JWTSubject

{

use Notifiable;

/**

* Get the identifier that will be stored in the subject claim of the JWT.

*

* @return mixed

*/

public function getJWTIdentifier()

{

return $this->getKey();

}

/**

* Return a key value array, containing any custom claims to be added to the JWT.

*

* @return array

*/

public function getJWTCustomClaims() : array

{

return [];

}

/**

* The attributes that are mass assignable.

*

* @var array

*/

protected $fillable = [

'name', 'email', 'password',

]; /**

* The attributes that should be hidden for arrays.

*

* @var array

*/

protected $hidden = [

'password', 'remember_token',

]; /**

* The attributes that should be cast to native types.

*

* @var array

*/

protected $casts = [

'email_verified_at' => 'datetime',

];

}

</code>

Now let's create a route for user input, detail, output, etc. The api.php in the router should look like this;

<code>

# router/api.php

.....Route::group([ 'middleware' => ['api'],

'prefix' => 'member'], static function ($router) {

Route::post('login', 'MemberController@login');

Route::post('register', 'MemberController@register');

Route::group(['middleware' => 'jwt.verify'], static function( $router){

Route::post('logout', 'MemberController@logout');

Route::post('refresh', 'MemberController@refresh');

Route::get('detail', 'MemberController@detail'); });

});

.....

and then create the jwt.verify middleware, so that we can control requests from routes. Artisan from CLI

php artisan make:middleware JwtMiddleware

:/app/Http/Middleware JwtMiddleware file will be formed under the contents of the following edit.

<?php

namespace App\Http\Middleware;use Closure;

use JWTAuth;

use Exception;

use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;

class JwtMiddleware extends BaseMiddleware

{

/**

* Handle an incoming request.

*

* @param \Illuminate\Http\Request $request

* @param \Closure $next

* @return mixed

*/

public function handle($request, Closure $next)

{

try {

$user = JWTAuth::parseToken()->authenticate();

if( !$user ) throw new Exception('User Not Found');

} catch (Exception $e) {

if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){

return response()->json([

'data' => null,

'status' => false,

'err_' => [

'message' => 'Token Invalid',

'code' => 1

]

]

);

}else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){

return response()->json([

'data' => null,

'status' => false,

'err_' => [

'message' => 'Token Expired',

'code' =>1

]

]

);

}

else{

if( $e->getMessage() === 'User Not Found') {

return response()->json([

"data" => null,

"status" => false,

"err_" => [

"message" => "User Not Found",

"code" => 1

]

]

); }

return response()->json([

'data' => null,

'status' => false,

'err_' => [

'message' => 'Authorization Token not found',

'code' =>1

]

]

);

}

}

return $next($request);

}

}

and to use this middleware on routes we define it on the kernel. : /app/Http/Kernel.php is now fully operational.

...

protected $routeMiddleware = [

....

'jwt.verify' => \App\Http\Middleware\JwtMiddleware::class,

...

Let’s create the controls that meet the routes. Again, Artisan can do this operation via CLI. In that

php artisan make:controller MemberController

After that, the contents of the MemberController will be created in

/app/Http/Controller.

...

use App\Http\Requests\RegisterRequest;

use Exception;

use Illuminate\Http\JsonResponse;

use Illuminate\Http\Request;

use JWTAuth;

use Hash;

use App\User;

use Tymon\JWTAuth\Exceptions\JWTException;

...protected $data = [];/**

*

* @return void

*/

public function __construct()

{

$this->data = [

'status' => false,

'code' => 401,

'data' => null,

'err' => [

'code' => 1,

'message' => 'Unauthorized'

]

];

}

/**

* With the request-> only method, we only take the email-password as a *parameter and perform the user authentication with the attempt *function of the auth method in the laravel. If the user is correct, we *return a token for the user to use for later processing.

*

* @param Request $request

* @return JsonResponse

*/

public function login(Request $request): JsonResponse

{ $credentials = $request->only(['email', 'password']);

try {

if (!$token = JWTAuth::attempt($credentials)) {

throw new Exception('invalid_credentials');

}

$this->data = [

'status' => true,

'code' => 200,

'data' => [

'_token' => $token

],

'err' => null

]; } catch (Exception $e) {

$this->data['err']['message'] = $e->getMessage();

$this->data['code'] = 401;

} catch (JWTException $e) {

$this->data['err']['message'] = 'Could not create token';

$this->data['code'] = 500;

}

return response()->json($this->data, $this->data['code']);

}/**

*I do not elaborate as the user registers method used here before, as described in RegisterRequest.

* @param RegisterRequest $request

* @return JsonResponse

*/

public function register(RegisterRequest $request): JsonResponse

{

$user = User::create([

'name' => $request->post('name'),

'email' => $request->post('email'),

'password' => Hash::make($request->post('password'))

]);

$this->data = [

'status' => true,

'code' => 200,

'data' => [

'User' => $user

],

'err' => null

];

return response()->json($this->data, $this->data['code']);

}/**

* Bring the details of the verified user.

*

* @return JsonResponse

*/

public function detail(): JsonResponse

{

$this->data = [

'status' => true,

'code' => 200,

'data' => [

'User' => auth()->user()

],

'err' => null

];

return response()->json($this->data);

}/**

*Log out the user and make the token unusable.

* @return JsonResponse

*/

public function logout(): JsonResponse

{

auth()->logout();

$data = [

'status' => true,

'code' => 200,

'data' => [

'message' => 'Successfully logged out'

],

'err' => null

];

return response()->json($data);

}/**

* Renewal process to make JWT reusable after expiry date.

* @return JsonResponse

*/

public function refresh(): JsonResponse

{

$data = [

'status' => true,

'code' => 200,

'data' => [

'_token' => auth()->refresh()

],

'err' => null

];

return response()->json($data, 200);

}

then we catch JWT related errors in our Exception Handler file and set the feedbacks. It must look exactly like this;

....use Illuminate\Http\Request;

use Illuminate\Http\Response;

use Tymon\JWTAuth\Exceptions\TokenExpiredException;

use Tymon\JWTAuth\Exceptions\TokenInvalidException;

use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;

use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;

...

/**

* Render an exception into an HTTP response.

*

* @param Request $request

* @param \Exception $exception

* @return Response

*/

public function render($request, Exception $exception) :Response

{

if ($exception instanceof UnauthorizedHttpException) {

$preException = $exception->getPrevious();

if ($preException instanceof

TokenExpiredException) {

return response()->json([

'data' => null,

'status' => false,

'err_' => [

'message' => 'Token Expired',

'code' =>1

]

]

);

}

else if ($preException instanceof

TokenInvalidException) {

return response()->json([

'data' => null,

'status' => false,

'err_' => [

'message' => 'Token Invalid',

'code' => 1

]

]

);

} else if ($preException instanceof

TokenBlacklistedException) {

return response()->json([

'data' => null,

'status' => false,

'err_' => [

'message' => 'Token Blacklisted',

'code' => 1

]

]

);

}

if ($exception->getMessage() === 'Token not provided') {

return response()->json([

'data' => null,

'status' => false,

'err_' => [

'message' => 'Token not provided',

'code' => 1

]

]

);

}else if( $exception->getMessage() === 'User not found'){

return response()->json([

'data' => null,

'status' => false,

'err_' => [

'message' => 'User Not Found',

'code' => 1

]

]

);

}

}

return parent::render($request, $exception);

}




</code>




and so we can now run tests on the postman. First, we start the project via Artisan CLI.

<code>

php artisan serve

then our project is running on http://127.0.0.1:8000.

 

 

You may be interested

The Ultimate CDN (Content Delivery Network) Guide
CDN
2256 views
CDN
2256 views

The Ultimate CDN (Content Delivery Network) Guide

Nadia Benslimane - August 3, 2020

The Ultimate CDN Guide- Everything About CDN You probably know what CDN (Content Delivery Network) stands for. You may also be aware of its full definition, but…

The Essential CDN Glossary
CDN
8176 views
CDN
8176 views

The Essential CDN Glossary

Nadia Benslimane - November 21, 2019

Why Have We Decided To Create a CDN Glossary? Whether you are new to the world of CDN, or have been involved in it for years, there…

Black Friday 2020 and Covid-19: How Is The Game Changing?
e-commerce
346 views1
e-commerce
346 views1

Black Friday 2020 and Covid-19: How Is The Game Changing?

Tushar Sonal - October 21, 2020

How Is Covid-19 Going To Impact Black Friday 2020? Black Friday is around the corner again. It is a much-awaited festival for shopping enthusiasts and brands chasing…

Coronavirus and OTT: What Is The Current Situation?
CDN
489 views
CDN
489 views

Coronavirus and OTT: What Is The Current Situation?

Tushar Sonal - October 13, 2020

The Repercussions of Coronavirus on OTT Industry The OTT industry has significantly transformed how people have been used to consuming media content. In the 2000s, the explosion…

Introducing Medianova Meet: Our Free Video Conferencing Tool
New Features
729 views
New Features
729 views

Introducing Medianova Meet: Our Free Video Conferencing Tool

Aykut Teker - October 6, 2020

Meet Is A New Free Video Conferencing Tool Launched By Medianova Due to the current pandemic, video conferencing tools are on high-demand. Even though working remotely decimated…

Most from this category