Architectural guidance for coding agents adding private customer access, connections, background work, subscriptions or service credits to existing apps. Specs only; reuse the host and chosen providers.
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Use when an existing app gains sign-in or lacks a coherent return-to-app flow. Skip solved parts. External-service API consent is a separate connection, not the app session.
User is the existing local actor. Identity is the provider's stable verified subject, namespaced by issuer/project as appropriate. Each accepted identity maps to exactly one user; a user may have multiple identities only if linking is supported. Session authenticates one user; the auth service may own all session storage. See diagrams.
Reuse the managed auth user ID as the local key when it already fits. An extra identity mapping exists only when the host ID differs or supported linking requires it. Email is contact information, not a safe automatic cross-provider account-linking key. Do not create an AppLift session store or token format.
Names below describe meanings, not required columns. Availability is required for the selected workflow; new storage is not.
| Information / meaning | Authority and simplest source | Needed when / workflow it enables |
|---|---|---|
user_id: stable local actor | Existing host user key, or managed auth user key already used by the host | Every authenticated operation needs a consistent actor; preserve existing IDs. |
issuer + subject: namespaced provider identity, associated with user_id | Verified auth result plus trusted host mapping; a fixed issuer/project may come from configuration | Resolves repeat sign-in to the same user. Add a mapping only if the provider identity cannot already resolve the host user. |
| Authenticated actor and session validity/expiry | Supported auth verifier/session service; expiry alone does not establish validity | Protected requests and session restoration need the verifier's result. Reuse SDK refresh/rejection behavior rather than adding local token or session columns. |
Email/name are optional contact/display values, not identity keys. Add them only for a selected screen, communication or explicit signup policy; use the provider's verification information if that policy depends on verified email. Tokens, credentials and provider recovery records do not belong in this field mapping.
users.id; optional identities(issuer, subject, user_id) with unique (issuer, subject). Sessions stay with the auth service unless the app already owns them.| Trigger / actor | Authority and effect | Repeat or failure / user outcome |
|---|---|---|
| User starts login | Supported provider SDK owns redirect, state/nonce and code verification appropriate to the flow. | Cancel returns to login without creating partial access. Preserve safe return location. |
| Verified callback arrives | Resolve stable identity. Reuse user; create only if signup policy allows it. Commit mapping and any required local user creation together. | Repeat resolves the same user. Existing-only signup rejects unknown identities. Linking requires authenticated proof under an explicit policy. |
| App opens / session expires | SDK restores or refreshes session. Backend verifies it and derives user ID; request body cannot select another actor. | Transient service failure offers bounded retry. Invalid/revoked session clears private context and requests sign-in; avoid redirect loops. |
| User signs out | Invoke provider-supported session invalidation/logout and clear local private caches. | Repeated logout is harmless. State whether logout affects this device or all sessions using provider capabilities. |
| User loses provider account | Provider owns account recovery. | Explain provider recovery route. App-owner recovery, if offered, requires a separate explicit proof process; never relink solely by matching email. |
Before redirecting after expiry, preserve unsent work only if safe; do not leak private drafts into shared browser storage or restore them to a different user. Sign-in recovery does not recreate revoked team membership.
Concrete transition: a returning user stays signed in and ordinary requests reuse valid authentication without unnecessary provider calls. Inspect the chosen SDK and actual network path before diagnosing repeated refreshes. Preserve provider persistence/renewal defaults unless the device or security policy justifies an override; use native SDK/session facilities rather than a new custom session framework.
| Layer | Required behavior |
|---|---|
| Client session and token renewal | Restore the SDK-managed session under the agreed device policy. Reuse a usable token through the normal SDK getter; let the SDK renew when needed. Avoid forcing refresh, re-login or profile reload for every operation. A getter call alone does not prove a network request. |
| Backend token validation | Authenticate every protected request with the supported verifier. For locally verifiable signed tokens, check signature, allowed algorithm, trusted issuer/audience, subject and expiry/other required claims. Reuse the verifier's signing-key cache with its documented expiry/rotation behavior. Decoding claims alone grants nothing; opaque tokens or provider-required introspection still use the supported remote validation path. |
| App authorization and revocation | Check current native membership, account/deletion state and applicable session-revocation boundary at the enforcing operation. A valid signature does not establish current app permission or knowledge of upstream session revocation. Preserve existing revocation guarantees. |
| Paid capability eligibility | Apply the separate subscription freshness and reconciliation contract. Login persistence, signing keys and paid access have separate validity boundaries; fresh authentication does not require a new Stripe inventory. Explicit billing transitions retain authoritative verification. |
Keep token expiry, key-cache lifetime and revocation freshness distinct. Document how upstream revocation/disabled-user state reaches the guard and its maximum detection delay. Local app state covers only revocations it actually receives. If the provider or agreed policy requires an online revocation check, retain it; replacing it with bounded reuse requires an explicit security-policy decision and a working invalidation/refresh path. Never disable that check merely to meet a latency goal, or extend validity on an error.
Reuse verifier/key-cache instances where supported. Keep mutable user/session state scoped to its actor/client or server request. Use SDK coordination first; if extra single-flight coordination is needed, coalesce renewal by session and key discovery by trusted issuer/project context. Bound waits/retries, clear settled failures, and reuse completed results only within their validity. Key rotation or an unknown key can trigger the verifier's bounded refresh, never unlimited retries or acceptance with unverified keys. Logout/account switching must prevent a late renewal from restoring the old private context.
Official mechanism examples: SDK persistence, token reuse/renewal, verification and key caching, online revocation checks, and local-verification availability depends on provider/key configuration. Use current provider instructions rather than copying cache durations or token mechanics into a custom implementation.
Name signup policy, chosen auth service, current user key, session validation boundary and private-cache reset points. Operator owns approved OAuth app/redirect configuration and consent. Verify repeat login keeps one user, altered/invalid session cannot access a protected operation, and expiry leads to refresh or usable sign-in recovery. These are implementation checks, not claims that this spec ran them.
Official mechanisms: OIDC subject stability, Google OAuth web flow, managed session example. Use the chosen service's current documentation.