Table of Contents
Securing APIs is crucial for protecting sensitive data and ensuring only authorized users can access certain endpoints. In this tutorial, we will walk through the process of securing Symfony APIs using JSON Web Token (JWT) authentication, a popular method for stateless authentication.
Prerequisites
- Symfony 5 or higher installed
- API Platform or custom API setup
- Composer for dependency management
- Basic knowledge of Symfony and security concepts
Step 1: Install JWT Authentication Bundle
Begin by installing the LexikJWTAuthenticationBundle, which provides JWT support for Symfony.
composer require lexik/jwt-authentication-bundle
After installation, add the bundle to your kernel if Symfony version requires manual registration.
// config/bundles.php
return [
// ...
Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true],
];
Step 2: Generate SSL Keys
JWT requires a private and public key pair for signing tokens. Generate them using OpenSSL:
mkdir -p config/jwt
openssl genrsa -out config/jwt/private.pem -aes256 4096
openssl rsa -pubout -in config/jwt/private.pem -out config/jwt/public.pem
Secure the private key by setting appropriate permissions.
chmod 600 config/jwt/private.pem
Step 3: Configure the Bundle
Update your Symfony configuration to include JWT settings.
// config/packages/lexik_jwt_authentication.yaml
lexik_jwt_authentication:
secret_key: '%kernel.project_dir%/config/jwt/private.pem'
public_key: '%kernel.project_dir%/config/jwt/public.pem'
pass_phrase: 'your_passphrase'
token_ttl: 3600
Replace 'your_passphrase' with a secure passphrase used during key generation.
Step 4: Update Security Configuration
Configure your security.yaml to enable JWT authentication.
// config/packages/security.yaml
security:
encoders:
Symfony\Component\Security\Core\User\UserInterface:
algorithm: auto
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
login:
pattern: ^/api/login
stateless: true
anonymous: true
json_login:
check_path: /api/login
username_path: email
password_path: password
api:
pattern: ^/api
stateless: true
jwt: ~
access_control:
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
Step 5: Create Login Endpoint
Ensure your User entity implements UserInterface and has an email and password. The login endpoint will authenticate and return a JWT token.
Example Controller
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class ApiController extends AbstractController
{
/**
* @Route("/api/login", name="api_login", methods={"POST"})
*/
public function login()
{
// The JSON login is handled automatically by security.yaml
// No code needed here unless customizing response
}
}
Step 6: Testing the Setup
Use a tool like Postman to send a POST request to /api/login with JSON body containing email and password:
Request:
{
"email": "[email protected]",
"password": "your_password"
}
If successful, you will receive a JWT token in response. Use this token in the Authorization header for subsequent API requests:
Authorization: Bearer your_jwt_token
Conclusion
Implementing JWT authentication in Symfony enhances your API security by enabling stateless, token-based authentication. Follow these steps to set up and test your secured API endpoints effectively.