Repository navigation
feat(admin): step up admin writes with an authenticator app code - #315
Merged
Merged
Conversation
From auth server v0.20 every admin write answers 403 step_up_required until the session has a fresh step-up. The instance client now verifies an authenticator app code on the same session and retries the write once, for every command and every migrate batch. prepare-device-replacement sends the identity proofing record the server requires.
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.
Closes #245
From auth server v0.20 (fells-code/seamless-auth-api#490) every admin write answers
403 {error: "step_up_required", ...status}until the session has a fresh step-up. The CLI mapped any 403 to "requires an admin role", so these commands failed with a misleading message.What changes
src/core/authClient.ts). When a response is403 step_up_required, the client runs a step-up handler and retries the same request once on the same session. Because it sits under every wrapper, it applies to eachmigratebatch, not only the first, so a run that outlasts the 5 minute window asks for a new code before the next batch. Concurrent refusals share one step-up, the same way refresh is single-flight. Portal clients never step up.src/core/stepUp.ts):GET /totp/statusfirst./totp/verify-mfaanswers401 totp_verification_failedfor an account with no TOTP as well as for a wrong code, so the status call is the only way to tell them apart. With nothing enrolled, the CLI tells the user to enroll an authenticator app (dashboard or app) or use the dashboard.--json), validates the code with the sharedTotpVerifyRequestSchema, and strips the spaces apps show.401 totp_verification_failed: re-prompts, at most 3 attempts.423 account_locked: reportsretryAfterSeconds.429: reportsRetry-After.SEAMLESS_TOTP_CODEsupplies a code without one (same pattern asSEAMLESS_REFRESH_TOKEN). It is used once per run because codes are single use.forbidden(res)gives aStepUpError(aPermissionErrorsubclass, so existing handlers print it) forstep_up_required, and the plain admin-role error otherwise. It is used inadmin.tscall(), everysystemConfig.tswrapper andmigrate.ts.totp_verification_failedis now returned as is.DeviceReplacementRecoverySchemarequires:--proofing <in_person|remote_exception> --evidence-ref <ref> [--approver <name>], validated locally withRecoveryProofingSchema. Without it the v0.20 API rejects the request, so this is a breaking flag change (minor changeset, described in the body).PermissionErrormoved tosrc/core/permissionError.tsto avoid an import cycle. It is still re-exported fromsystemConfig.tsandadmin.ts.Commands covered
config set,config apply,config oauth-providers add|update|remove,users delete,users prepare-device-replacement,org create|update,org members add|update|remove,migrate csv --applyandmigrate entra-id(dry runs too, since the import route is gated).Checks
npm run build: passesnpm test: 69 files passed (1 skipped), 1480 tests passed, 4 skippednpm run coverage: passes thresholds (statements 98.88, branches 96.24, functions 98.36, lines 99.22)Help topics (config, users, org, migrate), README and AGENTS.md are updated.