Introduction

JWT (JSON Web Token) verification requires cryptographic operations that depend on PHP's OpenSSL extension. When the extension is not loaded, JWT libraries throw errors like "openssl_sign() expects parameter" or "Class 'Firebase\\JWT\\BeforeValidException' not found" during token decode and verify operations.

This commonly occurs on minimal PHP installations, Docker containers, or after PHP version upgrades where the extension was not carried over.

Symptoms

  • JWT decode throws "Call to undefined function openssl_verify()"
  • Error: "openssl_sign(): supplied key param cannot be coerced into a private key"
  • phpinfo() does not show the OpenSSL section

Common Causes

  • php.ini does not include extension=openssl (disabled by default on some distributions)
  • PHP was compiled without OpenSSL support
  • The OpenSSL shared library (libssl) is not installed on the system

Step-by-Step Fix

  1. 1.Enable the OpenSSL extension in php.ini: Add or uncomment the extension directive.
  2. 2.```bash
  3. 3.# Find your php.ini:
  4. 4.php --ini

# Edit php.ini and ensure this line is present (not commented): extension=openssl

# Verify it's loaded: php -m | grep openssl # Output should show: openssl ```

  1. 1.Install the OpenSSL PHP package on Debian/Ubuntu: The extension may be in a separate package.
  2. 2.```bash
  3. 3.# Install the PHP OpenSSL extension:
  4. 4.sudo apt-get install -y php8.2-openssl
  5. 5.# Or for the meta-package that includes common extensions:
  6. 6.sudo apt-get install -y php8.2-common

# Restart PHP-FPM: sudo systemctl restart php8.2-fpm ```

  1. 1.Install OpenSSL in Docker containers: Ensure the Docker image includes the extension.
  2. 2.```dockerfile
  3. 3.FROM php:8.2-fpm

# Install OpenSSL extension RUN docker-php-ext-install openssl

# Or for Alpine: # RUN apk add --no-cache php82-openssl

# Verify: RUN php -m | grep openssl ```

  1. 1.Verify JWT verification works after enabling OpenSSL: Test the complete flow.
  2. 2.```php
  3. 3.<?php
  4. 4.require 'vendor/autoload.php';
  5. 5.use Firebase\JWT\JWT;
  6. 6.use Firebase\JWT\Key;

$secretKey = 'your-secret-key'; $token = JWT::encode( ['sub' => '1234', 'iat' => time(), 'exp' => time() + 3600], $secretKey, 'HS256' );

// This will fail if OpenSSL is not loaded: $decoded = JWT::decode($token, new Key($secretKey, 'HS256')); echo "User ID: " . $decoded->sub; ```

Prevention

  • Include openssl in your PHP extension checklist during environment setup
  • Use a Dockerfile that explicitly installs all required extensions
  • Add an extension check to your application bootstrap: extension_loaded('openssl')
  • Pin PHP packages to specific versions to prevent extension loss during upgrades