Any language (raw REST)
IdentSphere is pure HTTP + JSON. If your language can make HTTP calls and parse JSON, it can integrate with IdentSphere.
The bare minimum
You need three things in your language:
- An HTTP client (Python
httpx, Gonet/http, RubyNet::HTTP, PHPGuzzle, etc.). - A JSON parser (every language has one in stdlib).
- Optional: a JWT library if you want to validate tokens locally without round-tripping through IdentSphere (Pattern 2 in the overview).
Almost every language has all three.
Endpoints you'll actually call
The full reference is in the API section. The ones you need on day one:
| Call | When | Reference |
|---|---|---|
POST /v1/auth/register | New user signs up | docs |
POST /v1/auth/login | Existing user signs in | docs |
POST /v1/auth/refresh | Access token expired | docs |
POST /v1/auth/logout | User clicks "log out" | docs |
GET /v1/auth/session | Need current user info | docs |
GET /.well-known/jwks.json | Validate a JWT locally | (always public, no auth required) |
Request shape
All bodies are JSON. All responses are JSON. Errors all use the same envelope:
{
"error": {
"code": "invalid_credentials",
"message": "wrong password or unknown email",
"type": "authentication_error"
}
}
See Errors for the full error catalog.
Cookies vs. Authorization header
IdentSphere supports both. Pick one:
Cookie flow (browser-style)
- Browser submits login form
- Your backend forwards to
POST /v1/auth/login - IdentSphere responds with
Set-Cookie: identsphere_at=...; HttpOnly; ... - Browser stores the cookie automatically
- Subsequent requests include the cookie; IdentSphere validates
Browsers handle this without any code on your side beyond forwarding the
Set-Cookie response header.
Bearer flow (mobile / API / server-to-server)
- Client posts credentials to
POST /v1/auth/login - Reads
access_tokenfrom the JSON body - Sends
Authorization: Bearer <token>on subsequent requests
For mobile apps / server-to-server / programmatic, the Bearer flow is usually simpler — no cookie store to manage.
Validating a JWT locally
This is the fastest path to "language X validates an IdentSphere token":
# Python with python-jose
import httpx
from jose import jwt
jwks = httpx.get("http://identsphere/.well-known/jwks.json").json()
claims = jwt.decode(token, jwks, algorithms=["RS256"], options={"verify_aud": False})
// Go with golang-jwt + keyfunc
jwks, _ := keyfunc.NewDefault([]string{"http://identsphere/.well-known/jwks.json"})
tok, _ := jwt.Parse(token, jwks.Keyfunc)
# Ruby with jwt + net/http
require "jwt"; require "net/http"; require "json"
jwks = JSON.parse(Net::HTTP.get(URI("http://identsphere/.well-known/jwks.json")))
decoded = JWT.decode(token, nil, true, { jwks: jwks, algorithms: ["RS256"] })
// PHP with firebase/php-jwt
use Firebase\JWT\JWT;
use Firebase\JWT\JWK;
$jwks = json_decode(file_get_contents("http://identsphere/.well-known/jwks.json"), true);
$claims = JWT::decode($token, JWK::parseKeySet($jwks));
// Java with Auth0 java-jwt
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.UrlJwkProvider;
import com.auth0.jwt.JWT;
JwkProvider provider = new UrlJwkProvider("http://identsphere/.well-known/jwks.json");
DecodedJWT jwt = JWT.decode(token);
// then verify with provider.get(jwt.getKeyId()).getPublicKey()
Every JWT library follows the same pattern: fetch JWKS, verify signature, decode claims. Three lines.
Token claims
IdentSphere-issued tokens contain these standard claims plus a small set of extensions:
| Claim | Type | Meaning |
|---|---|---|
sub | string (UUID) | User ID |
org | string (UUID) | Organization ID for this session |
iss | string | Issuer URL (AppConfig.public_base_url) |
exp | int (Unix ts) | Expiration |
iat | int (Unix ts) | Issued at |
typ | string | access / refresh / mfa |
email | string | (When available — populated on social login) |
jti | string (UUID) | Unique per-token ID for denylisting |
sid | string (UUID) | Session family ID — same across refreshes |
aal | string | aal1 (password) / aal2 (MFA-verified) |
auth_time | int (Unix ts) | When the user originally authenticated |
auth_method | string | password / passkey / social_oauth |
All fields except sub, exp, iat, typ are nullable in the source
struct; deserialize them as optionals in your language.
"But which language SDKs are coming?"
Roadmap, in order:
- ✅ Rust (
identsphere-axumcrate) — already shipping - ✅ TypeScript / React (
@identsphere/react) — already shipping - ⏳ Python (
identsphere) — pip-installable client wrapper, v1.1 - ⏳ Go (
github.com/IdentSphere/sdks) — Go client wrapper, v1.1 - ⏳ Java (Maven
dev.IdentSphere:identsphere-client) — v1.2 - ⏳ Ruby (gem) — v1.2
- ⏳ PHP (Composer) — v1.3
Until those land, the raw REST + JWKS approach in this page works for any language. It's only ~30 lines of glue code per language.