Skip to content

feat(auth): revocation-aware token introspection — POST /api/v1/auth/introspect (TODO item 4) - #116

Open
lopugit wants to merge 38 commits into
developfrom
claude/auth-token-introspection-s6
Open

feat(auth): revocation-aware token introspection — POST /api/v1/auth/introspect (TODO item 4)#116
lopugit wants to merge 38 commits into
developfrom
claude/auth-token-introspection-s6

Conversation

@lopugit

@lopugit lopugit commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Implements TODO.md item 4: external platforms can already verify Thingtime JWTs offline via /api/v1/auth/jwks, but offline verification cannot see server-side revocation. This adds the live-status check.

What changed

  • POST /api/v1/auth/introspect (new route, RFC 7662 shape): accepts the token in the JSON body ({ "token": "…" }) or as an Authorization: Bearer header. Verifies the signature via the existing verifyJwt, then checks the Mongo session (getLiveSession): exists, not revoked, not expired, userId matches sub, and the user still exists / service-account auth still allowed.
  • introspectToken in api/utils/auth/getCurrentUser.ts — the logic lives in the utils layer beside resolveTokenUser (FUNDAMENTALS: data access through the utils layer). Deliberate difference from resolveSessionUser: it also reports purpose: 'app' sessions, because external "Login with Thingtime" platforms are the primary caller and introspection only reports status — it never grants the credential any capability.
  • No oracle: inactive tokens return a bare { active: false } with no reason. Active tokens return sub, jti, purpose, iat/exp (epoch seconds; exp: null = non-expiring), iss. Cache-Control: no-store on all responses.
  • Authorization model: possession of the token — you can only ask about tokens you already hold (consistent with the SSO default-open origins decision in PR Thingtime SSO: default-open origins — any URL (incl. preview deploys) can use Login with Thingtime #87). Per-IP rate limit via the shared limiter (auth.introspect: 120/min, admin-tunable like every other key).
  • Registered in the Nitro dispatcher, documented on /docs/api (auto-serves /api/v1/auth/introspect-docs), and covered in apiTests.ts (missing token → 400; unverifiable token → bare { active: false }).

Verified live (worktree dev stack, 127.0.0.1:13930)

  • Missing token → 400 with guidance; garbage token → { active: false } (body and Bearer variants).
  • Registered a throwaway user via the real POST /api/v1/auth/register (per FUNDAMENTALS seeding rule) → introspect returned active: true with correct sub/jti/purpose: "browser"/iat/exp/iss.
  • Revocation: POST /api/v1/auth/logout → the same token now introspects { active: false }.
  • /tests page: both new tests pass in the Auth group run. Two unrelated failures in that run are parallel-session environment artifacts (another session's cookie on the shared 127.0.0.1 cookie jar breaks the "anonymous" expectation, and the shared per-IP resend-verification window was already exhausted → 429).
  • /docs/api renders the new "Token introspection" entry.

🤖 Generated with Claude Code

@gitguardian

gitguardian Bot commented Jul 21, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
35008687 Triggered Generic High Entropy Secret c98e2ff remix/app/docs/apiDocs.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
thingtime Ready Ready Preview Aug 23, 2026 9:07am
thingtime (develop) Ready Ready Preview Aug 23, 2026 9:07am

Request Review

@lopugit

lopugit commented Jul 30, 2026

Copy link
Copy Markdown
Owner Author

Consolidation note: this is now the single TODO-4 PR. Chosen over #114/#117/#120 because its introspectToken deliberately reports purpose:'app' sessions — external Login-with-Thingtime platforms are introspection's primary caller, and the resolveTokenUser/resolveSessionUser paths the other PRs reuse default-deny purpose-scoped sessions (they would report active:false for exactly the tokens that matter). Also returns purpose + iss with the RFC 7662 bare {active:false} no-oracle shape. #114, #117, #120 closed as duplicates.

@github-actions

Copy link
Copy Markdown
Contributor

🤝 Merged main into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

Conflicted files:

  • remix/app/api/utils/rateLimit/config.ts

Please review the merge commit before relying on it.

@lopugit
lopugit changed the base branch from main to develop August 6, 2026 06:53
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

Conflicted files:

  • remix/app/api/utils/rateLimit/config.ts

Please review the merge commit before relying on it.

@github-actions github-actions Bot added the ai-rebase-in-progress AI stack rebase currently owns this PR branch label Aug 8, 2026
@github-actions github-actions Bot removed the ai-rebase-in-progress AI stack rebase currently owns this PR branch label Aug 8, 2026
@lopugit
lopugit force-pushed the claude/auth-token-introspection-s6 branch from f717307 to 16f7644 Compare August 8, 2026 01:34
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

🧬 Rebased claude/auth-token-introspection-s6 onto develop with the AI PR/stack rebase workflow.

  • Previous head: f7173077c38e80ce5387a38cc6c8c7197cac29e0
  • Rewritten head: 16f7644d6b2af9367f0e654144b60617ec4fb3d3
  • graphify: refreshed and committed (semantic mode: none)
  • Direct stacked children dispatched: 0

The branch was published once with an exact force-with-lease. Please review the rewritten commits before relying on them.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

🤖 Auto-resolve running — the conflict resolver started working on this PR at 14:30 UTC.

Expected to finish around 14:38 UTC (resolutions typically land in 3-8 minutes; the job times out at 30). On success a merge commit resolving the conflicts is pushed to this branch and a result comment follows — no manual action is needed meanwhile.

Live status

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

Conflicted files:

  • graphify-out/GRAPH_REPORT.md
  • graphify-out/graph.json
  • graphify-out/manifest.json
  • remix/app/api/utils/rateLimit/config.ts

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify on the merged code WITH LLM semantic extraction (graphify extract, claude-cli backend) and committed the result — content new to this merge is semantically indexed; unchanged content came from the tracked cache.

Please review the merge commit before relying on it.

@github-actions github-actions Bot added the ai-rebase-in-progress AI stack rebase currently owns this PR branch label Aug 9, 2026
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

🤖 Auto-rebase running — the stack rebase started working on this PR at 12:34 UTC.

Expected to finish around 12:49 UTC (most rebases still land in 5-15 minutes; the hosted-runner ceiling is 360). On success this branch is force-pushed onto its new base and a result comment follows — no manual action is needed meanwhile.

Live status

@github-actions github-actions Bot removed the ai-rebase-in-progress AI stack rebase currently owns this PR branch label Aug 9, 2026
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

🧬 Rebased claude/auth-token-introspection-s6 onto develop with the AI PR/stack rebase workflow.

  • Previous head: 246c948591900c7fe6bebbea0e7b005d06706548
  • Rewritten head: d7a7c6e84b26697d4c687da2b62183a46f7b0142
  • graphify: refreshed and committed (semantic mode: none)
  • Direct stacked children dispatched: 0

The branch was published once with an exact force-with-lease. Please review the rewritten commits before relying on them.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

No AI resolution was needed by merge time; the branch was updated with a plain merge commit.

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify update (AST/text-only — the semantic extraction attempt failed this run; see the workflow log) and committed the result. Run graphify locally with an LLM backend if fresh semantic data is needed.

Please review the merge commit before relying on it.

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

No AI resolution was needed by merge time; the branch was updated with a plain merge commit.

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify on the merged code WITH LLM semantic extraction (graphify extract, claude-cli backend) and committed the result — content new to this merge is semantically indexed; unchanged content came from the tracked cache.

Please review the merge commit before relying on it.

# Conflicts:
#	graphify-out/GRAPH_REPORT.md
#	graphify-out/cache/semantic/66a986879eae83885e86f6094b6b9c67714e4c2f256edd157db885d9b5fa3772.json
#	graphify-out/cache/semantic/9472c3b491d798863284f2ee76417b9e548102934fab1c26c939c174263aece7.json
#	graphify-out/cache/semantic/9d941bc0e7934417a20121e81239551aeb78e32a69110b1c863c1d39ae6315fd.json
#	graphify-out/cache/semantic/a7bb429ccfa80a835eaada037544d54c6b485760f4a81f9425bd0a2c55f9abf5.json
#	graphify-out/cache/semantic/bad9f54f0b45f717512b05260481bacd21cb0c3fa0c31eab8a26993349b4261b.json
#	graphify-out/cache/semantic/f1a8d1b8925dafdff51f3774815b93fa71d531dc21b2eb632f9ecc2d46c245e1.json
#	graphify-out/graph.json
#	graphify-out/manifest.json
`graphify extract` with LLM semantic extraction (graphify 0.9.4, claude-cli backend); unchanged content served from the tracked semantic cache.

Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/32448001629
@github-actions
github-actions Bot temporarily deployed to develop-pr-116 August 21, 2026 04:59 Destroyed
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

No AI resolution was needed by merge time; the branch was updated with a plain merge commit.

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify on the merged code WITH LLM semantic extraction (graphify extract, claude-cli backend) and committed the result — content new to this merge is semantically indexed; unchanged content came from the tracked cache.

Please review the merge commit before relying on it.

github-actions Bot added a commit that referenced this pull request Aug 21, 2026
… — POST /api/v1/auth/introspect (TODO item 4)
# Conflicts:
#	graphify-out/GRAPH_REPORT.md
#	graphify-out/graph.json
#	graphify-out/manifest.json
`graphify extract` with LLM semantic extraction (graphify 0.9.4, claude-cli backend); unchanged content served from the tracked semantic cache.

Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/32449178062
@github-actions
github-actions Bot temporarily deployed to develop-pr-116 August 21, 2026 05:22 Destroyed
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

No AI resolution was needed by merge time; the branch was updated with a plain merge commit.

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify on the merged code WITH LLM semantic extraction (graphify extract, claude-cli backend) and committed the result — content new to this merge is semantically indexed; unchanged content came from the tracked cache.

Please review the merge commit before relying on it.

# Conflicts:
#	graphify-out/GRAPH_REPORT.md
#	graphify-out/graph.json
#	graphify-out/manifest.json
`graphify extract` with LLM semantic extraction (graphify 0.9.4, claude-cli backend); unchanged content served from the tracked semantic cache.

Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/32452631143
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

No AI resolution was needed by merge time; the branch was updated with a plain merge commit.

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify update (AST/text-only — the semantic extraction attempt failed this run; see the workflow log) and committed the result. Run graphify locally with an LLM backend if fresh semantic data is needed.

Please review the merge commit before relying on it.

# Conflicts:
#	graphify-out/GRAPH_REPORT.md
#	graphify-out/cache/semantic/03d4bef600057c8f0d44c78d9048b84998a642fe21cc953224d6cdde139c62b8.json
#	graphify-out/cache/semantic/0658eddb308e398d6cef9abc1f7274e397f032dd5abbf8c87ddff06b0586fa83.json
#	graphify-out/cache/semantic/384333055645511b027a58e7515a6c9852c1a50fcd245e590590ce28e20e8ee7.json
#	graphify-out/cache/semantic/d4a698266a3959f926c076a5dba885ee86ccb7906d6d9d29f3a490562135fe20.json
#	graphify-out/graph.json
#	graphify-out/manifest.json
AST/text-only `graphify update` (graphify 0.9.4, no semantic extraction); run graphify locally with an LLM backend if semantic data is needed.

Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/32457149963
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

No AI resolution was needed by merge time; the branch was updated with a plain merge commit.

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify on the merged code WITH LLM semantic extraction (graphify extract, claude-cli backend) and committed the result — content new to this merge is semantically indexed; unchanged content came from the tracked cache.

Please review the merge commit before relying on it.

# Conflicts:
#	graphify-out/GRAPH_REPORT.md
#	graphify-out/graph.json
#	graphify-out/manifest.json
`graphify extract` with LLM semantic extraction (graphify 0.9.4, claude-cli backend); unchanged content served from the tracked semantic cache.

Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/32461677790
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

No AI resolution was needed by merge time; the branch was updated with a plain merge commit.

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify on the merged code WITH LLM semantic extraction (graphify extract, claude-cli backend) and committed the result — content new to this merge is semantically indexed; unchanged content came from the tracked cache.

Please review the merge commit before relying on it.

# Conflicts:
#	graphify-out/GRAPH_REPORT.md
#	graphify-out/graph.json
#	graphify-out/manifest.json
`graphify extract` with LLM semantic extraction (graphify 0.9.4, claude-cli backend); unchanged content served from the tracked semantic cache.

Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/32466414690
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

No AI resolution was needed by merge time; the branch was updated with a plain merge commit.

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify on the merged code WITH LLM semantic extraction (graphify extract, claude-cli backend) and committed the result — content new to this merge is semantically indexed; unchanged content came from the tracked cache.

Please review the merge commit before relying on it.

# Conflicts:
#	graphify-out/GRAPH_REPORT.md
#	graphify-out/graph.json
#	graphify-out/manifest.json
`graphify extract` with LLM semantic extraction (graphify 0.9.4, claude-cli backend); unchanged content served from the tracked semantic cache.

Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/32469692868
@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

🤝 Merged develop into claude/auth-token-introspection-s6 — conflicts auto-resolved by the resolve-pr-conflicts workflow.

Conflicted files:

  • graphify-out/GRAPH_REPORT.md
  • graphify-out/graph.json
  • graphify-out/manifest.json
  • remix/server/routes/api/[...].ts

graphify-out/ was reset wholesale to the develop side (repo rule: one side, never mixed — the graph merge driver is unavailable in CI).
Then re-ran graphify on the merged code WITH LLM semantic extraction (graphify extract, claude-cli backend) and committed the result — content new to this merge is semantically indexed; unchanged content came from the tracked cache.

Please review the merge commit before relying on it.

github-actions Bot and others added 2 commits August 23, 2026 08:44
…nflicts)

Conflicted paths: graphify-out/GRAPH_REPORT.md, graphify-out/graph.json, graphify-out/manifest.json, remix/server/routes/api/[...].ts

Resolved by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/32628861456

Co-Authored-By: Claude <noreply@anthropic.com>
`graphify extract` with LLM semantic extraction (graphify 0.9.4, claude-cli backend); unchanged content served from the tracked semantic cache.

Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/32628861456
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-merge-paused AI merge-conflict resolution failed; manual retry required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant