---
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://vonvon.id/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 Vonvon 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-vonvon.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/vonvon/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/vonvon/sdk/go/vonvon"

client, err := vonvon.NewClient(vonvon.ClientOptions{
Issuer:        "https://vonvon.id",
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 := vonvon.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 | Vonvon 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://vonvon.id/sdks/go/index.mdx
