Assetera Docs
API reference

Authentication (Keycloak)

What credentials a tenant receives, how to use them, and what they represent. Assetera Identity is a Keycloak realm speaking standard OIDC / OAuth 2.0.

Assetera Identity is a Keycloak realm speaking standard OpenID Connect / OAuth 2.0. Because it is standard OIDC, any OIDC client library works. As a tenant you are provisioned an OIDC client; every token that client mints carries your tenant claim, and Assetera's APIs validate it locally against the realm's public keys (JWKS). No shared secret is held by the API, and there is no per-request round trip back to Keycloak.

What you are provisioned

When your tenant is onboarded you receive one confidential OIDC client:

You receiveWhat it isWhat it represents
client_idYour tenant's client identifierYour tenant's machine identity
A client secret or (preferred) a key pair for private_key_jwtHow the client proves itselfOnly your backend can mint tokens for your tenant
The issuer / realm URL and its discovery document.../realms/assetera + .well-known/openid-configurationWhere to authorize, get tokens, and fetch keys
An audience for the API you calle.g. marketplace-apiWhich API your tokens are valid for
Redirect URIs (for user login)Your BFF callback URLsWhere users return after signing in

The client secret / private key is a backend credential. It never ships to a browser. Prefer private_key_jwt: you hold the private key and Assetera registers only your public keys, so no shared secret crosses the boundary.

Two grants

How you obtain a token depends on who is calling:

GrantWhoWhen
Authorization Code + PKCEa user (via your BFF)someone signs in and clicks through a UI
Client Credentialsyour backendserver to server, no user present

Both yield a signed JWT carrying your tenant claim; the grant only changes how the token is obtained, not how the API validates it.

Getting a token (backend, Client Credentials)

curl -X POST \
  "https://auth.<base_domain>/realms/assetera/protocol/openid-connect/token" \
  -d grant_type=client_credentials \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d audience=marketplace-api
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI...",
  "token_type": "Bearer",
  "expires_in": 300,
  "scope": "marketplace.read"
}

You then call the API with Authorization: Bearer <access_token>. Use the discovery document to resolve the real token, authorize, and jwks_uri endpoints for your environment rather than hardcoding paths.

Inside the token

The access token is a signed JWT. The claims that matter to an integrator:

{
  "iss": "https://auth.<base_domain>/realms/assetera",
  "aud": "marketplace-api",
  "sub": "b1e...-user-or-service-id",
  "tenant": "your-tenant-id",
  "scope": "marketplace.read marketplace.trade",
  "exp": 1730000000
}

Being finalised

The exact claim name for the tenant (tenant vs tenant_id), the scope catalogue, and the role model are being finalised alongside marketplace-api development. Treat the names above as illustrative.

  • tenant scopes every response. It is minted by your client and read server-side; you cannot set or spoof it on the wire (see Tenancy).
  • aud pins the token to one API. A token for one service is rejected by another, so it cannot be replayed.
  • exp is short (minutes). Refresh (user flows) or re-request (M2M) rather than caching long-lived tokens.

How validation works

The API validates every token itself, against the realm's JWKS: signature, issuer, audience, expiry, then it reads the tenant claim and scopes the query. If you gate your own UI, validate the same way in your BFF, and always re-check authorisation on the server.

The interactive (user) flow

On this page