InternalAuthor2025

PeakCore Auth

An OAuth 2.0 identity provider written from scratch.

PeakCore Auth is an OAuth 2.0 identity provider written from scratch in Python and FastAPI, with mandatory PKCE, rotating refresh tokens and family-based reuse detection, serving as the single authentication authority for every application in the PeakCore ecosystem.

What it is

Centralized OAuth 2.0 Identity Provider built from scratch. Mandatory PKCE, RS256 JWT with key rotation, rotating refresh tokens with family-based reuse detection, Google SSO passthrough, Admin API.

Checkable facts

  • Mandatory PKCE on every authorization flow
  • RS256 JWT with scheduled key rotation
  • Refresh-token families with reuse detection

Why write an identity provider instead of using one

A hosted identity provider is the right default for almost everyone. It stops being right when you run several applications that must share one account system, need the token behaviour to be yours to reason about, and cannot accept a per-user cost that scales with a portfolio rather than with revenue.

The honest version of this decision is that most teams should not make it. Auth0, Clerk and their peers exist because authentication is a place where a subtle mistake is expensive and a library that has been attacked by thousands of people is safer than one that has been attacked by nobody.

The case for building it here was specific: one account identity across every PeakCore application, full control of the token lifecycle so its behaviour is auditable rather than documented by a vendor, and a cost structure that does not grow with the number of small applications sharing it. Those three together move the balance, and none of them applies to a single product.

The decision that took the most work: reuse detection by token family

Refresh tokens rotate on every use, and each new token is linked to the one it replaced, forming a family. If a token that has already been rotated is presented again, the entire family is revoked at once. That converts a stolen refresh token from a silent, permanent foothold into a single failed request.

A refresh token is a long-lived credential: it exists so a user does not log in every hour. That lifespan is also its danger, because a stolen one works until it expires. The naive design issues a new access token whenever a valid refresh token appears and never asks whether that refresh token should still exist.

Family-based reuse detection asks exactly that. Because each rotation records which token it descended from, a replayed old token is provable evidence that two parties hold the same credential, which only happens after a theft. The response is to revoke the whole chain, log the user out everywhere, and force a fresh authentication. The alternative that was rejected was stateless refresh with no server-side record, which is simpler and cannot detect this at all.

What was hardest to get right: rotating signing keys with zero downtime

Access tokens are signed, and the signing key has to be replaceable without invalidating every token already in circulation. Each token carries a key identifier, so the server can retire a key for new signatures while still verifying tokens signed by the previous one until they expire.

The trap here is that key rotation and token validity are on different clocks. Rotate a key naively and every access token signed with the old one fails on its next request, which logs out every active user at once. That is the failure that turns a security best practice into an outage.

The key identifier on each token is what resolves it: verification looks up the key that actually signed the token rather than assuming the current one, so an old key stays valid for verification long enough for its tokens to expire naturally while no new tokens use it. Getting the overlap window right, long enough to be invisible, short enough to be meaningful, was the part that took iteration.

How secrets are stored

Nothing sensitive is stored in a form that a database leak would expose directly. Tokens are hashed with SHA-256 before storage, client secrets with bcrypt, and session cookies are HttpOnly, Secure and SameSite=Lax. A dump of the tables yields verifiers, not credentials.

The distinction is deliberate: SHA-256 for tokens, which are high-entropy and compared by exact match, and bcrypt for client secrets, which need a deliberately slow hash to resist offline brute force. Using one for the other is a common and quiet mistake.

Access tokens are RS256 or HS256 JWTs, state parameters are HMAC-SHA256 signed with a TTL so the login flow itself cannot be tampered with mid-redirect, and PKCE with S256 is mandatory for every public client, which closes the authorization-code interception attack that PKCE exists to prevent.

Questions

When does it make sense to build your own identity provider?
Rarely, and only when three things hold at once: several applications must share one account system, you need the token lifecycle to be yours to reason about rather than a vendor's to document, and a per-user hosted cost would scale with a portfolio instead of with revenue. For a single product, use a hosted provider.
What is refresh token reuse detection?
Refresh tokens rotate on every use and each one is linked to the token it replaced, forming a family. Presenting a token that has already been rotated is proof that two parties hold the same credential, so the entire family is revoked at once. It turns a stolen refresh token from a permanent foothold into one failed request.
How is signing-key rotation done without logging everyone out?
Each access token carries the identifier of the key that signed it. A retired key stays valid for verification until its tokens expire, while new tokens use the current key. Verification resolves the actual signing key per token rather than assuming the latest one, so rotation is invisible to active users.
How are tokens and secrets stored?
Tokens are hashed with SHA-256, client secrets with bcrypt, and session cookies are HttpOnly, Secure and SameSite=Lax. The two hashes are chosen for their jobs: exact-match verifiers for high-entropy tokens, a deliberately slow hash for secrets that must resist offline brute force. A database dump yields verifiers, not usable credentials.

Facts on this page verified 2026-08-08