feat(auth): revocation-aware token introspection — POST /api/v1/auth/introspect (TODO item 4) - #116
feat(auth): revocation-aware token introspection — POST /api/v1/auth/introspect (TODO item 4)#116lopugit wants to merge 38 commits into
Conversation
|
| 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
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- 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
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 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.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
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. |
|
🤝 Merged Conflicted files:
Please review the merge commit before relying on it. |
|
🤝 Merged Conflicted files:
Please review the merge commit before relying on it. |
f717307 to
16f7644
Compare
|
🧬 Rebased
The branch was published once with an exact force-with-lease. Please review the rewritten commits before relying on them. |
|
🤖 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. |
|
🤝 Merged Conflicted files:
Please review the merge commit before relying on it. |
|
🤖 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. |
|
🧬 Rebased
The branch was published once with an exact force-with-lease. Please review the rewritten commits before relying on them. |
246c948 to
d7a7c6e
Compare
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
Please review the merge commit before relying on it. |
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
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
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
Please review the merge commit before relying on it. |
… — 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
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
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
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
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
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
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
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
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
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
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
|
🤝 Merged Conflicted files:
Please review the merge commit before relying on it. |
…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
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 anAuthorization: Bearerheader. Verifies the signature via the existingverifyJwt, then checks the Mongo session (getLiveSession): exists, not revoked, not expired, userId matchessub, and the user still exists / service-account auth still allowed.introspectTokeninapi/utils/auth/getCurrentUser.ts— the logic lives in the utils layer besideresolveTokenUser(FUNDAMENTALS: data access through the utils layer). Deliberate difference fromresolveSessionUser: it also reportspurpose: 'app'sessions, because external "Login with Thingtime" platforms are the primary caller and introspection only reports status — it never grants the credential any capability.{ active: false }with no reason. Active tokens returnsub,jti,purpose,iat/exp(epoch seconds;exp: null= non-expiring),iss.Cache-Control: no-storeon all responses.auth.introspect: 120/min, admin-tunable like every other key)./docs/api(auto-serves/api/v1/auth/introspect-docs), and covered inapiTests.ts(missing token → 400; unverifiable token → bare{ active: false }).Verified live (worktree dev stack, 127.0.0.1:13930)
{ active: false }(body and Bearer variants).POST /api/v1/auth/register(per FUNDAMENTALS seeding rule) → introspect returnedactive: truewith correctsub/jti/purpose: "browser"/iat/exp/iss.POST /api/v1/auth/logout→ the same token now introspects{ active: false }./testspage: 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/apirenders the new "Token introspection" entry.🤖 Generated with Claude Code