Skip to content

Letting someone act without an account

A customer must sign a quote. A supplier must confirm a date. These people have no account with you, never will, and creating one for them is out of the question.

The kernel provides the brick: a link pointing at a resource, and a single-use code sent by email to prove it is the intended recipient opening it.

from kewos.secure_link import issue_link_on, request_otp_on, verify_otp_on
from kewos.secure_link.types import OtpPurpose
with engine.begin() as conn:
token, ctx = issue_link_on(
conn,
resource_kind="library_loan",
resource_ref="19",
recipient_email="reader@example.test",
scope="loan:read",
secret_key=key,
)

token is the only plaintext copy: you put it in the email’s URL, and it is stored nowhere. Run:

plaintext token : kws_sl_2_f... (50 characters)
in the database : 67cac6636cba5ff24d3b... (is the plaintext token there? False)

A stolen database yields no usable link: it holds hashes only.

The single-use code

with engine.begin() as conn:
request_otp_on(
conn, link_id=ctx.link_id, purpose=OtpPurpose.OPEN,
recipient_email="reader@example.test", from_address="no-reply@example.test",
render_email=my_template, secret_key=key,
)

The email leaves through the transactional outbox (rule 17): if your transaction fails, the code is never sent. Run:

code : 6 digits
is the plaintext code stored? : False
wrong code : OtpInvalidError
right code : accepted
the same one, replayed : OtpNotFoundError

That last line is the property that matters: a code works once. It is consumed on verification, so replaying an intercepted email gets nothing.

What the kernel holds for you

GuaranteeDefault
Code lifetime10 minutes
Sends per window3 per 10 minutes
Attempts before lockout5
StorageHMAC hash only, never the code nor the token
Traceabilityevery outcome audited, never the code (rule 13)
Channelemail only, never SMS

The five-attempt lockout is what makes six digits acceptable: without it, a short code is guessable.

Two consents rather than one

OtpPurpose separates opening (OPEN) from acting (APPLY). Two distinct codes, and deliberately so: reading a document and signing it are not the same act. A third party who has opened has not yet consented.