---
title: "sdk/java"
description: "Java 17+ server SDK for networkless JWT verification, HTTP 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/java

## 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

Java 17+ and Maven required.

```xml
<!-- First install the source checkout: cd sdk/java && mvn install -->
<dependency>
  <groupId>dev.xid</groupId>
  <artifactId>xid-sdk-java</artifactId>
  <version>0.1.0-alpha.0</version>
</dependency>
```

## Quick start

Construct one `XidClient` at application startup and use it as a singleton.

```java
import dev.xid.sdk.XidClient;
import dev.xid.sdk.XidClientOptions;
import dev.xid.sdk.XidClaims;
import dev.xid.sdk.XidTokenException;
import dev.xid.sdk.XidJwksException;

XidClient xid = XidClient.create(
XidClientOptions.builder()
    .issuer("https://xid.dev")
    .audience("your-client-id")
    .webhookSecret("whsec_xxx")
    .build()
);

try {
XidClaims claims = xid.verifyToken(accessToken);
String userId = claims.getSub();
String scope  = claims.getScope();
} catch (XidTokenException e) {
response.sendError(401, "Unauthorized: " + e.getReason());
} catch (XidJwksException e) {
response.sendError(503, "Service unavailable");
}
```

## Authenticate an HTTP request

```java
import dev.xid.sdk.AuthResult;

// Bearer-only by default
AuthResult result = xid.authenticateRequest(request.getHeader("Authorization"), null);

if (result.isAuthenticated()) {
String userId = result.getClaims().get().getSub();
} else {
response.sendError(401);
}

String token = xid.exchangeSessionToken(
request.getRequestURL().toString(),
request.getHeader("Cookie"),
"/v1/sessions/token"
);
```

## Verify webhook

```java
import dev.xid.sdk.XidWebhookException;

byte[] rawBody = request.getInputStream().readAllBytes();
Map<String, String> headers = Map.of(
"svix-id",        request.getHeader("svix-id"),
"svix-timestamp", request.getHeader("svix-timestamp"),
"svix-signature", request.getHeader("svix-signature")
);

try {
xid.verifyWebhook(headers, rawBody);
} catch (XidWebhookException e) {
response.sendError(400, "Invalid webhook: " + e.getReason());
}
```

## XidClientOptions

| Method | Default | Description |
| --- | --- | --- |
| `.issuer(String)` | required | OIDC issuer; must match token iss exactly |
| `.audience(String)` | `null` | Expected aud; null skips validation |
| `.webhookSecret(String)` | `null` | Webhook secret (`whsec_` prefix or raw base64) |
| `.jwksCacheDuration(Duration)` | 1 hour | JWKS in-memory cache TTL |
| `.clockSkewTolerance(Duration)` | 30 seconds | exp/nbf clock skew tolerance |
| `.connectTimeout(Duration)` | 5 seconds | HTTP connection timeout for JWKS fetch |
| `.readTimeout(Duration)` | 10 seconds | HTTP read timeout for JWKS fetch |

## Platform notes

- Uses `nimbus-jose-jwt` for JWT/JWKS parsing. ES256 is primary; RS256 and PS256 are supported.
- All public APIs are synchronous and thread-safe.
- Logging via SLF4J facade; bring your own implementation (Logback, Log4j2).
- Exception hierarchy: `XidException` -&gt; `XidTokenException`, `XidJwksException`, `XidWebhookException`.

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