Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ All notable changes to backendkit are documented here. Format:

## [Unreleased]

### Changed

- Docs: `socrate.ClientConfig.AdminBaseURL` is documented as required in production. The value
derived when it is empty (`BaseURL` with port 8081, same scheme and host) is wrong behind a
TLS reverse proxy, where the admin API is plain HTTP on loopback; the integration guide, the
README and the package doc now say to set it (e.g. `http://127.0.0.1:8081`), to read the port
from the server's `ADMIN_PORT` (8082 in the layout that co-hosts a legacy server on 8081),
and what a backend on another host can and cannot call. No code change.

## [1.15.0] - 2026-09-29

Minor release on the **v1** line: no breaking change to any exported identifier. It adds opt-in
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ however you like in your own service.
| `SOCRATE_JWKS_URL` | `jwtauth.New` | JWKS endpoint used to validate RS256 signatures, e.g. `https://socrate.example.com/.well-known/jwks.json` |
| `SOCRATE_ISSUER` | `jwtauth.New` | Expected `iss` claim — optional; enforced only when non-empty (an empty value logs a warning at startup) |
| `SOCRATE_BASE_URL` | `socrate.NewClient` | Socrate OAuth port base URL (e.g. `https://socrate.example.com`) |
| `SOCRATE_ADMIN_BASE_URL` | `socrate.NewClient` | Socrate admin API base URL — optional; derived from `SOCRATE_BASE_URL` with port 8081 when empty |
| `SOCRATE_ADMIN_BASE_URL` | `socrate.NewClient` | Socrate admin API base URL, e.g. `http://127.0.0.1:8081` (the server's `ADMIN_PORT`; 8082 where a legacy server holds 8081). Set it in production: the value derived from `SOCRATE_BASE_URL` (port 8081, same scheme and host) is wrong behind a TLS proxy |
| `SOCRATE_CLIENT_ID` | `socrate.NewClient`, `jwtauth.WithAudience` | OAuth client ID |
| `SOCRATE_CLIENT_SECRET` | `socrate.NewClient` | Client secret — required for service-account calls, `Decide`, `RevokeToken`, `IntrospectToken` and a BFF's token exchange |
| `SOCRATE_APP_ID` | `socrate.NewClient` | Pre-resolved numeric app ID — **required** for every service-account method, including `Decide` |
Expand Down
24 changes: 19 additions & 5 deletions docs/CLIENT-INTEGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ guide:
| `SOCRATE_JWKS_URL` | `jwtauth.New` | JWKS endpoint, e.g. `https://socrate.example.com/.well-known/jwks.json` |
| `SOCRATE_ISSUER` | `jwtauth.New` | Expected `iss` claim — optional but recommended in production |
| `SOCRATE_BASE_URL` | `socrate.NewClient` | OAuth (public) port base URL, e.g. `https://socrate.example.com` |
| `SOCRATE_ADMIN_BASE_URL` | `socrate.NewClient` | Admin API base URL — optional; derived from `BaseURL` with port 8081 (the default deployment's admin port) if omitted |
| `SOCRATE_ADMIN_BASE_URL` | `socrate.NewClient` | Admin API base URL, e.g. `http://127.0.0.1:8081`. Set it in production: when empty it is derived from `BaseURL` with port 8081, which is wrong behind a TLS proxy (§6.3) |
| `SOCRATE_CLIENT_ID` | `socrate.NewClient` | Your app's OAuth client ID |
| `SOCRATE_CLIENT_SECRET` | `socrate.NewClient` | Client secret — required for service-account calls, `Decide`, `RevokeToken`, `IntrospectToken` and a BFF's token exchange |
| `SOCRATE_APP_ID` | `socrate.NewClient` | Pre-resolved numeric app ID — **required** for every service-account method |
Expand Down Expand Up @@ -302,7 +302,7 @@ client, err := socrate.NewClient(socrate.ClientConfig{
ClientID: os.Getenv("SOCRATE_CLIENT_ID"), // required
ClientSecret: os.Getenv("SOCRATE_CLIENT_SECRET"), // service-account / introspect / revoke
AppID: os.Getenv("SOCRATE_APP_ID"), // required for service-account calls
// AdminBaseURL: "https://socrate.example.com:8081", // optional; derived from BaseURL if empty
AdminBaseURL: os.Getenv("SOCRATE_ADMIN_BASE_URL"), // e.g. http://127.0.0.1:8081 — see §6.3
// Timeout: 30 * time.Second, // optional; default 30s
})
if err != nil {
Expand Down Expand Up @@ -365,9 +365,23 @@ URLs yourself:
everything else — app-user management, app management, superadmins,
security, dashboard, audit logs, magic links, policy decisions.

`AdminBaseURL` defaults to `BaseURL` with the host port replaced by `8081`.
Set it explicitly when your deployment differs, for example when the admin API
listens on another host or port.
`AdminBaseURL` defaults to `BaseURL` with the host port replaced by `8081`,
keeping its scheme and host. That default only fits a Socrate reached directly,
with both ports on one host. **Set `AdminBaseURL` explicitly in production:**

- Behind a TLS reverse proxy (the usual layout), `BaseURL` is the public issuer,
e.g. `https://socrate.example.com`, and the derived
`https://socrate.example.com:8081` is wrong: the admin API is plain HTTP bound
to loopback (`ADMIN_BIND_HOST=127.0.0.1`), not published by the proxy. Use
`http://127.0.0.1:<ADMIN_PORT>` from a service on the same host.
- The port is the server's `ADMIN_PORT`: 8081 by default, but a host that runs
another service on 8081 moves it — the layout that co-hosts Socrate with a
legacy server uses **8082**. Read it from the server's environment file rather
than assuming 8081; a wrong port can reach a different service.
- A backend on another host cannot reach a loopback-bound admin API at all. It
can still validate tokens (JWKS) and use the OAuth-port methods; admin, app-user
and policy calls need the backend on the Socrate host, or an admin API bound
to a private interface and firewalled to that backend.

### 6.4 Method reference

Expand Down
7 changes: 5 additions & 2 deletions socrate/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
// 8081 — Admin API (internal; restrict at network level)
// /api/admin/*, /api/apps/{id}/users/*, /api/apps/{id}/service/*
//
// AdminBaseURL defaults to BaseURL with the host port replaced by 8081.
// AdminBaseURL defaults to BaseURL with the host port replaced by 8081, keeping
// its scheme and host. Behind a TLS reverse proxy that default is wrong (the admin
// API is plain HTTP on loopback, on the server's ADMIN_PORT), so production
// callers set it explicitly, e.g. http://127.0.0.1:8081.
// All user-management and admin calls are routed to AdminBaseURL automatically.
package socrate

Expand Down Expand Up @@ -70,7 +73,7 @@ type Client struct {
// ClientConfig holds the constructor options for Client.
type ClientConfig struct {
BaseURL string // OAuth port URL (e.g. https://auth.example.com)
AdminBaseURL string // Admin port URL (e.g. https://auth.example.com:8081); derived from BaseURL if empty
AdminBaseURL string // Admin port URL (e.g. http://127.0.0.1:8081); derived from BaseURL (port 8081) if empty — set it behind a TLS proxy
ClientID string // OAuth client ID
ClientSecret string // OAuth client secret (required for service-account calls)
AppID string // Pre-resolved numeric app ID; skips runtime resolution when set
Expand Down
Loading