---
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://auth.sundays.ink/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.

Registry status: UNPUBLISHED. Install this SDK only from the repository source checkout; do not use an external package registry.

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://auth.sundays.ink/sdks/java/index.mdx
