本文へ移動
cccskills
無料GitHub で公開

authentication-portal-cross-device

Maintain optional cross-device portal login, its directive parser, QR and polling UI, approving-browser binding, single-use transfers, MFA and provider evidence, logout invalidation, and TLS/browser tests.

インストール方法を見る

含まれるファイル(2)

  • SKILL.md14.8 KB
  • agents/openai.yaml292 B

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Cross-Device Portal Login

Configuration and ownership

authn.CrossDeviceLoginConfig.Enabled is an explicit opt-in. Nil, omitted and zero configurations disable both routes and login links. Assign the result of pkg/authn/cross_device/parser.NewCrossDeviceLoginConfigFromDirectives(statements) to PortalConfig.CrossDeviceLogin before construction. The parser accepts complete enable cross-device login or disable cross-device login statements encoded with cfgutil.EncodeArgs. Empty input disables; duplicate/conflicting settings, extra tokens, joined keywords and multiline records fail without partial output or echoed values. Collect all feature statements before parsing. JSON/XML/YAML use cross_device_login with nested enabled; serialization preserves the opt-in.

Portal-owned implementation uses the cross_device_ filename prefix. The embedded cross_device template and core/js/cross_device.js serve the flow. The login template exposes the action inside user_actions for local and provider-only configurations and beside the provider choices for mixed portals. Filesystem login overrides must add the opt-in action themselves; the built-in new template remains available unless overridden. The old /qrcode/login.png bookmark still encodes ordinary portal navigation and is a separate feature.

The cross-device presentation contract owns step-specific headings, prominent matching codes, copy fallback, action layout, recovery labels, and optional Chrome screenshot capture. Built-in requester terminal states hide inactive controls and offer a fresh request; clipboard feedback remains separate from lifecycle status. Neither presentation changes nor recovery controls weaken explicit approval or revive a stopped interaction.

Browser and HTTP contract

All routes are relative to the portal mount; nested and root mounts work. Match the complete route segment so mounts such as /cross-device-team/auth continue to serve ordinary login and the transfer flow. Existing route namespaces retain ownership of names such as /oauth2/cross-device and /assets/js/cross-device, whether the feature is enabled or disabled. The /provider/<realm> namespace also retains ownership; /provider/cross-device is a provider login, while /cross-device/provider/... remains an invalid transfer endpoint. The optional HTTP login capability does not supply cross-device completion evidence. An unknown child beneath the actual transfer route must remain a 404, including children resembling other routes. This is a browser login transfer, not an RFC 8628 device authorization endpoint.

RouteMethodResult
/cross-deviceGETRequesting page; JavaScript starts an interaction
/cross-device/startPOSTIndependent activation code and requester secret, PNG data URI, verification URI, matching display code, 300-second lifetime and 2-second interval
/cross-device/activate?code=...GETMatching-code warning and form; new approving-browser binding cookie
/cross-device/beginPOSTChecks activation code and browser CSRF value, binds the interaction, starts a fresh portal login
/cross-device/confirmGET / POSTShows the authenticated account and matching code; explicit approve or deny
/cross-device/pollPOSTPending/slow-down status, or one-time cookie issuance and a next destination
/cross-device/cancelPOSTCancels an unconsumed interaction

The fresh login opened when the approving browser binds an interaction renders without the login page's signed-in-elsewhere probe, so a session another tab holds or renews cannot carry the approving browser away before it completes the interactive login. Going back from the password step or starting over keeps that login fresh.

POSTs require HTTPS, exactly one matching Origin, compatible Fetch Metadata, and a form body bounded to 4 KiB, including unknown-length/chunked requests. Require one valid Content-Type header; accept URL-encoded media types with parameters such as charset=UTF-8. Oversized bodies return 413, unsupported media types return 415, and malformed/ambiguous forms return 400. Duplicate form values, Content-Type headers and binding cookies fail closed. A method error advertises all methods supported by that endpoint, including GET and POST for confirmation. The host must normalize trusted forwarded metadata before calling the library. The requesting secret travels in form bodies only; the QR and copyable link contain only the activation code. Browser JavaScript retains capabilities only in page memory, polls serially every two seconds, and stops on expiry, cancellation, navigation, denial or ambiguous network failure. Reloading the requester starts over. Navigation clears the pending capability and hides the QR/link with a terminal status, so a restored history document cannot display a stopped request as waiting. Late network or clipboard results must not replace a terminal status. A lost redeemed response requires a fresh interaction; there is no retry grace that can mint a second credential family.

Use the original AbortController/event-listener APIs for bounded fetches; the flow must not require AbortSignal.any or AbortSignal.timeout. Abort in-flight work on cancellation/navigation, bound start/poll requests and response-body reads to ten seconds, and give cleanup cancellation its own five-second budget. Remove the parent abort listener and clear the deadline on every exit. A late start result must be cancelled without revealing its QR/link or restarting polling.

Responses disable caching and framing, confine content/form submission to the same origin, and use Referrer-Policy: strict-origin. Do not switch the form page to no-referrer: Chrome then sends Origin: null, breaking strict CSRF checks. Strict-origin omits the activation path and query from referrers.

The shared cookie role is CrossDeviceSessionIDCookieName, default AUTHP_CROSS_DEVICE_SESSION_ID. cookie cross-device session id name <name> and cookie prefix <prefix> configure it through the shared cookie parser. The factory always emits Secure, HttpOnly, host-only, mount-scoped, SameSite=None, 300-second cookies; None permits signed cross-site SAML POST callbacks. Its CSRF protection comes from origin checks, random binding and explicit approval, not SameSite. Deletion matches issuance. Optional __Host- names require root mounts; no reserved prefix is required.

Evidence, issuance and lifecycle

A code alone cannot authenticate either device. The approving browser must complete ordinary HTML password/MFA, OAuth or SAML login after binding, then explicitly approve the displayed account and matching code. Preexisting JWTs, API-key/Basic login and JSON login cannot supply completion. Never auto-approve on a GET or immediately after a provider callback. Matching-code warnings help users detect unsolicited QR requests; possession of a link is not evidence that the requesting device belongs to them.

The store snapshots completed sandbox proof or authenticated upstream attributes before portal transforms. It also binds the proof to the issued session token. Only local/LDAP proofs go through issueSandboxTokens; local identity/version checks and current challenge policy run again for the requesting address and issuer. AMR comes from verified checkpoints. Refresh and OIDC, when configured, create independent browser credentials using the normal issuer/completion APIs.

OAuth/SAML transfer rechecks the configured backend, uses the captured upstream attributes, reruns transforms for the requesting device, and checks additional local-factor requirements. Retain the original protocol method (oauth2 versus the provider kind oauth) so GitHub claim ownership remains correct. Decode snapshots with JSON-number preservation. Provider transfer expiry cannot exceed the original portal login; upstream ID/refresh tokens are not copied. Upstream revocation cannot be detected beyond the provider's existing login/session contract; this feature does not add introspection.

For a selected OAuth snapshot realm, the approving browser has an opaque portal family while the requester remains access-only. Decode the bounded canonical snapshot, normalize recognized nested roles before current requester policy, and keep the resulting roles authoritative through signing. Carry federated AMR and original authentication time from the approving issuer's verified evidence, never upstream AMR/ACR. Do not copy its SID or refresh credential. Use refresh-token-identity to maintain snapshot capture, role authority and the selected-provider trust boundary.

Each requester receives a fresh session ID and ordinary credential cookies; poll JSON never includes bearer tokens. If grant, persistence or OIDC completion fails, remove newly cached credentials, revoke an undelivered refresh family, and restore response headers before returning failure. No credential-bearing response precedes successful completion.

Pending records live only in the owning portal, including when runtime-state persistence is enabled. They expire after five minutes, are pruned on admission, and disappear on Close/restart. Bounds are 1024 active requests total and eight per trusted source address; they are fixed runtime limits, not configuration. A binding cannot select multiple live requests. Approval is bound to the exact form displayed: when another approving tab changes the binding cookie and account, an old confirmation must not approve the new request. Its CSRF token must still match that browser's current binding. Mutex-protected approval consumption precedes issuance; concurrent polls mint at most one result. Cancellation/denial before consumption prevents issuance. Cancellation cannot undo a redemption that already won the race. Portal, external-provider and browser refresh logout invalidate outstanding transfers by session or family. Before confirmation and redemption, validate both the cached approving access session and any associated refresh family. Obtain the family reference from the committed local issuer result, never an arbitrary sid claim. Use the refresh manager's read-only ValidateSession: normal rotation remains live; replay, replacement, logout without an access cookie, expiry and unavailable storage fail closed. Never look up a captured old refresh credential, which would itself trigger replay revocation. This liveness check adds no authentication authority to a public family ID. A concurrent revocation cannot undo a completed transfer. Local credential revocation and a stronger current challenge policy also deny redemption. Sharing one portal across hosts/mounts does not permit cross-scope capabilities; each interaction fixes its HTTPS origin and mount.

Validation

Parser unit tests and its executable example cover grammar, defaults, redaction, independent results and serialized opt-in. Store tests cover scope, snapshots, capacity, expiry, binding uniqueness, cancellation/logout, shutdown and concurrent single redemption. Cookie tests cover names, collisions and fixed attributes.

cross_device_e2e_test.go uses public parsers, temporary local databases, separate cookie jars and TLS production handlers. It covers local/MFA, root/nested mounts, refresh/OIDC coexistence, signed upstream OAuth/SAML, independent credentials, JWKS/gatekeeper verification, wrong secrets/origins, explicit approval, denial, cancellation, revocation, current policy, expired login, logout and concurrency. Keep explicit family lifecycle cases for rotation, replay, account replacement and logout after the access cookie is removed. Verify access-only custom sid claims remain independent of local refresh state, and provider names equal to cross-device still complete real login with the feature on or off. Keep a two-account stale-form case with two requesting browsers and one approving cookie jar: a stale form cannot approve either request, and a valid new form delivers credentials only to its corresponding requester. Completion-capacity rejection must deliver no credentials and release the undelivered refresh family for subsequent logins. TestTokenRefreshProviderCrossDevice and TestE2ETokenRefreshProviderCrossDevice cover selected-provider snapshot composition: healthy approving-family rotation, requesting-device role overwrite and factor denial, verified AMR/authentication time, and access-only issuance. cross_device_browser_e2e_test.go runs Chrome with isolated browser contexts and real forms, QR rendering, responsive layout, scheduled polling, cookie checks, navigation and history recovery. Disable the newer AbortSignal static helpers in that browser fixture to exercise compatibility through real fetches and forms; this is not physical TV/VR certification. Node client tests complement it with expiry, request/body deadlines, and late-start/poll/clipboard cancellation races. The browser journey also checks approval/denial and recovery presentation across phone/tablet/desktop widths, real clipboard success/denial, and keyboard focus. Set AUTHCRUNCH_CROSS_DEVICE_SCREENSHOT_DIR to an ignored review directory to retain the captures described in the presentation contract. Keep the legacy filesystem-theme journey: presentation wrappers must remain optional for the original polling, copying, cancellation, and redemption hooks.

make test TEST_DIR='./pkg/authn ./pkg/authn/cookie/... ./pkg/authn/cross_device/parser ./pkg/authn/token_refresh' TEST='CrossDevice|ExampleNewCrossDevice|ValidateSession|ExtractBasePathCookieMount|PersistentRefreshReplayAndRevocation' COVERAGE_DIR=.coverage/cross-device
make test-ui
make ci-check

Requester destinations

The request page carries its validated redirect_url into the start POST query; the 4096-byte form-body limit stays unchanged. Start binds the destination to the pending transfer independently of approving-browser evidence. It is never included in the activation link or QR. Poll redemption revalidates that stored value and marks the response destination bound, including an empty choice. Approval, callback/poll query values and shared cookies cannot replace it. An empty or rejected destination goes to portal?redirect_url=. The ordinary login link and older filesystem request themes receive the same context through the renderer. Preserve the start-only query in the client; poll/cancel carry only their existing body capabilities.

TestCrossDeviceStoreRequesterDestinations checks immutable requester ownership; TestE2ECrossDeviceRequesterDestinationIsolation approves multiple requests in reverse order with conflicting cookies and poll queries. Real Chrome exercises destination navigation with both basic and legacy request themes.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

authdb

無料

Maintain the standalone cmd/authdb server, pkg/httpserver listener and portal routing, HTTP configuration parser, TLS, shutdown, executable tests, and deployment guidance. Use authdbctl for the management client.

日本語の概要は準備中です。原文の説明を表示しています。

greenpau/go-authcrunch602026年10月11日 更新

authdbctl

無料

Maintain cmd/authdbctl commands, flags, configuration, terminal input, management retries, output, and executable E2E tests. Use authentication-client for the reusable portal login protocol.

日本語の概要は準備中です。原文の説明を表示しています。

greenpau/go-authcrunch602026年10月11日 更新

Maintain or embed pkg/authclient for portal login, password/TOTP and API-key authentication, native credential transport, configuration parsing, and credential files. Covers authdbctl login wiring; management commands and the admin API have separate owners.

日本語の概要は準備中です。原文の説明を表示しています。

greenpau/go-authcrunch602026年10月11日 更新

Maintain conditional authentication challenge policies, reusable authchal and user-transform FromDirectives parsers, safe claim substitution, GitHub ID/organization transforms, registered-factor inventory, passwordless WebAuthn selection, verified AMR access claims, and policy revalidation across portal login, refresh, OIDC, and direct authentication.

日本語の概要は準備中です。原文の説明を表示しています。

greenpau/go-authcrunch602026年10月11日 更新

Maintain portal cookie configuration, reusable cookie directive parsing, common prefixes and explicit names, domain attributes, factory issuance/deletion, and cookie interoperability with OIDC, refresh, OAuth, and gatekeepers.

日本語の概要は準備中です。原文の説明を表示しています。

greenpau/go-authcrunch602026年10月11日 更新

Maintain the opt-in encrypted Documents API, immutable account ownership, SQLite ciphertext storage, chunk transactions, recipient key envelopes, configuration parser, and TLS/browser cryptographic tests. The separately maintained React application has its own integration skill.

日本語の概要は準備中です。原文の説明を表示しています。

greenpau/go-authcrunch602026年10月11日 更新

greenpau のスキルをすべて見る

このスキルの問題を報告する