Repository navigation
feat: v0.20 recovery sessions, account notice delivery and console headers - #14
Merged
Merged
Conversation
…ole proxy The console proxy forwarded only Content-Type, Cache-Control, ETag and Last-Modified, so the API's X-Frame-Options, Content-Security-Policy and X-Content-Type-Options were dropped and the console served on the application's origin could be framed. Forward those three as well. Closes #12
A placeholder such as the starters' dev-only-cookie-signing-key-replace-me is long enough to pass the length check, and it is public. Refuse it, the GRAB_FROM_SEAMLESS_AUTH_PORTAL_DEV example, and anything containing replace-me, for both cookie_secret and service_secret, unless insecure_cookies is set for local development. Refs fells-code/seamless-auth-server#231
An access token from a recovery code or self-service recovery carries recovery: true, and the auth API refuses it on everything but enrolling a new factor. The guard now refuses it too, raising EnrollmentRequired (a subclass of Unauthenticated) that the bindings answer 403 enrollment_required, so an application does not treat a half-recovered account as signed in. RequireUser(allow_recovery=True), @require_auth(allow_recovery=True) and authenticate(allow_recovery=True) admit it, and User.recovery reports it. When a recovery session in cookie transport completes passkey registration or TOTP enrollment, the adapter refreshes in the same response so the access cookie drops the claim. A bearer client refreshes itself. Refs fells-code/seamless-auth-server#232
…outes The auth API tells an account's owner when recovery opens, and hands the notices back to an adapter that owns delivery and names their kinds. - With deliver and the new deliver_account_notices=True, a manifest route marked notices (today POST /recovery/verify) asks for external delivery with x-seamless-auth-delivery-kinds: account_notice_email,account_notice_sms, delivers every item in the response's deliveries, and strips them before answering. Without the option the header is not sent and the API sends the notices itself, because it counts a returned notice as the owner being told. - Delivery gains notice, subject, text and cancel_url (hidden from repr, never logged), and purpose, which is account_recovery on a recovery code. - An unknown delivery kind is logged and skipped. A failed notice no longer stops the others, and a delivery error is logged by type only. - The manifest parser keeps the optional notices field, and the bundled manifest is synced from the API (0.19.4), which adds the recovery, recovery-code and system-config policy routes. 503 recovery_notice_failed and 403 step_up_required bodies pass through unchanged. Closes #13
The auth API opens a recovery request once it hands the notices back, and counts the owner as told. If the application delivers none of them, the owner has not been told, so the adapter now cancels the request through POST /recovery/cancel with the token from the notice's cancel link and answers 503 recovery_notice_failed. One delivered notice is enough to answer normally. The cancel link and its token are never logged. Refs #13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The v0.20 work for the Python adapter: the console proxy headers, placeholder secrets, recovery sessions, and account recovery notice delivery.
#12: console proxy headers
X-Frame-Options,Content-Security-PolicyandX-Content-Type-Options, onGETandHEAD, so the console served on the app origin cannot be framed.Placeholder secrets (fells-code/seamless-auth-server#231)
Adapterrefusescookie_secretorservice_secretset todev-only-cookie-signing-key-replace-me,GRAB_FROM_SEAMLESS_AUTH_PORTAL_DEV, or anything containingreplace-me(case-insensitive).insecure_cookies=True, the adapter's local development mode.Recovery sessions (fells-code/seamless-auth-server#232)
recovery: true(from the cookie or a bearer token) by raisingEnrollmentRequired, a subclass ofUnauthenticated. Only a literaltruecounts.require_authanswers 403{"error": "enrollment_required"}.RequireUseranswers 403{"detail": "enrollment_required"}, matching its existing 401 and 403 bodies.RequireUser(auth, allow_recovery=True),@require_auth(allow_recovery=True)andauthenticate(..., allow_recovery=True).User.recoveryreports the state.POST /webauthn/register/finishorPOST /totp/enroll/verify, the adapter refreshes in the same response, so the access cookie drops the claim.POST /auth/refreshitself. This is documented.#13: account recovery delivery
deliver_account_notices(defaultFalse, needsdeliver). With it set, a manifest route markednotices: true(todayPOST /recovery/verify) is called with external delivery, the delivery service token, andx-seamless-auth-delivery-kinds: account_notice_email,account_notice_sms.deliveriesand stripsdeliveriesfrom the response in both transports.POST /recovery/cancel{"cancelToken": <fragment of cancelUrl>}(proxy service token, no credential) and answers 503{"error": "recovery_notice_failed"}.Deliverygainsnotice,subject,text,cancel_urlandpurpose, plusis_account_recovery.cancel_urlandtext(which contains the link) are hidden fromrepr.otp_emailandotp_smswithpurpose: "account_recovery"reach the callback with that purpose. The README asks apps to word them as a recovery code.noticesfield. The bundled manifest is synced from the API's committed copy (apiVersion 0.19.4), which adds the/recovery/*,/recovery-codes*,GET /recovery/requests,DELETE /recovery/requests/{id}and/system-config/policy*routes.recovery_notice_failed, 403step_up_required, every new access route, and the pre-auth recovery routes, including/recovery/completeissuing a recovery session.Checks
Each commit was also checked on its own (ruff, mypy, pytest). The conformance suite was not run locally; it runs in CI.
Closes #12
Closes #13