---
title: "sdk/go"
description: "Go server SDK for networkless JWT verification, 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/go

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

```shell
go get github.com/StringKe/xid/sdk/go@main
```

## Quick start

Create one `Client` at application startup and reuse it across requests. The client caches JWKS internally with a configurable TTL.

```go
import "github.com/StringKe/xid/sdk/go/xid"

client, err := xid.NewClient(xid.ClientOptions{
Issuer:        "https://xid.dev",
Audience:      "your-client-id",
WebhookSecret: "whs_...",
})
if err != nil {
log.Fatal(err)
}

// HTTP middleware (recommended)
http.Handle("/api/", client.Middleware(apiHandler, func(w http.ResponseWriter, r *http.Request) {
http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
}))

// Inside a protected handler
func apiHandler(w http.ResponseWriter, r *http.Request) {
claims := xid.ClaimsFromContext(r.Context())
fmt.Fprintf(w, "hello %s", claims.Subject)
}
```

## Verify token directly

```go
claims, err := client.VerifyAccessToken(ctx, tokenString)
if err != nil {
// handle verification failure
}
fmt.Println(claims.Subject, claims.OrgID)

// Explicit same-origin Core session -> JWT exchange
token, err := client.ExchangeSessionToken(
ctx,
"https://app.example.com/account",
request.Header.Get("Cookie"),
"/v1/sessions/token",
)
```

## Verify webhook

```go
func webhookHandler(w http.ResponseWriter, r *http.Request) {
event, err := client.VerifyWebhook(r)
if err != nil {
    http.Error(w, "invalid signature", http.StatusBadRequest)
    return
}
// event.Body: raw JSON body
// event.ID:   svix-id for idempotency
w.WriteHeader(http.StatusNoContent)
}
```

## Core API

| Symbol | Description |
| --- | --- |
| `NewClient(opts)` | Construct the client. `Issuer` is required; other fields are optional. |
| `(*Client).VerifyAccessToken(ctx, token)` | Verify a JWT string, return `*Claims` or error. |
| `(*Client).AuthenticateRequest(ctx, r)` | Extract and verify token from an HTTP request. Always returns `AuthState`, does not panic. |
| `(*Client).Middleware(next, onUnauthorized)` | Standard `net/http` middleware. Injects `*Claims` into context on success. |
| `ClaimsFromContext(ctx)` | Extract claims injected by Middleware. |
| `(*Client).VerifyWebhook(r)` | Verify webhook request signature. Returns `*WebhookEvent` with raw body on success. |

## ClientOptions

| Field | Default | Description |
| --- | --- | --- |
| `Issuer` | required | XID issuer URL |
| `Audience` | empty (skip) | Expected JWT aud claim |
| `WebhookSecret` | empty | Webhook HMAC signing secret |
| `JWKSCacheTTL` | `1h` | JWKS local cache TTL |
| `HTTPClient` | 10s timeout default | HTTP client for JWKS fetch |

## Platform notes

- ES256 is the primary algorithm; RS256 is supported for compatibility. ES384 and ES512 are not yet implemented.
- JWKS is fetched from `{issuer}/jwks`. OIDC Discovery auto-detection is a planned improvement.
- `Claims` embeds `jwt.RegisteredClaims` and adds `ClientID`, `Scope`, `AMR`, `ACR`, `OrgID`, `OrgSlug`.

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