Keycloak SDK for Ruby
Authentication (OIDC / OAuth2) and the Admin REST API for Keycloak behind one consistent facade, with hardened JWT validation.
English · 한국어
Part of a nine-language polyglot SDK (Java · Python · Node · Go · C# · PHP · Rust · Ruby · Kotlin) — one API surface, isomorphic across all of them: github.com/xzawed/KeyCloakSDK.
Pre-release — the first release candidate (
0.1.0.rc1) is on RubyGems; there is no stable release yet. ⚠️ RubyGems does not install a pre-release by default: a baregem install keycloak-sdkfinds nothing until a stable version exists. Ask for it explicitly —gem install keycloak-sdk --pre, or pin the exact version as shown below.
Requirements
- Ruby 3.2+
- Sync-only (every wrapped gem is synchronous); exception-based error handling under
KeycloakSdk::Error
Install
gem install keycloak-sdk -v 0.1.0.rc1
Or in a Gemfile:
gem "keycloak-sdk", "0.1.0.rc1"
While 0.1.0.rc1 is the only release, the version must be explicit — gem install keycloak-sdk and a bare gem "keycloak-sdk" both skip pre-releases and resolve nothing. Drop the pin once a stable release exists.
Name mismatch, on purpose: the gem is
keycloak-sdk(hyphen) but the require path and module arekeycloak_sdk/KeycloakSdk(underscore) — this avoids colliding with the existingkeycloakgem'sKeycloakmodule.
Quickstart
require "keycloak_sdk"
config = KeycloakSdk::Config.new(
server_url: "https://kc.example.com",
realm: "myrealm",
client_id: "admin-cli",
client_secret: "changeme" # load the real value from an env var / secrets manager
)
client = KeycloakSdk::KeycloakClient.new(config)
# 1) Issue a token via the client-credentials grant. TokenSet#inspect masks every token value.
token = client.auth.client_credentials_token
# 2) Validate it — algorithm pinning, exact iss, aud containment, mandatory exp, nbf, clock skew.
validated = client.auth.validate(token.access_token)
puts "subject=#{validated.subject} aud=#{validated.audience}"
# 3) Admin API — admin is created lazily on first access. create() returns the new user id.
user_id = client.admin.users.create({ username: "alice", enabled: true })
client.admin.users.delete(user_id)
client.close
Audience: validation requires the token's
audto containclient_id. A stock realm does not put the client id in a client-credentials token'saud, so on a default realm either passexpected_audience: "my-api"(the audience your realm actually issues), or add an Audience protocol mapper to the client in Keycloak.
The five admin resources — users / clients / roles / groups / realms — offer symmetric CRUD, and client.admin.raw is the escape hatch to the underlying bearer-authenticated Faraday::Connection.
Security defaults
The SDK replaces the unsafe library defaults rather than inheriting them:
- Algorithm pinning — the header-supplied
algis never trusted, soalg: noneand HS/RS confusion are rejected structurally: the pin is applied before key lookup and signature verification, not after. - Strict claim checks — exact
issmatch,audcontainment, mandatoryexp,nbf, and a bounded clock skew. - DoS-safe JWKS — a refetch is triggered only by an unresolved key ID and never by a bad signature, and is rate-limited to a minimum interval (
jwks_min_refetch, 30s by default). The gate applies on a cold cache too, so it cannot be sidestepped by hitting the SDK before its first successful fetch — no volume of forged tokens makes the SDK issue more than one JWKS request per interval. - Secret handling —
Config,TokenSet, andAuthorizationRequestmask secrets and tokens in#inspect(***, no prefix leak), TLS verification is on by default, timeouts are always applied, and redirect-following middleware is never installed (SSRF hardening).
Masking covers this SDK's own #inspect; it cannot cover what your logging framework or a backtrace does with a value you hand it. Ruby has no erasable string type, so the client secret lives in an ordinary String for its lifetime — masking is defence in depth, not an erasure guarantee.
Versioning and support
This SDK is pre-1.0. Under SemVer a 0.x minor bump may carry breaking changes, so read the release notes before upgrading. Only the newest released version of each language SDK receives security fixes — there are no LTS lines, and older 0.x releases are not backported to. Full policy: SECURITY.md.
Documentation
- Getting started — install, quickstart, and the compatibility matrix
- Deploying a Keycloak server — the server this SDK talks to
- Security policy
- Full example:
examples/quickstart.rb