Normalize JWT public key PEM

This commit is contained in:
2026-05-21 13:27:35 -05:00
parent 94064b27c3
commit 7836b72d6d
3 changed files with 68 additions and 5 deletions

View File

@@ -103,7 +103,7 @@ class JwtAuthMiddleware
private function signatureIsValid(string $token, string $signature): bool private function signatureIsValid(string $token, string $signature): bool
{ {
[$header, $payload] = explode('.', $token, 3); [$header, $payload] = explode('.', $token, 3);
$publicKey = str_replace('\\n', "\n", (string) config('jwt.public_key')); $publicKey = $this->normalizePublicKey((string) config('jwt.public_key'));
if ($publicKey === '') { if ($publicKey === '') {
throw new \RuntimeException('JWT public key is empty'); throw new \RuntimeException('JWT public key is empty');
@@ -129,6 +129,35 @@ class JwtAuthMiddleware
return $result === 1; return $result === 1;
} }
private function normalizePublicKey(string $publicKey): string
{
$publicKey = trim(str_replace(['\\r\\n', '\\n', '\\r', "\r\n", "\r"], "\n", $publicKey));
if ($publicKey === '') {
return '';
}
if (
preg_match(
'/-----BEGIN PUBLIC KEY-----(.*?)-----END PUBLIC KEY-----/s',
$publicKey,
$matches
)
) {
$body = preg_replace('/\s+/', '', $matches[1]);
if ($body === '') {
return '';
}
return "-----BEGIN PUBLIC KEY-----\n"
. chunk_split($body, 64, "\n")
. "-----END PUBLIC KEY-----\n";
}
return $publicKey;
}
private function tokenIsExpired(array $payload): bool private function tokenIsExpired(array $payload): bool
{ {
if (!isset($payload['exp']) || !is_numeric($payload['exp'])) { if (!isset($payload['exp']) || !is_numeric($payload['exp'])) {

View File

@@ -30,12 +30,29 @@ Route::get('/health', function () {
Route::get('/health-check-key', function () { Route::get('/health-check-key', function () {
$rawPublicKey = (string) config('jwt.public_key'); $rawPublicKey = (string) config('jwt.public_key');
$formattedPublicKey = str_replace('\\n', "\n", $rawPublicKey); $formattedPublicKey = trim(str_replace(['\\r\\n', '\\n', '\\r', "\r\n", "\r"], "\n", $rawPublicKey));
if (
preg_match(
'/-----BEGIN PUBLIC KEY-----(.*?)-----END PUBLIC KEY-----/s',
$formattedPublicKey,
$matches
)
) {
$body = preg_replace('/\s+/', '', $matches[1]);
$formattedPublicKey = "-----BEGIN PUBLIC KEY-----\n"
. chunk_split($body, 64, "\n")
. "-----END PUBLIC KEY-----\n";
}
$publicKeyResource = openssl_pkey_get_public($formattedPublicKey); $publicKeyResource = openssl_pkey_get_public($formattedPublicKey);
return response()->json([ return response()->json([
'raw_key_empty' => $rawPublicKey === '', 'raw_key_empty' => $rawPublicKey === '',
'key_length' => strlen($formattedPublicKey), 'raw_key_length' => strlen($rawPublicKey),
'formatted_key_length' => strlen($formattedPublicKey),
'has_begin_marker' => str_contains($rawPublicKey, '-----BEGIN PUBLIC KEY-----'),
'has_end_marker' => str_contains($rawPublicKey, '-----END PUBLIC KEY-----'),
'openssl_accepted' => $publicKeyResource !== false, 'openssl_accepted' => $publicKeyResource !== false,
'openssl_error' => openssl_error_string(), 'openssl_error' => openssl_error_string(),
]); ]);

View File

@@ -17,12 +17,29 @@ Route::get('/health', function () {
Route::get('/health-check-key', function () { Route::get('/health-check-key', function () {
$rawPublicKey = (string) config('jwt.public_key'); $rawPublicKey = (string) config('jwt.public_key');
$formattedPublicKey = str_replace('\\n', "\n", $rawPublicKey); $formattedPublicKey = trim(str_replace(['\\r\\n', '\\n', '\\r', "\r\n", "\r"], "\n", $rawPublicKey));
if (
preg_match(
'/-----BEGIN PUBLIC KEY-----(.*?)-----END PUBLIC KEY-----/s',
$formattedPublicKey,
$matches
)
) {
$body = preg_replace('/\s+/', '', $matches[1]);
$formattedPublicKey = "-----BEGIN PUBLIC KEY-----\n"
. chunk_split($body, 64, "\n")
. "-----END PUBLIC KEY-----\n";
}
$publicKeyResource = openssl_pkey_get_public($formattedPublicKey); $publicKeyResource = openssl_pkey_get_public($formattedPublicKey);
return response()->json([ return response()->json([
'raw_key_empty' => $rawPublicKey === '', 'raw_key_empty' => $rawPublicKey === '',
'key_length' => strlen($formattedPublicKey), 'raw_key_length' => strlen($rawPublicKey),
'formatted_key_length' => strlen($formattedPublicKey),
'has_begin_marker' => str_contains($rawPublicKey, '-----BEGIN PUBLIC KEY-----'),
'has_end_marker' => str_contains($rawPublicKey, '-----END PUBLIC KEY-----'),
'openssl_accepted' => $publicKeyResource !== false, 'openssl_accepted' => $publicKeyResource !== false,
'openssl_error' => openssl_error_string(), 'openssl_error' => openssl_error_string(),
]); ]);