Authentication and Security
This page describes how to authenticate your system's calls to the LightCMS external REST API, and how your tenant is determined once you're authenticated.
Design principle
You call the API with a short-lived access token issued by the LightCMS identity provider (OAuth 2.0 client credentials grant). To get the token, you authenticate with a JWT signed by your own private key — LightCMS only holds the matching public key you registered during onboarding. Your client registration determines your tenant.
How authentication works
Authentication takes one extra call before you call the API:
- Sign a client assertion — a short-lived JWT signed with your private key.
- Get an access token — send the assertion to the LightCMS token endpoint. You receive an access token valid for 5 minutes.
- Call the API — send the access token in the standard
Authorizationheader. Reuse it until it expires, then get a new one.
Step 1 — client assertion
The client assertion is a JWT signed with your private key (RSA, RS256), following RFC 7523.
Assertion header
| Claim | Mandatory | Description |
|---|---|---|
alg |
yes | Must be RS256 |
kid |
yes | Key identifier agreed with LightCMS during onboarding. It selects the public key the signature is verified with |
Assertion payload
| Claim | Mandatory | Description |
|---|---|---|
iss |
yes | Your client_id |
sub |
yes | Your client_id |
aud |
yes | Token endpoint URL |
jti |
yes | Unique identifier of the assertion. An assertion cannot be used twice |
iat |
yes | Issued-at timestamp |
exp |
yes | Expiration timestamp, at most 5 minutes after iat |
Sign a new assertion for every token request.
Step 2 — access token
Send the assertion to the token endpoint of the environment. The token endpoint URL and your client_id are provided during onboarding.
POST /keycloak/realms/lightcms/protocol/openid-connect/token HTTP/1.1
Host: {host}
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=<your client_id>
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=<signed client assertion>
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ...",
"expires_in": 300,
"token_type": "Bearer"
}
Errors of the token endpoint follow the OAuth 2.0 format (RFC 6749 §5.2), e.g. {"error": "invalid_client"} for an assertion that can't be verified.
Step 3 — call the API
Send the access token in the standard Authorization header of every API request:
Token lifetime
The access token is valid for expires_in seconds (5 minutes). Cache it and reuse it for all requests until it expires, then get a new one — there is no refresh-token flow. There's no need to get a token per request.
Responses
| Situation | Response |
|---|---|
| Missing, malformed, unverifiable or expired access token | 401 Unauthorized |
| Valid access token, but your client isn't authorized for the requested endpoint or method, or for the requested tenant | 403 Forbidden |
| Valid access token and authorized endpoint | request is processed normally |
Both 401 and 403 are returned as Problem Details — see Standardized responses.
Tenant identification
Your tenant is derived from your client registration — never from the URL, body or X-Cms-Tenant header of the request. A client can only act on behalf of the tenants registered for it.
If your client is registered for more than one tenant, select the tenant of a request with the X-Cms-Tenant-Override header. Without it, the default tenant of your client is used. A tenant your client isn't registered for is refused with 403 Forbidden.
Onboarding
Before you can call the API, your client is registered as part of onboarding:
- You generate an RSA key pair (at least 2048 bits) and send LightCMS the public key, together with a
kidvalue you choose to identify it. - LightCMS registers a client for you with your public key, your tenant(s) and the list of endpoints and methods your integration is authorized to call.
- LightCMS sends you your
client_idand the token endpoint URL for each environment. - You keep the private key and use it to sign client assertions from that point on.
Key rotation
To rotate your key:
- Generate a new key pair and send us the new public key with a new
kid. - LightCMS registers the new key for your client and confirms the switch-over time with you.
- Sign your client assertions with the new key (new
kid) from that time on.
JWKS URL
If you publish your public keys on a JWKS URL, LightCMS can read your keys from it instead. A new key is then picked up automatically, with no coordinated switch-over.