Aller au contenu

omniauth/otp Référence de l’API

Étage
Fournisseur · Omniauth
Version
1.x
Suite de conformité
non branchée
Vérifié en réel
Vérifié en partie
Licence
MIT
composer require omniauth/otp:1.x-dev

Lue dans les fichiers PHP du paquet au commit 069bf3092f64 : ses espaces de noms, classes, interfaces et énumérations, leurs constantes, propriétés et méthodes publiques avec leur PHPDoc, et les options que prennent ses fabriques. Rien n’en est exécuté.

Omniauth\Otp

  • CacheUsedSteps class

    The last time step each account used, in any PSR-6 pool or PSR-16 cache: plain PHP, tests, and a host's cache pool (the same one its throttle uses is fine). Each entry lives only as long as its code could still verify.

    2 methods

  • SealedTotpSecrets class

    An application's TotpSecrets store with its secrets sealed by a box (SodiumSecretBox: Marco's decision QA5): what the store keeps is the box's, what TotpMethod reads is the base32 secret. A secret is opened only when a code is verified or the enrolment's QR code is drawn (secret()); whether an account has one is read without opening it (has()). A secret that does not open throws (Exception\UnreadableSecret): never "no secret", which would let the account in without its second factor.

    5 methods

  • SodiumSecretBox class

    The TOTP secrets sealed at rest with libsodium's secretbox (XSalsa20 and Poly1305: encrypted and authenticated) under one 32-byte key - Marco's decision QA5. What the store keeps:

    6 methods · 1 constant

  • TotpMethod class

    An authenticator application (TOTP, RFC 6238) as a second factor, over spomky-labs/otphp - the library scheb/2fa verifies with, on the parameters omnibase's User gives it (SHA1, 30 seconds, 6 digits) and the leeway every site sets (0): a code scheb accepts, this accepts, and the secrets kept today (user.secret, base32) go on working. One thing more than scheb: a code is accepted once, and none older than the last one accepted (Contract\UsedSteps).

    10 methods · 4 constants

Omniauth\Otp\Contract

  • SecretBox interface

    The secrets at rest (Marco's decision QA5, 2026-10-20: the TOTP secret encrypted with sodium, its key in the secrets vault). SodiumSecretBox is the box; SealedTotpSecrets wraps the application's TotpSecrets store with it, and TotpMethod never knows. Both hosts (omnibridge/symfony, omnibridge/laravel) build it from the same key.

    2 methods

  • UsedSteps interface

    The time steps whose code an account already used: a code is accepted once (RFC 6238 §5.2), and none older than the last one accepted. Omniauth\Otp\CacheUsedSteps keeps them in any PSR-6 pool or PSR-16 cache; a host may keep them anywhere else (a column, its rate limiter's store).

    1 method

Omniauth\Otp\Exception

  • UnreadableSecret class

    A sealed secret that does not open: sealed under another key (a key rotated without its rows, a host on the wrong key), or altered. Never answered as "no secret": an account would then sign in without the second factor it set up. The message names no key and no secret.

Omniauth\Otp\Testing

  • AuthenticatorApp class

    An authenticator application in PHP, for tests: it scans the otpauth:// address an enrolment gives (or takes a secret) and shows the code of the moment on the clock given - the code a person would type.

    5 methods

Omniauth\Otp

CacheUsedSteps class

final class CacheUsedSteps implements UsedSteps CacheUsedSteps.php:19

The last time step each account used, in any PSR-6 pool or PSR-16 cache: plain PHP, tests, and a host's cache pool (the same one its throttle uses is fine). Each entry lives only as long as its code could still verify.

Read then written, not atomic: two requests at the same instant with the same code may both pass. The throttle (five tries in 15 minutes per account) bounds what that leaves; a host that needs it exact keeps the steps where it can lock.

CacheUsedSteps::__construct()

public function __construct(readonly CacheItemPoolInterface|CacheInterface $cache, readonly string $prefix = 'omniauth.totp.')

CacheUsedSteps::claim()

public function claim(string $handle, int $step, int $ttl): bool

SealedTotpSecrets class

final class SealedTotpSecrets implements TotpSecrets SealedTotpSecrets.php:17

An application's TotpSecrets store with its secrets sealed by a box (SodiumSecretBox: Marco's decision QA5): what the store keeps is the box's, what TotpMethod reads is the base32 secret. A secret is opened only when a code is verified or the enrolment's QR code is drawn (secret()); whether an account has one is read without opening it (has()). A secret that does not open throws (Exception\UnreadableSecret): never "no secret", which would let the account in without its second factor.

SealedTotpSecrets::__construct()

public function __construct(readonly TotpSecrets $store, readonly SecretBox $box)

SealedTotpSecrets::secret()

public function secret(object $account): ?string

SealedTotpSecrets::has()

public function has(object $account): bool

Whether the account has a secret, without opening it.

SealedTotpSecrets::enable()

public function enable(object $account, string $secret): void

SealedTotpSecrets::disable()

public function disable(object $account): void

SodiumSecretBox class

final class SodiumSecretBox implements SecretBox SodiumSecretBox.php:27

The TOTP secrets sealed at rest with libsodium's secretbox (XSalsa20 and Poly1305: encrypted and authenticated) under one 32-byte key - Marco's decision QA5. What the store keeps:

otp:v1:<base64url, unpadded, of the 24-byte nonce then the box>

130 characters for a 52-character secret (scheb/2fa's and TotpMethod's): omnibase's user.secret (VARCHAR 255) holds it as it is. The prefix names the format and its version; a base32 secret (A-Z, 2-7, =) never starts with it, so open() tells a sealed secret from one kept in clear before the box and returns the latter as it is, until every row is sealed; seal() leaves a sealed value as it is (a rewrite of the rows runs twice harmlessly).

The key never lives in a file of the application's repository: the host reads it from its secrets vault or its environment (omniauth.yaml's totp.secret_key, config/omniauth.php's), base64 (fromBase64()), and both hosts of one database share it. Key rotation: docs/otp.md.

const PREFIX = 'otp:v1:'

SodiumSecretBox::__construct()

public function __construct(string $key)
$key

the 32 raw bytes of the key

SodiumSecretBox::fromBase64()

public static function fromBase64(string $key): self

From the key as a host keeps it: base64 (standard or URL-safe, padded or not) of 32 bytes.

SodiumSecretBox::generateKey()

public static function generateKey(): string

A new key, in base64: what goes into the vault (php -r "require 'vendor/autoload.php'; echo Omniauth\Otp\SodiumSecretBox::generateKey();").

SodiumSecretBox::isSealed()

public static function isSealed(string $stored): bool

Whether a stored value is sealed (by this format), without opening it.

SodiumSecretBox::seal()

public function seal(string $secret): string

SodiumSecretBox::open()

public function open(string $stored): string
Throws

UnreadableSecret a sealed value that does not open under this key

TotpMethod class

final class TotpMethod implements SecondFactor, Enrolling, Revocable TotpMethod.php:40

An authenticator application (TOTP, RFC 6238) as a second factor, over spomky-labs/otphp - the library scheb/2fa verifies with, on the parameters omnibase's User gives it (SHA1, 30 seconds, 6 digits) and the leeway every site sets (0): a code scheb accepts, this accepts, and the secrets kept today (user.secret, base32) go on working. One thing more than scheb: a code is accepted once, and none older than the last one accepted (Contract\UsedSteps).

verify(): ['code' => '123 456'] (spaces ignored). Enrolment: enrolBegin() draws a secret as scheb does and gives it with its otpauth:// address (Challenge::$data: 'secret', 'uri' - the host draws the QR code of 'uri'); enrolConfirm() checks a first code against it and keeps it in the store. revoke() forgets it. Secrets go through Contract\TotpSecrets; wrapped in SealedTotpSecrets with a SodiumSecretBox they are sealed at rest (QA5).

const ALGORITHM = 'sha1'

scheb/2fa's TOTP, as omnibase's User configures it and every site's scheb_two_factor.yaml leaves it.

const PERIOD = 30
const DIGITS = 6
const LEEWAY = 0

TotpMethod::__construct()

public function __construct(readonly Accounts $accounts, readonly TotpSecrets $secrets, readonly UsedSteps $used, readonly int $leeway = self::LEEWAY, readonly int $period = self::PERIOD, readonly int $digits = self::DIGITS, readonly string $algorithm = self::ALGORITHM, readonly ?string $issuer = null, readonly ?string $server = null, ?ClockInterface $clock = null)
$leeway

seconds a code is accepted before and after its period (scheb's leeway), lower than the period

$issuer

scheb's issuer: shown by the application

$server

scheb's server_name: appended to the label, "ringo@example.org"

TotpMethod::factor()

public function factor(): Factor

TotpMethod::enrolled()

public function enrolled(object $account): bool

TotpMethod::verify()

public function verify(Attempt $attempt, Proof $proof, Context $context): Verdict

TotpMethod::enrolBegin()

public function enrolBegin(Attempt $enrolment, Proof $proof, Context $context): Challenge

TotpMethod::enrolConfirm()

public function enrolConfirm(Attempt $enrolment, Proof $proof, Context $context): Enrolled

TotpMethod::revoke()

public function revoke(object $account): void

TotpMethod::uri()

public function uri(object $account, ?string $secret = null): ?string

The otpauth:// address an application scans, the same scheb/2fa's TotpAuthenticator::getQRContent() gives: the label is the account's identifier (omnibase's getTotpAuthenticationUsername()), "@" and the server name when one is set; the issuer when one is set. Of the account's own secret when none is given (the settings' QR code), or null when it has none.

TotpMethod::code()

public function code(string $secret, ?int $timestamp = null): string

The code of $secret at this moment (or at $timestamp): what the application shows.

TotpMethod::secret()

public static function secret(): string

A new secret as scheb/2fa draws it: 32 random bytes, base32, upper case, unpadded (52 characters).

Omniauth\Otp\Contract

SecretBox interface

interface SecretBox SecretBox.php:12

The secrets at rest (Marco's decision QA5, 2026-10-20: the TOTP secret encrypted with sodium, its key in the secrets vault). SodiumSecretBox is the box; SealedTotpSecrets wraps the application's TotpSecrets store with it, and TotpMethod never knows. Both hosts (omnibridge/symfony, omnibridge/laravel) build it from the same key.

SecretBox::seal()

public function seal(string $secret): string

What the store keeps for this base32 secret.

SecretBox::open()

public function open(string $stored): string

The base32 secret of what the store keeps. A box must read back the secrets kept before it existed (in clear) until every row is sealed: it tells them apart (a prefix, a version byte) and returns them as they are.

UsedSteps interface

interface UsedSteps UsedSteps.php:11

The time steps whose code an account already used: a code is accepted once (RFC 6238 §5.2), and none older than the last one accepted. Omniauth\Otp\CacheUsedSteps keeps them in any PSR-6 pool or PSR-16 cache; a host may keep them anywhere else (a column, its rate limiter's store).

UsedSteps::claim()

public function claim(string $handle, int $step, int $ttl): bool

Claims the code of $step for the account of $handle: true the first time, false when that step or a later one was already claimed.

$ttl

how long, in seconds, the claim must be remembered: past it the code of that step no longer verifies anyway

Omniauth\Otp\Exception

UnreadableSecret class

final class UnreadableSecret extends RuntimeException implements OmniauthException UnreadableSecret.php:13

A sealed secret that does not open: sealed under another key (a key rotated without its rows, a host on the wrong key), or altered. Never answered as "no secret": an account would then sign in without the second factor it set up. The message names no key and no secret.

Omniauth\Otp\Testing

AuthenticatorApp class

final class AuthenticatorApp AuthenticatorApp.php:15

An authenticator application in PHP, for tests: it scans the otpauth:// address an enrolment gives (or takes a secret) and shows the code of the moment on the clock given - the code a person would type.

AuthenticatorApp::scan()

public static function scan(string $uri, ClockInterface $clock): self

The application after scanning the QR code of $uri.

AuthenticatorApp::of()

public static function of(string $secret, ClockInterface $clock, int $period = 30, int $digits = 6, string $algorithm = 'sha1'): self

The application with a secret typed in (SHA1, 30 seconds, 6 digits unless told).

AuthenticatorApp::code()

public function code(int $periods = 0): string

The code shown now - or $periods periods from now (-1: the one before).

AuthenticatorApp::secret()

public function secret(): string

AuthenticatorApp::label()

public function label(): ?string