Session Identity Verification Automation: Reading a Token Is Not the Same as Verifying It

A token's contents and a token's authenticity are two separate facts
A JSON Web Token is built from three parts joined by dots, and the middle part — the payload, carrying claims like a user's own identifier — is simply base64-encoded, not encrypted and not scrambled in any way that resists reading. Decoding that middle part and reading its contents is a completely ordinary, harmless operation that reveals exactly what the token CLAIMS. It reveals nothing at all about whether those claims are true, because the only mechanism that actually ties a token to a real, authenticated event is its separate, third part: a cryptographic signature, produced by the issuing authority's own private key, verifiable only by checking it against that authority's known public key or by asking the authority directly. Code that reads a token's claims without ever checking its signature is reading a claim, not confirming a fact — the two operations look almost identical in code, and only one of them is actually security.
How the underlying problem shows up before you fix it
A function responsible for identifying an authenticated user reads a session token's own payload directly (typically by base64-decoding its middle segment) and extracts a claimed identifier from it.
The same function never calls the actual issuing authority (here, Supabase's own authentication service) to confirm the token's cryptographic signature, its expiration, or that it was genuinely issued by that authority in the first place.
Automated tests covering this function, if any exist, tend to construct a token by hand and confirm the DECODING logic works correctly — without independently testing whether an unsigned, forged, or expired value with the identical shape is also, incorrectly, accepted.
Every other part of the application that depends on "who is the current user" inherits this same gap by construction, because they all ultimately call the same single function to answer that question — a fix at this one point closes the gap everywhere at once, and a defect at this one point opens it everywhere at once.
The defect produces no error, no warning, and no unusual log entry under normal operation — a genuinely authenticated user's own real token decodes and behaves identically to a forged one, so nothing about ordinary usage ever surfaces the gap.
Why reading a token and verifying a token are easy to confuse in code
Both operations start from the identical raw material — a session cookie holding a token-shaped string — and both produce the identical-looking output: a user identifier a function can act on. The difference lives entirely in ONE additional step that a decode-only implementation can skip without producing any visible error: actually checking the token's cryptographic signature, which requires either verifying it locally against the correct public key or asking the issuing authority directly. Skipping that step does not break anything for a genuine, legitimately-issued token — decoding its payload directly happens to produce the same correct-looking user identifier a proper verification would have. The gap becomes exploitable only for a token that was never legitimately issued at all, which a decode-only check has no way to distinguish from a real one.
How Centriu Loop replaced a decode with a real, server-verified check
Centriu Loop's own function for resolving the current user from a session cookie previously extracted the underlying access token from the cookie's own value, then base64-decoded the token's payload segment directly and read a `sub` (subject) claim from the decoded JSON as the authenticated user's identifier — returning that value straight to every caller across the application as the confirmed, current user. Decoding a token's payload is a purely mechanical operation on data the token itself carries; it does not, on its own, confirm that the token was genuinely issued by Supabase's own authentication service, that it has not been tampered with, or that it has not already expired. Nothing in the prior code performed that confirmation at all — any string shaped like three base64 segments joined by dots, wrapped in the format the cookie parser expected, and carrying a `sub` claim of the caller's choosing, would have been decoded and trusted identically to a real, properly-issued session.
The fix introduces a dedicated verification function that sends the extracted token to Supabase's own authentication endpoint (`auth.getUser`), which independently validates the token's cryptographic signature, confirms it has not expired, and confirms it was issued for the correct audience — returning a genuinely verified user id only when all of that holds, and returning nothing at all otherwise. Because that verification is a real network call to an external service, and because Centriu Loop needs to resolve the current user on effectively every request, the fix adds a short-lived cache: a verified result is kept for up to sixty seconds, explicitly capped so it can never outlive the token's own real, cryptographically-declared expiration time, and the cache itself is bounded in total size with older entries pruned once a ceiling is reached — keeping the correctness gain from real verification while keeping its performance cost genuinely small. Every function elsewhere in Centriu Loop that previously called the decode-only version was switched to the new, verified version, so the fix closes the gap for every caller across the module at the single point where user identity is actually resolved, rather than needing to be applied separately at each call site.
What is actually built today
Centriu Loop's server-side user-identity resolution calls Supabase's own authentication service directly for every session, cryptographically verifying the token's signature, expiration, and audience before trusting any identity it carries.
A verified result is cached for up to sixty seconds, and never longer than the token's own real, declared expiration — keeping the performance cost of genuine verification low without ever trusting a result past the point it could legitimately still be valid.
The verification cache is bounded in total size, with older entries pruned once a fixed ceiling is reached, preventing unbounded memory growth under sustained real traffic.
A locally decoded token payload is used only to read the claimed expiration timestamp as a fast, local first check — never as the basis for trusting an identity — with the actual identity confirmed exclusively by the real, server-side verification call.
Every function across Centriu Loop that resolves "who is the current user" now routes through this single, verified path, rather than each call site needing its own independent verification logic.
A name badge nobody actually checks against the guest list (illustrative framing of the actual measured finding)
Before the fix, presenting a name badge at the door was enough to be let in — the door staff read the name printed on it and waved the bearer through, with no one ever checking that name against the actual guest list. Anyone could print their own badge with any name on it. After the fix, the exact same badge is checked against the real guest list before anyone is admitted — the badge alone no longer grants entry; only a badge the list itself confirms does.
What changes operationally
Centriu Loop's server-side session check now cryptographically verifies every session token against Supabase's own authentication service before trusting any identity it claims — closing a gap where a token's own, unverified payload had previously been read and trusted directly, with no signature check anywhere in that path.
When this is not the right fit
This automation covers specifically how Centriu Loop's own internal dashboard resolves and verifies a signed-in user's session. It is a distinct mechanism from this pillar's separate pages on Loop's public, unauthenticated consumer credential portal — that portal uses its own dedicated, revocable 192-bit credential system entirely, not a Supabase session token of the kind this page addresses.
Decoding a token locally vs. verifying it against the issuing authority
Decoding a token's payload locally is fast, requires no network call, and is the simplest possible way to read what a token claims — which is exactly why it is tempting to treat that claim as sufficient on its own. It provides zero actual security guarantee, because reading a claim and confirming a claim's authenticity are different operations entirely. Verifying a token against its actual issuing authority is the only version of the two that confirms genuineness — at the cost of a real network call, which a short, tightly-bounded cache can absorb without meaningfully reducing the strength of the guarantee.
Related systems
Main system: Centriu Loop.
What it does NOT do
- Does not change how a session cookie is issued, stored, or its overall lifetime — this fix corrects only how the SERVER verifies a token it already receives, not how or when a token is originally created.
- Does not affect Centriu Loop's separate, public consumer credential portal, which uses its own dedicated, revocable, hash-stored 192-bit credential system entirely independent of this internal-dashboard session mechanism.
- Does not eliminate the performance benefit of not calling an external service on every single request — the sixty-second cache preserves nearly all of that benefit while closing the actual security gap.
- Does not claim every possible forged-token scenario was tested against a real, confirmed exploitation attempt in production — the finding is a genuine, structural gap in the verification logic, confirmed directly from the code's own prior implementation.
- Does not extend this same verification pattern automatically to every other Centriu module — this fix is specific to Centriu Loop's own session-resolution function, confirmed to have carried this exact gap.
Security and governance
Centriu Loop's server-side session-identity check now cryptographically verifies every token against Supabase's own authentication service before trusting the identity it claims, closing a gap where a token's own unverified payload had previously been decoded and trusted directly. Any personal data referenced in session or account records remains subject to Brazil's LGPD (Law No. 13,709/2018). Full detail on access control lives at /governanca and /iso.
Pricing and contracting
Available by monthly subscription, with tiered plans. Values and terms come from the official pricing table at /precos (Centriu's central source — never restated here).
Frequently asked questions
Was this ever actually exploited?
The finding is a genuine, structural gap confirmed directly from the prior code's own implementation — no verification step existed anywhere in the identity-resolution path. Whether it was ever specifically exploited in practice is a separate question this fix does not itself claim to answer; the fix closes the underlying mechanism regardless.
Isn't decoding a JWT's payload a completely normal thing to do?
Yes, decoding a payload to read its claims (like an expiration timestamp) is fine and is still done today, as a fast local check. The defect was trusting the CLAIMED IDENTITY from that decode as sufficient on its own, without ever separately verifying the token's cryptographic signature.
Why add a cache if the whole point is to verify every request?
Because a genuine verification call to Supabase's own auth service has a real network cost, and Centriu Loop resolves the current user on nearly every request. The cache is capped at sixty seconds and can never outlive the token's own real, declared expiration — preserving the actual security guarantee while keeping the added cost small.
Does this affect Centriu Loop's separate consumer credential portal?
No — that portal uses an entirely different, dedicated credential system (a 192-bit secret, hashed in the database, delivered via URL fragment), covered on this pillar's own separate pages, unrelated to this internal-dashboard session mechanism.
How was this specific gap actually found?
Confirmed directly by reading the prior code's own implementation as part of a broader security hardening pass — the decode-only logic and the complete absence of any signature-verification step are both visible directly in the code itself.
What does Centriu Loop cost?
It is sold by subscription with a published starting price — exact current values are on the central pricing page.
See how Centriu Loop verifies every session, not just decodes it
Reach our commercial team directly, or leave your details below — we'll follow up with guidance for your case.
