Nexus Passkey Tester

Exercise the Nexus Cognito passwordless / passkey (WebAuthn) flow against the real user pool, using AWS SDK v3 in the browser.

Passkey note: WebAuthn is origin-bound — the browser requires this page's domain to match the pool's Relying Party ID (RP ID), which is nexus.staging.11os.net. So passkey enroll/sign-in only works when this page is served from a *.nexus.staging.11os.net origin over HTTPS (e.g. https://passkey.nexus.staging.11os.net:5173 — see the README for the hosts + mkcert setup). EMAIL_OTP and password bootstrap work on plain http://localhost. A SecurityError during a passkey step almost always means the page isn't on the RP-ID domain.

Configuration

Pre-filled with dev values. Saved to this browser (localStorage).

Bootstrap a session

Get an access token without a passkey yet, so a brand-new user can enroll one.

A) Password (nexus-test client · USER_PASSWORD_AUTH)

B) EMAIL_OTP (nexus-app client · USER_AUTH choice flow)

Enroll a passkey

Requires a signed-in session (an access token from a bootstrap above). Runs StartWebAuthnRegistration → navigator.credentials.create() → CompleteWebAuthnRegistration.


  

Sign in with a passkey (passwordless)

USER_AUTH choice flow with PREFERRED_CHALLENGE: WEB_AUTHN on the nexus-app client → navigator.credentials.get() → RespondToAuthChallenge.

Tokens

No session yet.

ID token claims


    

Access token claims (what the authorizer reads)


    
Raw access token (Bearer)

    

Call the API

Proves the token works. GET {apiBase}/me/capabilities with Authorization: Bearer <accessToken>.

Properties /properties

Properties you're entitled to (ABAC — your grants' match facets vs each property's facets; the row's access lists your matched roles). Click an id to fetch GET /properties/{id}.

Create a property POST /properties

Metadata (all optional)

Accounts /accounts (nexus_admin / retail_admin)

Every account (ACCOUNT# slice) with its disabled flag and ABAC grants. Click an email to load it below. Admin routes need a nexus_admin grant (unrestricted) or a retail_admin grant (scoped to its facets).

Create an account POST /accounts

Access is grant-based — set grants to give access. custom:role is vestigial (the authorizer ignores it). Grant roles: retail_read (view) · retail_write (view+edit) · retail_admin (scoped admin) · nexus_admin (global admin).

Pick the facet(s) a grant must match + a role, then + add grant. No facets = a global grant.

No grants added.

Manage one account

Patch PATCH /accounts/{email}

Grants /accounts/{email}/grants

Portals /portals (admin)

Captive-portal configs (PORTAL# slices). The guest broker at portal.<domain> facet-matches a device to one of these. Click an id to fetch GET /portals/{id} and edit/delete it. Note: responses use snake_case (portal_id, portal_url, landing_mode, landing_url); create/patch bodies use camelCase. The list is scoped to portals your grants let you view (the row's access shows your matched roles).

Create a portal POST /portals

Manage one portal

Patch PATCH /portals/{id} (omitted fields unchanged)

Sessions /reports/sessions (Connectivity Overview)

Concurrent session counts by identity provider over a time window (one series per provider). Open endpoint — no auth required; data is currently synthetic.

Pick a predefined range, or custom to unlock from/to. The date pickers fill the Unix fields with that UTC day's bounds (from → 00:00:00Z, to → 23:59:59Z); you can still edit the raw Unix seconds. The mapping applies to all three reports. All banners → corporate · a banner + All sites → banner · a site → store.

Identity providers /reports/identity-providers

Session share by identity provider over the window (count + fractional share). Single aggregate — no time series. Open endpoint — no auth required; data is synthetic.

Authentication health /reports/authentication-health

Per-period Access-Accept / Access-Reject counts (rejects exclude MAC-auth) with a success-rate overlay, plus window summary metrics. Bucket interval is derived server-side from the window. Open endpoint — no auth required; data is synthetic.

Log