---
title: "sdk/ruby"
description: "Ruby server SDK for networkless JWT verification, Rack/Rails request authentication, and webhook signature validation."
locale: "en"
---

> Documentation Index
> Fetch the relevant documentation index at: https://xid.fngx.org/sdks/llms.txt
> Use this file to discover all available pages before exploring further.

# sdk/ruby

## Status

Implemented and verified locally. Real IdP round-trip verification (JWKS fetch, token sign/verify against a live XID instance) has not been performed yet and must be completed before production use.

XID publishes no packages to any registry. This SDK is distributed as source in the XID repository; use it from a checkout of the repository.

Request authentication is Bearer-only by default. An application-owned JWT cookie is read only when its exact name is configured. The opaque \_\_Host-xid.rt.\* Core cookie is never scanned or verified locally; exchange it by forwarding the complete Cookie header to exact same-origin POST /v1/sessions/token with redirects disabled, and accept only a response containing the token field.

## Install

```ruby
# Gemfile
gem "xid", path: "../xid/sdk/ruby"

bundle install
```

## Quick start

```ruby
require "xid"

Xid.configure do |c|
  c.issuer         = "https://xid.dev"
  c.audience       = "your_client_id"
  c.webhook_secret = "whsec_AbCdEf..."
end

# Verify a token
begin
  claims = Xid.verify_token(raw_token)
  puts claims.sub    # => "usr_abc123"
  puts claims.scope  # => "openid profile email"
rescue Xid::TokenVerificationError => e
  puts "Token invalid: #{e.message}"
end
```

## Authenticate a Rack/Rails request

```ruby
# Sinatra before-filter
before do
  auth = Xid.authenticate_request(request)
  halt 401, "Unauthorized" unless auth.signed_in?
  @current_user_id = auth.claims.sub
end

# Explicit same-origin Core session -> JWT exchange
token = Xid.exchange_session_token(
  incoming_request_url: request.url,
  cookie_header: request.get_header("HTTP_COOKIE")
)
```

## Verify webhook

```ruby
# Rails controller action
def receive
  raw_body = request.raw_post
  payload = Xid.verify_webhook(request.headers.to_h, raw_body)
  handle_event(payload["type"], payload["data"])
  head :ok
rescue Xid::WebhookVerificationError
  head :bad_request
end
```

## Multi-issuer setup

```ruby
config_a = Xid::Configuration.new
config_a.issuer   = "https://tenant-a.xid.dev"
config_a.audience = "client_a"
client_a = Xid::Client.new(config_a)
claims = client_a.verify_token(token)
```

## Configuration options

| Key | Default | Description |
| --- | --- | --- |
| `issuer` | `https://xid.dev` | OIDC issuer URL |
| `audience` | `nil` | Expected aud claim; nil skips validation |
| `jwks_ttl` | `3600` | JWKS local cache TTL in seconds |
| `leeway` | `60` | JWT clock skew tolerance in seconds |
| `webhook_secret` | `nil` | Webhook signing secret with `whsec_` prefix |
| `webhook_tolerance` | `300` | Webhook replay window in seconds |
| `cookie_name` | `disabled` | Application-owned JWT cookie name; disabled unless explicitly configured |

## Platform notes

- Depends on the `jwt` gem (ES256/RS256 support). Ruby 3.1+ required.
- `Xid.authenticate_request` accepts both a Rack env hash and a Rack `Request` object.
- Exception hierarchy: `Xid::Error` -&gt; `ConfigurationError`, `JwksError`, `TokenVerificationError`, `WebhookVerificationError`.

Source: https://xid.fngx.org/sdks/ruby/index.mdx
