JWT Authentication

True\AuthenticationJWT is a complete JWT login system. It stores the JWT in a secure HTTP-only cookie, tracks failed-login lockouts, and supports an optional 2FA step backed by GoogleAuthenticator.

Constructing the class

The constructor takes the collaborators it needs plus an optional $config override:

public function __construct(
    object $userClass,
    object $loginAttemptClass,
    object $JWT,
    object $PasswordGenerator,
    object $App,
    array  $config = []
)
  • $userClass — fetches user records (by username, by id, …).
  • $loginAttemptClass — tracks failed attempts and lockout windows.
  • $JWT — encodes/decodes the JWT.
  • $PasswordGenerator — used to mint passwords when needed; see PasswordGenerator.
  • $App — gives the class getConfig() / writeConfig() access.
  • $config — any of the keys below; values you omit fall back to the defaults.

Configuration

KeyDefaultPurpose
attemptsAllowed8Failed logins before lockout.
algRS256JWT signing algorithm.
privateKeyFilenullPath to the private signing key (RSA).
publicKeyFilenullPath to the public verification key.
pemkeyPasswordnullPassword for the private key, if encrypted.
encryptionPasswordFilenullPath to a file holding the encryption password.
cookieauthjwtCookie name that carries the JWT.
ttl2592000Token lifetime (seconds). Default is 30 days.
httpstrueMark the cookie Secure.
httpOnlytrueMark the cookie HttpOnly.

Supported algorithms: RS256, RS384, RS512, HS256, HS384, HS512.

A typical setup

$taAuthConfig = (array) $App->getConfig('trueadminAuth.ini');

$configArguments = [
    'privateKeyFile'         => BP.'/app/data/key_private_rsa.pem',
    'publicKeyFile'          => BP.'/app/data/key_public_rsa.pem',
    'encryptionPasswordFile' => 'trueadminAuth.ini',
];
foreach ($taAuthConfig as $k => $v) $configArguments[$k] = $v;

$Auth = new True\AuthenticationJWT(
    $AdminUsers, $LoginAttempts, $JWT, $PasswordGenerator, $App, $configArguments
);

Logging in

login() validates the username + password, checks lockout state, issues a JWT cookie, and returns:

  • true — credentials valid and 2FA isn't required. User is fully logged in.
  • false — credentials valid and 2FA is required. A partial JWT is set; the user still needs to pass the 2FA step.
  • throws — bad credentials, account locked, missing config, etc.
try {
    if ($Auth->login('john.doe', 'securepassword')) {
        echo "Login successful!";
    } else {
        echo "2FA required.";
    }
} catch (Exception $e) {
    echo "Login failed: " . $e->getMessage();
}

Session helpers

$Auth->isLoggedIn();          // true when the cookie carries a valid full JWT
$Auth->googleAuth2fAStep();   // true when the user has logged in but not completed 2FA
$user = $Auth->getUserInfo(); // returns the decoded user object
$Auth->updateToken(['role' => 'admin']);  // merge extra claims into the cookie
$Auth->logout();              // clear the cookie

Security notes

  • Keep private keys outside the document root and lock down their file permissions.
  • Always serve over HTTPS — the default https => true assumes it.
  • Rotate signing/encryption keys on a schedule.
  • The lockout counter is a soft brute-force deterrent; pair it with a rate limiter on the login route.