CoolCMS API

ExternalLinkConfirmation
in package

FinalYes

Pairing an OAuth identity with an existing password account needs the account owner's confirmation by e-mail ("pre-hijacking" protection).

Why: with account.activation.auto = 1 anyone can register an account with somebody else's e-mail (nothing verifies it). When the real owner of the e-mail later signs in with Google, a provider-verified e-mail used to pair automatically — and the victim ended up in the attacker's account. A password account is therefore paired only after its owner clicks the one-time link sent to the account's e-mail.

The plain token travels only in the e-mailed link; the database keeps its sha256 hash and an expiry (same scheme as PasswordResetToken). Pure, no I/O — the Api managers own storage and delivery.

Table of Contents

Constants

RESEND_INTERVAL_SECONDS  : int = 900
At most one confirmation e-mail per account in this window. A repeated sign-in attempt inside it keeps the pending request (and the already e-mailed link) untouched, so it never invalidates the link the owner is about to click.
TTL_SECONDS  : int = 86400
Link validity (24 h).

Methods

buildExpiry()  : DateTime
canResend()  : bool
May a new confirmation e-mail be sent? `$lastRequestedAt` = when the currently pending request was created (`null` = none pending).
generate()  : string
hash()  : string
isRequired()  : bool
Does an account with this state need the e-mail confirmation before an OAuth identity found by e-mail may be paired with it?
isValid()  : bool
Is the stored request still usable? The token itself is looked up by its hash, so this only checks the expiry.
providerLabel()  : string
Human name of the provider for the e-mail text.

Constants

RESEND_INTERVAL_SECONDS

At most one confirmation e-mail per account in this window. A repeated sign-in attempt inside it keeps the pending request (and the already e-mailed link) untouched, so it never invalidates the link the owner is about to click.

public int RESEND_INTERVAL_SECONDS = 900

Methods

buildExpiry()

public static buildExpiry(DateTimeInterface $now) : DateTime
Parameters
$now : DateTimeInterface
Return values
DateTime

canResend()

May a new confirmation e-mail be sent? `$lastRequestedAt` = when the currently pending request was created (`null` = none pending).

public static canResend(DateTimeInterface|null $lastRequestedAt, DateTimeInterface $now) : bool
Parameters
$lastRequestedAt : DateTimeInterface|null
$now : DateTimeInterface
Return values
bool

hash()

public static hash(string $plainToken) : string
Parameters
$plainToken : string
Return values
string

isRequired()

Does an account with this state need the e-mail confirmation before an OAuth identity found by e-mail may be paired with it?

public static isRequired(string|null $passwordHash, string|null $externalId) : bool
  • a password is set and the account carries no provider identity yet ⇒ yes (it was registered with a password, nobody has proven the e-mail belongs to its owner),
  • no password (the account was created by an OAuth sign-in) ⇒ no, pairs automatically,
  • a provider identity is already stored (externalId) ⇒ no — the e-mail was proven by the provider when the account was created or by an earlier confirmed pairing.
Parameters
$passwordHash : string|null
$externalId : string|null
Return values
bool

isValid()

Is the stored request still usable? The token itself is looked up by its hash, so this only checks the expiry.

public static isValid(DateTimeInterface|null $expiresAt, DateTimeInterface $now) : bool
Parameters
$expiresAt : DateTimeInterface|null
$now : DateTimeInterface
Return values
bool

providerLabel()

Human name of the provider for the e-mail text.

public static providerLabel(string $provider) : string
Parameters
$provider : string
Return values
string
On this page

Search results