In Slim4 API Tutorial 3 JWT access token , we will discuss how to use Slim4 JWT access token in login API. After user successfully register, application / systems need a method to secure the data from unauthorized access. Login is one of the authentication methods to secure the data that belongs to the user. Usually login requires username and password . On web/frontend or mobile apps, user enter their username and password in a form view. At backend, username and password are sent by request. It can be formated in json. Furthermore, system will authenticate it, if username and password are correct then a response will be sent. One method that use to exchange the data between backend and frontend or mobile apps is JSON Web Token (JWT).
PHP Slim4 JWT Access Token
One of JWT access token packages can be used in Slim4 is firebase/php-jwt. This package supports function to encode and decode access token. The access token itself can be containing data such as created time, expired time, and user information. Install firebase/php-jwt by using composer:
composer require firebase/php-jwt
JWT key and algorithm settings
To make firebase/php-jwt encode and decode function properly, we need to set secret key and algorithm. This setting proposed to make encryption data same as decoded data (plaintext). Add secret key and algorithm in config/settings.php
// other code
'jwt' => [
'key' => 'secretkey',
'alg' => 'HS256',
]
// other code
PHP login authentication using JWT access token
At the API login, before system responds using JWT access token, we need to validate the user's request and existance of the user. Validation process checks the email and password is valid or not. If the validation is valid, then system / application will check user's existance. It will check on user data in the database. If user exists on the database, system will generate JWT access token. Created time, expired time, user ID, user email will be stored in the JWT access token.
// other code
use Firebase\JWT\JWT;
// other code
$app->post('/login', function (Request $request, Response $response) use ($settings) {
$body = $request->getBody();
$json = json_decode($body, true);
$validator = new Validator;
$validator->requirePresence('email', true, 'Email field is required')
->notEmptyString('email', 'Email is required')
->email('email', false, 'Email must be valid')
->requirePresence('password', true, 'Password field is required')
->notEmptyString('password', 'Password is required');
$errors = $validator->validate($json);
if ($errors) {
$messages['message'] = 'Login failed';
foreach($errors as $error) {
$messages['error'][] = array_values($error);
}
$statusCode = 401;
} else {
$user = User::where('email', $json['email'])
->where('password', sha1($json['password']))
->where('status', 1)
->first();
if ($user) {
$iat = new DateTimeImmutable(); // issued at time
$exp = $iat->modify('+30 minutes')->getTimestamp(); // expired
$nbf = $iat->getTimestamp(); // not before
$payload = [
'iat' => $iat->getTimestamp(),
'exp' => $exp,
'nbf' => $nbf,
'user_id' => $user->id,
'email' => $user->email,
];
$message['access_token'] = JWT::encode($payload, $settings['jwt']['key'], $settings['jwt']['alg']);
$statusCode = 200;
} else {
$message['message'] = 'Login failed';
$statusCode = 401;
}
}
$data = json_encode($message);
$response->getBody()->write($data);
return $response
->withHeader('Content-Type', 'application-json')
->withStatus($statusCode);
});
// other code
Login API using Postman:
Decode JWT Aaccess token
Sometimes the system requires additional data to be able to continue next process, for example user_id will use to find out user last update or maybe it will use as tag in shopping cart. One of effective way to get that data is decode function (decode). To be able to generate valid data, secret key and the algorithm for encryption must be same as decryption. Example code for decode function is as follows:
use Firebase\JWT\Key;
...
$app->post('/decode', function (Request $request, Response $response) use ($settings) {
$body = $request->getBody();
$json = json_decode($body, true);
$key = new Key($settings['jwt']['key'], $settings['jwt']['alg']);
$decode = JWT::decode($json['access_token'], $key);
$response->getBody()->write(json_encode($decode));
return $response->withHeader('Content-Type', 'application-json');
});
...
Decode JWT access token using Postman:
Full code can be viewed at Github.
Pingback: Slim4 Fashion Store API: 4 Autentikasi dan middleware – PerangkatLunakKu
Pingback: Slim4 Tutorial API: 4 Middleware autentikasi - PerangkatLunakKu
Pingback: Tutorial PHP Backend Slim4 - PerangkatLunakKu