Authentication
Authentication is a crucial aspect of web applications, ensuring that users are who they claim to be and have the necessary permissions to access resources. Prisma PHP simplifies the authentication process by providing a built-in authentication system that supports various authentication methods, including email/password, social logins, and third-party services. By integrating authentication into the development workflow, Prisma PHP streamlines the process of securing applications, making it easier for developers to implement user authentication and authorization features.
By default, Prisma PHP use the package firebase/php-jwt
for authentication. This package is a PHP library that enables developers to encode and decode JSON Web Tokens (JWTs) in PHP. JWTs are a popular method for securely transmitting information between parties as a JSON object. They are commonly used for authentication and authorization in web applications, providing a secure and efficient way to verify the identity of users and grant access to resources. For more information about JWTs, you can visit the official website: jwt.io.
To get stated with authentication you have to follow the following steps:
- Set the
AUTH_SECRET
environment variable in the.env
file. - Use the
Auth
class to authenticate users and generate JWTs, locationsrc/Lib/Auth/Auth.php
. - Use the
AuthConfig
class to configure the authentication settings, locationsrc/Lib/Auth/AuthConfig.php
. - Implement authentication middleware
AuthMiddleware
to protect routes and resources, locationsrc/Lib/Middleware/AuthMiddleware.php
. - Secure your application by validating JWTs and verifying user roles.
Set the AUTH_SECRET Environment Variable
The AUTH_SECRET
environment variable is used to sign and verify JWTs. It should be a random string of characters that is kept secret and not shared with others. You can generate a secure secret using a password manager or a random string generator. The secret should be unique for each application and should not be hard-coded in the source code.
By default Prisma PHP give you a random secret key AUTH_SECRET=your_secret_key
just for development purposes, you can change it in the .env
file.
- Get your secret key from openssl CLI,
openssl rand -base64 33
- Alternatively,
randomkeygen.com
. - Or install the package on local running the command
npm exec auth secret
, this will generate a random secret key and save it in the.env
file.
Use the Auth Class
To authenticate users and generate JWT tokens, you can use the Auth
singleton class located in src/Lib/Auth/Auth.php
. This class provides all the necessary methods for authentication, such as:
getInstance
Get the instance of the Auth class, $auth = Auth::getInstance();signIn
Sign In the user and generate a JWT token, $jwt = $auth->signIn($data);isAuthenticated
Check if the user is authenticated, $auth->isAuthenticated();getPayload
Get the payload of the JWT token. Use the$user = $auth->getPayload()
method to retrieve the information encrypted in the JWT token. This method will return the user information that was saved while generating the token, but decrypted.verifyToken
Verify the JWT token, $auth->verifyToken($token);refreshToken
Refresh the JWT token, $auth->refreshToken($token);signOut
Sign Out the user and destroy the JWT token, $auth->signOut('/redirect');
Use the AuthConfig Class
To configure the AuthConfig class you can find it in src/Lib/Auth/AuthConfig.php
file, you can change the default values as you want.
ROLE_IDENTIFIER
: The key used to identify the user role in the JWT payload.IS_ROLE_BASE
: A boolean value indicating whether the application uses role-based access control.IS_TOKEN_AUTO_REFRESH
: A boolean value indicating whether the JWT token should be automatically refreshed.public static $publicRoutes
: An array listing the public routes that do not require authentication, by default all routes is public.public static $privateRoutes
: An array of private routes that are accessible to all authenticated users without specific role-based access control.public static $roleBasedRoutes
: An associative array mapping specific routes to required user roles for access control.
Here is an example of how to configure the role base access control in the AuthConfig class:
if you going to use the role base access control you have to set the IS_ROLE_BASE
to true
and set the roles for each route in the public static $privateRoutes
and public static $roleBasedRoutes
array. The roles should be defined in the AuthRole
enum, you can find it in the src/Lib/Auth/AuthConfig.php
file.
enum AuthRole: string
{
case Admin = 'Admin';
case User = 'User';
public function equals($role)
{
return $this->value === $role;
}
}
Here is an example of how to configure the AuthConfig class:
final class AuthConfig
{
const ROLE_IDENTIFIER = 'role'; // The key used to identify the user role in the JWT payload
const IS_ROLE_BASE = false; // Enable role-based access control (true/false)
const IS_TOKEN_AUTO_REFRESH = false; // Enable token auto refresh (true/false)
// Be default all routes is public
public static $privateRoutes = [
'/dashboard', // All routes that is inside the dashboard route is private and require authentication
'/settings/profile', // All routes that is inside the settings/profile route is private and require authentication
**Note** the settings route is public
];
public static $roleBasedRoutes = [
'dashboard' => [self::ROLE_IDENTIFIER => [AuthRole::Admin, AuthRole::User]], // The dashboard route require Admin or User role to access
'dashboard/users' => [self::ROLE_IDENTIFIER => [AuthRole::Admin]], // The dashboard/users route require Admin role to access
**Note** the dashboard route is accessible by Admin and User roles
];
}
After configuring the AuthConfig class, you can use the Auth class to authenticate users and generate JWTs. The Auth class provides methods for authenticating users and generating JWTs. You can use the Auth->authenticate($role, $tokenValidity)
method to authenticate users and generate a JWT token. The method takes a mixed $role and a string $tokenValidity as arguments and returns a signed JWT token. You can use the token to authenticate requests and grant access to protected resources.
You can modify the authenticate
method to accept the user ID and token validity as arguments, this makes the method more flexible and allows you to specify the $role can be the user model that you want to store in the JWT payload.
- For the token validity
$tokenValidity
, you can use the following formats: 30s
for 30 seconds1m
for 1 minute1h
for 1 hour1d
for 1 day- By default, the token validity is set to
1h
for 1 hour. If you don't specify the token validity, it will use the default value.
Here is an example of how to use the Auth class to authenticate users and generate JWTs:
<?php
use Lib\Auth\Auth;
$auth = Auth::getInstance();
$loginUserInfo = ['id' => 1, 'username' => 'john.doe', 'email' => 'john.doe@gmail.com'];
try {
$jwt = $auth->authenticate($loginUserInfo);
echo "JWT: " . $jwt;
} catch (\InvalidArgumentException $e) {
echo "Error: " . $e->getMessage();
}
Note: The basic way to authenticate the user is by passing the user info directly to the `authenticate` method. In this case, there is no need to handle the `Role` separately.
Basic way to authenticate the user or login the user is by passing the user info directly to the `authenticate` method, in this case, there is no need to handle the `Role` separately.
<?php
use Lib\Auth\Auth;
use Lib\StateManager;
$auth = Auth::getInstance();
$user = StateManager::getState('user');
if ($auth->isAuthenticated()) {
StateManager::setState('user', $auth->getPayload());
}
function login()
{
global $auth;
$jwt = $auth->authenticate(['name' => 'admin'], '1m');
echo "JWT: $jwt";
}
?>
<button onclick="login">Login</button>
<p><?= $user->name ?? '' ?></p>
<?php
use Lib\Auth\Auth;
use Lib\Auth\AuthRole;
$auth = Auth::getInstance();
try {
$jwt = $auth->authenticate(AuthRole::Admin, '1m');
echo "JWT: " . $jwt;
} catch (\InvalidArgumentException $e) {
echo "Error: " . $e->getMessage();
}
In this example, we create a new instance of the Auth
class from the Lib\Auth
namespace. We then attempt to authenticate a user as an Admin
with a token expiration time of '1m' (one minute). The authenticate
method generates a JWT (JSON Web Token) which is then printed out. If an error occurs during authentication, such as invalid arguments, it catches the exception and prints the error message.
To check is the user is authenticated you can use the Auth->isAuthenticated()
method, this method will return true
if the user is authenticated and false
if the user is not authenticated.
For logout you can use the Auth->logout()
method to logout the user and destroy the JWT token, this method will redirect the user to the login page.
Here is an example of how to use the Auth class to logout the user:
To log out the user, you can use the signOut
function and then redirect the user to the home page.
<?php
use Lib\Auth\Auth;
function logout {
Auth::getInstance()->signOut('/'); // Replace '/path/to/redirect' with the actual path where you want to redirect the user after logout
}
?>
<button onclick="logout">Logout</button>
using get to logout the user, <a href="?logout">Logout</a>
<?php
use Lib\Auth\Auth;
$auth = Auth::getInstance();
if ($isGet && isset($params->logout)) {
$auth->logout('/'); // Replace '/path/to/redirect' with the actual path where you want to redirect the user after logout
}
?>
<a href="?logout">Logout</a>
Implement Authentication Middleware
Once you have generated a JWT token, you can use it to authenticate requests and grant access to protected resources. To do this, you need to implement authentication middleware that verifies the JWT token and grants access to authenticated users. The middleware should extract the JWT token from the request headers, decode the token, and verify the signature to ensure that it is valid. If the token is valid, the middleware should grant access to the protected resource; otherwise, it should return an error response or redirect.
Prisma PHP provides built-in middleware for authenticating requests and protecting routes. You can use the AuthMiddleware
class to authenticate requests and grant access to protected resources. The middleware extracts the JWT token from the request headers, decodes the token, and verifies the signature to ensure that it is valid. If the token is valid, the middleware grants access to the protected resource; otherwise, it returns an error response or redirect.
Here is an example of how to use the AuthMiddleware class to authenticate requests and protect routes:
public static function handle($requestUri)
{
// Check if the route matches the private routes that require authentication
$requestUri = trim($requestUri);
if (!self::matches($requestUri)) {
return;
}
// Check if the user is authorized to access the route or redirect to login
if (!self::isAuthorized()) {
redirect('/auth/login'); // Redirect to login page or return an error response depends on your implementation
exit;
}
// Check if the user has the required role to access the route or redirect to denied
if (AuthConfig::IS_ROLE_BASE && !self::hasRequiredRole($requestUri)) {
redirect('/denied'); // Redirect to denied page or return an error response depends on your implementation
exit;
}
}
In this example, the AuthMiddleware
class is used to authenticate requests and protect routes. It first checks if the requested URI matches a list of private routes that require authentication. If the URI does not match, it simply returns without further checks. If it matches, the middleware verifies whether the user is authorized. If not authorized, it redirects the user to a login page. Additionally, if role-based access control is enabled and the user does not have the required role for the route, it redirects to a denial page. This setup ensures that only authorized and properly role-equipped users can access specific routes.
Secure Your Application
After you've put the authentication middleware in place, it's time to leverage it to safeguard your application and its routes and resources. This middleware does the critical work of validating JWT tokens, thus ensuring only authenticated users who also meet the role-based permissions can access certain areas of your application. The configuration for this, including specifying which routes are protected and the roles that are permitted access, is handled through the AuthConfig
class.
This approach of integrating authentication and authorization mechanisms into your application is instrumental in protecting sensitive information and resources from unauthorized access. It guarantees that only users with the right permissions can reach protected resources. Prisma PHP facilitates this with its in-built authentication system, significantly simplifying the implementation of these crucial security features for developers.
For further details on implementing authentication and authorization with Prisma PHP, refer to the official documentation and API guide. These resources offer comprehensive guidance on authenticating users, generating JWT tokens, and securing routes and resources with the framework's authentication capabilities.