Files
preauth/.env.test
T
lyra ffb824c652 Add the passkey listener at priority 70
Priority 70 sits after RejectListener (77) and before LoginListener (66), and
both bounds are load-bearing:

- After 77 so a rate-limited IP never reaches a ceremony. Passkeys cannot be
  used to sidestep a lockout (D3), which is the point of the reviewer's third
  clarification.
- Before 66 because LoginListener treats any POST to the auth subdomain as a
  login attempt. A ceremony finish body has no username/totp, so Payload::load()
  returns null and the request would be scored as a failed login, burning a
  rate-limit token for every legitimate passkey login.

Verified in the live container rather than assumed: debug:event-dispatcher
confirms 77 -> 70 -> 66.

Other properties asserted by tests: every header-bearing request gets a JSON
response so fetch() callers never receive HTML; registration identity comes from
the live session, never the request body; a failed ceremony is indistinguishable
from a wrong TOTP code and spends the same shared budget; and begin is bounded
by a separate resource guard that deliberately does not consume failure budget.

The listener also marks its responses so SecurityHeadersListener can apply
no-store: these are the only browser-facing 2xx this application produces, since
the auth subdomain has no forward_auth in front of it. CSP gains
publickey-credentials-get/-create only when passkeys are available, so the
unavailable case stays byte-identical to before.
2026-09-27 10:50:09 +00:00

41 lines
1.0 KiB
Bash

APP_ENV=test
APP_DEBUG=0
APP_SECRET=test_secret_key_change_me
# fixed TOTP secret (JBSWY3DPEHPK3PXP) so functional tests can compute valid codes
TOTP_URI='otpauth://totp/Test-TOTP?secret=JBSWY3DPEHPK3PXP'
COOKIE_TTL=2592000
SUBDOMAIN_REDIRECT=0
AUTH_SUBDOMAIN=''
IP_TTL=0
TEAPOT=1
BURST_COUNT=10
BURST_TIME=30
UPPER_COUNT=100
UPPER_TIME=3600
PASSKEY_ENABLED=0
PASSKEY_RP_NAME=''
PASSKEY_USER_VERIFICATION='required'
PASSKEY_TIMEOUT=60000
PASSKEY_BUTTON_NAME='Sign in with a passkey'
PASSKEY_REGISTER_NAME='Register this device as a passkey'
PASSKEY_BEGIN_BURST_COUNT=30
PASSKEY_BEGIN_BURST_TIME=60
PUBLIC_PATHS=''
PUBLIC_BURST_COUNT=100
PUBLIC_BURST_TIME=60
PUBLIC_UPPER_COUNT=500
PUBLIC_UPPER_TIME=3600
TITLE='Pre-Authentication System'
BG_COLOR='#029386'
FG_COLOR='#ffffff'
ERROR_COLOR='#ffb16d'
ID_NAME='Session ID'
TOKEN_NAME='Authentication Token'
SUBMIT_NAME='Submit'
ERROR_MESSAGE='Unsuccessful login attempt'
TEAPOT_TITLE="I'm a teapot"
TEAPOT_MESSAGE='I refuse to brew coffee'
TOO_MANY_TITLE='Too many requests'
TOO_MANY_MESSAGE='Try again later'
SHELL_VERBOSITY=0