v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: MEDIUM auth.php.jwt.unsecured-signer

A JWT is configured with an unsecured / none signer, e.g. Configuration::forUnsecuredSigner() or new Signer\None() (lcobucci/jwt), or the 'none' algorithm passed to JWT::encode() / new Key(...) (firebase/php-jwt).

Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.

Why this matters

Unsecured tokens carry no signature, so anyone can mint a token with any claims and it will be accepted (CWE-347). This appears in AI-generated "quick token" and debugging code that then ships.

Use a real signer with a key from configuration: use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Key\InMemory; $config = Configuration::forSymmetricSigner( new Sha256(), InMemory::base64Encoded(getenv('JWT_KEY')) );

VULNERABLE
vulnerable.php
<?php

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer;

function lcobucci_unsecured()
{
    // ruleid: auth.php.jwt.unsecured-signer
    return Configuration::forUnsecuredSigner();
}

function lcobucci_none()
{
    // ruleid: auth.php.jwt.unsecured-signer
    return new Signer\None();
}

function firebase_key_none($k)
{
    // ruleid: auth.php.jwt.unsecured-signer
    return new Key($k, 'none');
}

function firebase_encode_none($p, $k)
{
    // ruleid: auth.php.jwt.unsecured-signer
    return JWT::encode($p, $k, 'None');
}

function firebase_decode_none($j, $k)
{
    // ruleid: auth.php.jwt.unsecured-signer
    return JWT::decode($j, new Key($k, 'none'));
}
SAFE
safe.php
<?php

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;

function lcobucci_symmetric()
{
    // ok: real HMAC signer with a key from the environment
    return Configuration::forSymmetricSigner(new Sha256(), InMemory::base64Encoded(getenv('K')));
}

function firebase_hs256($j, $k)
{
    // ok: pinned HS256 algorithm
    return JWT::decode($j, new Key($k, 'HS256'));
}

function firebase_encode($p, $k)
{
    // ok: real algorithm
    return JWT::encode($p, $k, 'HS256');
}

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

// oauthlint-disable-next-line auth.php.jwt.unsecured-signer -- <reason>

References

https://github.com/lcobucci/jwt ↗https://github.com/firebase/php-jwt ↗https://cwe.mitre.org/data/definitions/347.html ↗