Build the permit-reviewer sign-in path for two configured identity issuers. A reviewer may open both sign-in choices in separate tabs. The app must associate each callback with exactly one initiating browser session and must create a local session only after verifying an identity assertion addressed to this application. Reviewer 47 can access organization 6, while reviewer 62 belongs to organization 9; shared email text cannot merge their accounts. The project includes session renewal, local sign-out, and an explicit ceremony for adding a second provider. Use a maintained identity library for signatures and protocol messages. The small checkpoint below illustrates only local account-key construction; it is not a token verifier.
Project: federated permit reviewer sign-in
Build contract
- Store one expiring attempt per state with browser-session identity, issuer, verifier, nonce, and redirect URI; consume it atomically before code exchange.
- Verify signature and required identity claims through a trusted provider configuration, then map issuer and subject to a local account without email auto-merge.
- Give browser clients revocable app sessions, coordinate token renewal, require current record permission, and make linking and unlinking explicit account actions.
Implementation checkpoint
function sameExternalIdentity(left, right) {
return left.issuer === right.issuer && left.subject === right.subject;
}
console.log(sameExternalIdentity({ issuer: "issuer-6", subject: "reviewer-47" }, { issuer: "issuer-9", subject: "reviewer-47" }));
// Output: falseCost and boundaries
Each login holds O(1) short-lived attempt state and performs a token-endpoint round trip. Active app sessions add bounded storage and a lookup on protected requests. A unique issuer-and-subject index keeps account mapping efficient; a per-token-family renewal lock prevents 47 simultaneous browser requests from spending the same rotating token. Measure provider calls per renewal, callback failures by category, local logout-to-denial time, and account-link conflicts. Keep raw codes, verifiers, tokens, and private profile claims out of routine logs. A passing local sign-in test says nothing about organization 6 case authorization unless a direct API test checks it.
Failure drill
Complete two tab callbacks in reverse order, replay one callback, and attempt a wrong-issuer exchange. Supply an expired or wrong-audience identity token through the verifier test fixture. Give two subjects the same email, then try to link one already owned by another account. Expire the access token while 47 protected requests arrive and confirm one coordinated refresh. Finally remove reviewer 47 from organization 6, sign out while remote logout is unavailable, and retry a case read from an old tab and a restored page. Each failure must produce a narrow, recoverable result without opening a private record.
Acceptance checks
- Only matching unconsumed attempts reach the configured token endpoint.
- Wrong signature, issuer, audience, time, or nonce never creates a local session.
- Email collision, occupied external identity, stale link, and last-method unlink have explicit outcomes.
- Local sign-out and membership removal deny private reads even when provider logout or refresh fails.
Common Mistakes
- Assuming OAuth code exchange alone proves the user identity.
- Using an email address as the unique account key.
- Claiming provider-wide logout when only the app session ended.
Related lessons
Federated Identity and Session Lifecycle; Authorization Code, PKCE, and Callback Binding; ID Token Verification and Stable Account Identity; Refresh Token Rotation and App Session Boundary; Federated Account Linking, Logout, and Revocation.
