+33 9 84 25 52 61
Sign in
Developers

Three quickstarts, zero lock-in.

Obexal is a complete OIDC and OAuth 2.1 provider: discovery, JWKS, PAR, introspection and revocation sit exactly where the specifications put them. Start with three curl quickstarts, then go deeper in the documentation.

Add login to a web app

Authorization code with PKCE (S256): read the discovery document, send the user to the authorization endpoint, exchange the code.

login.sh
# 1. Read the discovery document
curl -s https://accounts.obexal.com/.well-known/openid-configuration

# 2. Generate a PKCE verifier and its S256 challenge
CODE_VERIFIER=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | cut -c1-64)
CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" \
  | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')

# 3. Send the user to the authorization_endpoint from discovery
#    .../oauth/authorize?response_type=code&client_id=$CLIENT_ID
#      &redirect_uri=$REDIRECT_URI&scope=openid+profile+email
#      &code_challenge=$CODE_CHALLENGE&code_challenge_method=S256

# 4. Exchange the returned code for tokens
curl -s https://accounts.obexal.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "code=$AUTH_CODE" \
  --data-urlencode "redirect_uri=$REDIRECT_URI" \
  --data-urlencode "client_id=$CLIENT_ID" \
  --data-urlencode "code_verifier=$CODE_VERIFIER"

Protect a machine service

Client credentials for service-to-service calls. The secret comes from your environment or secret manager, never inline on the command line.

service.sh
# CLIENT_SECRET is injected by your secret manager, never typed inline
curl -s https://accounts.obexal.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "client_id=$CLIENT_ID" \
  --data-urlencode "client_secret=$CLIENT_SECRET" \
  --data-urlencode "scope=directory.read"

# Response
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "directory.read"
}

Give an AI agent an identity

The agent authenticates with its own client credentials (PAR available at /oauth/par). Delegation has a proper name: Token Exchange, RFC 8693. The issued token carries the delegation chain in the act claim.

agent.sh
# 1. The agent gets its own token, capped by its scope ceiling and TTL cap
curl -s https://accounts.obexal.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "client_id=$AGENT_CLIENT_ID" \
  --data-urlencode "client_secret=$AGENT_CLIENT_SECRET" \
  --data-urlencode "scope=crm.read"

# 2. Delegation, properly named: Token Exchange (RFC 8693)
#    The agent acts on behalf of a user; the token carries the act claim
curl -s https://accounts.obexal.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  --data-urlencode "subject_token=$USER_ACCESS_TOKEN" \
  --data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
  --data-urlencode "client_id=$AGENT_CLIENT_ID" \
  --data-urlencode "client_secret=$AGENT_CLIENT_SECRET" \
  --data-urlencode "scope=crm.read"

Scope ceilings, kill switch and anomaly detection are covered in depth on AI agent identity.

Validate a token

Local validation against published keys when latency matters, introspection when revocation and the kill switch must be visible immediately.

validate.sh
# Option A: validate locally against the published keys
curl -s https://accounts.obexal.com/.well-known/jwks.json
# then check signature, exp, iss and aud in your JWT library

# Option B: server-side introspection (RFC 7662)
# Revoked tokens and agent kill switches show up here immediately
curl -s https://accounts.obexal.com/oauth/introspect \
  --data-urlencode "token=$ACCESS_TOKEN" \
  --data-urlencode "client_id=$CLIENT_ID" \
  --data-urlencode "client_secret=$CLIENT_SECRET"

Endpoints at a glance

Discovery
/.well-known/openid-configuration
JWKS
/.well-known/jwks.json
Token
/oauth/token
Pushed authorization requests
/oauth/par
Introspection
/oauth/introspect
Revocation
/oauth/revoke
RP-initiated logout
/oauth/logout
Userinfo
/oauth/userinfo
SAML metadata
/saml/idp/{tenant}/metadata
SCIM users
/scim/v2/Users
Admin API contract (OpenAPI 3.1)
/v1/openapi.json

The admin API is described by a public OpenAPI 3.1 contract: generate a client in your language instead of waiting for an SDK.

Provision users over SCIM

Inbound SCIM 2.0 covers the Users resource; groups are managed in the Obexal directory. Outbound SCIM provisions your downstream apps, with automatic deprovisioning.

scim.http
POST /scim/v2/Users HTTP/1.1
Host: accounts.obexal.com
Authorization: Bearer $SCIM_TOKEN
Content-Type: application/scim+json

{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "userName": "marie.durand@example.com",
  "name": { "givenName": "Marie", "familyName": "Durand" },
  "active": true
}

AI agents on the admin API side

Everything an agent does at the token endpoint is governed from the admin API.

Register an agent

Every agent gets its own client credentials, a human owner, an expiry date and lifecycle states (active, dormant, expired, orphaned).

Fail-closed ceilings

A scope ceiling and a maximum TTL per agent: any request beyond them is refused, never silently degraded.

Immediate kill switch

Cut an agent off in one call: tokens already issued turn inert at introspection. Secrets are renewed and expire on schedule.

Practical, and honest

Sandbox

The free trial doubles as a sandbox: 30 days, no credit card.

Service status

Service health is published continuously.

Changelog

Every notable API and product change is published.

TypeScript SDK

A zero-dependency TypeScript SDK exists, aimed at the browser. Server side, the API is plain HTTP from any language, or a client generated from the OpenAPI contract.

Developer FAQ

Which grant types are supported?

Authorization code with PKCE (S256) for user-facing apps, client credentials for services and agents, and Token Exchange (RFC 8693) for delegation. Pushed Authorization Requests are available at /oauth/par.

How do confidential clients authenticate?

With client_secret or private_key_jwt. DPoP is supported to bind a token to a key held by the client.

How do I validate access tokens?

Locally with the keys from /.well-known/jwks.json, or server side with introspection (RFC 7662) at /oauth/introspect. Revoke at /oauth/revoke.

Is there an SDK?

A zero-dependency TypeScript SDK exists, aimed at the browser. Server side we made a deliberate choice: strict standards plus a public OpenAPI 3.1 contract at /v1/openapi.json, from which you generate a client in your language.

How does SCIM work?

Inbound SCIM 2.0 exposes the Users resource at /scim/v2/Users; groups are managed in the Obexal directory. Outbound SCIM provisions downstream apps, with automatic deprovisioning on suspension and audited failures.

How do I give an AI agent an identity?

Each agent has its own client credentials, with PAR as an option. Acting on behalf of a user goes through Token Exchange (RFC 8693), with a chained act claim and downscoping. Ceilings, kill switch and anomaly detection: see AI agent identity.

Is there a test environment?

The free trial doubles as a sandbox: 30 days, no credit card, at accounts.obexal.com. Service status lives at /status/ and changes at /changelog/.

Where is it hosted?

Obexal is hosted in France, in a datacenter in the Paris region, with EU data residency. No non-EU dependency in the request path, no external CDN, self-hosted fonts. TLS 1.2 minimum, 1.3 preferred.

Everything else is in the docs.

Quickstarts, endpoint references and guides: everything above is covered in depth.