By NHI Mgmt Group Editorial TeamPublished 2026-04-27Domain: Best PracticesSource: WorkOS

TL;DR: Ruby JWT handling is straightforward with the jwt gem, but production security depends on strict verification: enforce the expected algorithm, validate iss, aud, and exp claims, and use JWKS for key rotation, according to WorkOS. The real risk is treating decoded tokens as trusted identity statements before signature and claim validation complete.


At a glance

What this is: This guide explains how to create, sign, and verify JWTs securely in Ruby, with emphasis on RS256, JWKS, claim validation, and rotation-aware verification.

Why it matters: It matters because JWTs often become NHI credentials or federated trust artifacts, so weak verification can undermine API authorisation, service-to-service trust, and human identity sessions alike.

👉 Read WorkOS's guide to secure JWT handling in Ruby


Context

JWTs are signed identity assertions, not encrypted containers. In Ruby applications, the security boundary sits in verification, not in decoding, because a token that parses cleanly can still be forged, tampered with, or mis-scoped if the signature, issuer, audience, and expiry checks are loose.

For IAM teams, the practical issue is that JWT handling now sits across human login flows, service identities, and token-based API access. That means a weak verifier is not just an application bug, it is an identity governance failure that can widen access far beyond the intended session or workload boundary.


Key questions

Q: How should security teams verify JWTs in Ruby applications?

A: Security teams should verify JWTs before trusting any claim, and they should enforce the expected signing algorithm, issuer, audience, and expiration checks on every request. A decoded token is only readable data, not proof of identity. Centralising verification in shared middleware reduces the chance that one endpoint accepts a weaker trust path than the rest.

Q: Why do JWKS-based JWT verifiers matter for IAM and NHI governance?

A: JWKS matters because public keys change over time, and verifiers need a reliable way to select the current key without manual redeployment. In identity governance terms, this preserves continuity of trust during rotation and prevents stale keys from remaining implicit trust anchors. It is especially important when one issuer supports many APIs or workloads.

Q: What breaks when JWT claims are checked before signature validation?

A: If claims are checked before signature validation, an attacker can supply a token that looks correct but was never issued by a trusted source. That can produce false positives for roles, audience, or expiry and turn a forged object into accepted identity evidence. The failure is policy without proof, which is not a safe authorisation model.

Q: What is the difference between JWT decoding and JWT verification?

A: Decoding only reads the token contents, while verification checks that the signature is valid and that the token matches the expected issuer, audience, and expiry rules. Decoding is useful for debugging. Verification is the step that makes the token trustworthy enough to use in authentication or authorisation decisions.


Technical breakdown

JWT structure and claim validation in Ruby

A JWT has three Base64URL-encoded parts: header, payload, and signature. The header declares the algorithm and sometimes the key identifier. The payload carries claims such as iss, sub, aud, exp, and custom application data. In Ruby, the jwt gem will happily decode a token without verifying it, but that only reveals what the token says, not whether it is trustworthy. The important point is that claims are policy inputs, not proof. A verifier must treat them as untrusted until the signature is validated and the expected claims match the application context.

Practical implication: never use decoded claims for access decisions until signature verification and claim validation both succeed.

RS256 and JWKS key rotation patterns

RS256 uses an asymmetric key pair, which lets an issuer sign with a private key and consumers verify with a public key. In distributed systems, JWKS is the practical distribution mechanism because it publishes active public keys and lets verifiers select the right key by kid. The jwt gem supports JWKS loading and refresh on unknown kid, which matters when keys rotate and old tokens remain valid until expiry. The governance issue is continuity of trust across key changes, not just crypto correctness. A verifier that cannot follow rotation will either break legitimate sessions or accept stale trust material too long.

Practical implication: standardise on JWKS-backed verification and keep retired public keys available until all signed tokens expire.

Algorithm confusion and bearer token handling

Algorithm confusion happens when a verifier accepts whatever algorithm the token header claims instead of enforcing the expected one. That opens the door to attacks where a token signed under one algorithm is misinterpreted under another. Ruby applications also need to treat JWTs as bearer credentials, which means transport and storage choices matter. Query strings, logs, and browser history can leak them. The safest pattern is strict algorithm allow-listing, HTTPS-only transport, and centralised verification logic so every route applies the same checks consistently.

Practical implication: lock verification to one algorithm, require Authorization bearer headers, and centralise token handling in middleware or a shared concern.


Read our 52 NHI Breaches Analysis report for a comprehensive view of breaches impacting Non-Human Identities including AI Agents.


NHI Mgmt Group analysis

JWT verification is an identity governance control, not a parsing exercise. In practice, many teams treat decode success as a signal of authenticity, but decoding only exposes token contents. The real control boundary is the combination of signature verification, claim enforcement, and key provenance. For IAM programmes, that means JWT handling belongs in the same control conversation as trust policy, not just application plumbing. Practitioners should treat unsigned trust as broken governance, not a convenience shortcut.

JWKS turns key rotation into a governance dependency. Once multiple services verify the same issuer, public key distribution becomes part of the access model. If consumers cannot track kid changes reliably, tokens fail unpredictably or retired keys linger beyond their intended life. That is why JWKS is more than an implementation detail. It is the mechanism that keeps issuer trust continuous across distributed workloads. Practitioners should manage key publication and retirement as an identity lifecycle process.

Bearer tokens create a blast radius problem when transport is loose. JWTs are portable credentials, which means any leak becomes reusable access until expiry. Query parameters, logs, and long-lived sessions all expand the window for abuse. This is a classic NHI pattern even when the token is used in human-facing flows, because the credential is machine-readable and replayable. The governance lesson is simple. If token carriage is weak, the access model is weak.

Claim validation is where policy becomes enforceable. The iss, aud, exp, and nbf claims are the bridge between cryptographic validity and business legitimacy. Without them, a token may be mathematically correct and still operationally wrong for the target API or tenant. That distinction matters across human identity, service tokens, and federated workload access. Practitioners should treat claim rules as the minimum policy layer that converts a signed object into an authorised one.

Named concept: verification trust boundary. The verification trust boundary is the point at which a token stops being an untrusted blob and becomes acceptable identity evidence. In Ruby JWT implementations, that boundary is crossed only after algorithm enforcement, signature validation, issuer and audience checks, and key lookup all succeed. The implication is that teams must define this boundary once and reuse it everywhere, or risk inconsistent trust decisions across endpoints.

From our research:

  • Organizations maintain an average of 6 distinct secrets manager instances, creating fragmentation that undermines centralised control, according to The State of Secrets in AppSec.
  • 43% of security professionals are concerned about AI systems learning and reproducing sensitive information patterns from codebases.
  • For related controls, see NIST SP 800-207 Zero Trust Architecture for the policy and trust model that should frame token verification decisions.

What this signals

Verification trust boundary: token parsing, signature checking, and claim enforcement need to be treated as one control surface, not three separate developer tasks. When teams split those responsibilities, inconsistent trust decisions emerge across APIs and service layers. That becomes especially risky in environments where a single token can represent both human session access and machine-to-machine access.

JWT-heavy estates tend to drift into fragmented key and secret handling, which is exactly where governance weakens. Our research shows organisations maintain an average of 6 distinct secrets manager instances, a pattern that makes centralised key control harder to sustain and complicates rotation discipline. The practical response is to simplify the trust path before token sprawl becomes an authorisation problem.

For teams aligning token handling with policy, NIST SP 800-207 Zero Trust Architecture is the right external frame: verify every request, assume tokens can be replayed, and minimise standing trust in the transport layer. That posture matters whether the token secures a human session, an API client, or a workload identity.


For practitioners

  • Enforce signature verification on every protected endpoint Require JWT.decode to verify signatures before any claim is used for authorisation, and map failures to consistent 401 responses. Do not allow code paths that only decode tokens for convenience or debugging.
  • Pin verification to the expected algorithm Allow only the algorithm your issuer actually uses, such as RS256, and reject header-driven algorithm switching. This prevents algorithm confusion from becoming an authentication bypass.
  • Move verification behind a shared middleware layer Centralise JWT parsing, signature checks, issuer and audience validation, and error handling in one Rack middleware or Rails concern so every route inherits the same trust boundary.
  • Adopt JWKS for rotation-aware key selection Fetch public keys from a JWKS endpoint, select by kid, and keep retired keys published until all tokens signed with them have expired. That keeps verification stable during key rotation.

Key takeaways

  • JWT security in Ruby depends on verification discipline, not on whether the token can be decoded.
  • JWKS and strict algorithm enforcement are the controls that keep distributed token trust stable during rotation.
  • Teams should centralise JWT validation so every endpoint applies the same issuer, audience, expiry, and signature rules.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

OWASP Non-Human Identity Top 10 address the attack and risk surface, while NIST Zero Trust (SP 800-207) and NIST CSF 2.0 set the governance and control requirements practitioners need to meet.

FrameworkControl / ReferenceRelevance
OWASP Non-Human Identity Top 10NHI-01JWT handling involves token trust and verification failures.
NIST Zero Trust (SP 800-207)PR.AC-4Token verification is part of continuous access validation.
NIST CSF 2.0PR.AC-1Access permissions must be validated through consistent identity controls.

Standardise token acceptance rules and keep them uniform across all protected services.


Key terms

  • JSON Web Token: A JSON Web Token is a compact signed object used to carry identity and claim data between systems. In practice, it is trustworthy only after the signature, issuer, audience, and expiry checks succeed, because the payload is readable before it is verified.
  • JWKS: A JSON Web Key Set is a published set of public keys used to verify signed tokens. It supports rotation by letting verifiers select the correct key through a key identifier such as kid, which is why it is central to distributed token governance.
  • Algorithm Confusion: Algorithm confusion is a verification failure where a system accepts a token under the wrong signing algorithm or trusts the token header too much. The result is that a token can be validated in a way the issuer never intended, undermining authentication integrity.
  • Bearer Credential: A bearer credential is a secret that grants access to whoever possesses it. JWTs used as bearer tokens must be protected in transit and storage because theft or logging can turn a legitimate session artifact into reusable access.

Deepen your knowledge

JWT verification, key rotation, and claim enforcement are core topics in our NHI Foundation Level course, the industry's only accredited NHI security programme. If you are building token governance into an API or identity stack, it is worth exploring.

This post draws on content published by WorkOS: How to handle JWT in Ruby. Read the original.

NHIMG Editorial Note
Published by the NHIMG editorial team on 2026-04-27.
NHI Mgmt Group — the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org