Skip to content

Authentication ​

Quarzo has two independent authentication mechanisms. Pick the one that matches what you're building - they don't compose into each other.

Which one do I need?

M2M - broker backend ​

Your broker backend authenticates as a service account - a machine identity provisioned for you on our identity provider (the "insurer IdP"). This takes three steps: get a service-account access token, resolve the identity of the end user you're acting on behalf of, then exchange for a delegated token.

1. Your service account ​

Quarzo provisions a service account for your broker backend during integration and delivers a JSON key:

json
{
  "type": "serviceaccount",
  "keyId": "163840776835432193",
  "key": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----",
  "userId": "163840762291765249"
}

Store it the way you'd store any private key - never commit it, never log it.

2. Get an access token - JWT Bearer Grant ​

Authenticate with RFC 7523 (JWT Bearer Grant): build a JWT assertion signed with your service account's private key, and exchange it for an access token.

Assertion claims:

ClaimValue
issYour service account's userId.
subYour service account's userId (same as iss).
audThe IdP's issuer URL for your environment - see the warning below.
iat / expIssued-at and a short expiry (a few minutes).

Sign with RS256 using the key from your JSON key, setting the JWT header's kid to keyId. Exchange the assertion at the token endpoint:

http
POST {authority}/oauth/v2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&assertion=<signed-jwt-assertion>
&scope=<scope-string-provided-during-onboarding>

aud must match the issuer exactly

aud must equal the IdP's OIDC issuer for {authority}, with no trailing slash. A URL copied from the IdP's admin console usually has one. A mismatch fails with 400 invalid_grant ("invalid assertion") - an error that gives no indication the cause is a trailing slash.

The audience scope is required

The scope string we give you during onboarding includes a provider-specific audience entry. Without it, the token is issued successfully but carries the wrong audience: it will be rejected by every Quarzo business endpoint even though the token itself is valid.

The resulting access token authenticates you as the service account - but on its own it is not enough to call endpoints that need a broker identity.

3. Resolve the actor, then exchange for a delegated token ​

Endpoints such as POST /v1/subscription/subscribers or POST /v1/broker-notifications/registrations reject a bare service-account token with 401 (NO_SESSION / INACTIVE_SESSION). Before calling them, resolve who you're acting on behalf of:

http
GET /v1/authentication/subjects/{externalUserId}
Authorization: Bearer <service-account-access-token>

externalUserId is the identifier you assigned to that subscriber or broker user when you registered them with Quarzo. The response gives you the corresponding Quarzo/insurer IdP identity:

json
{
  "kind": "subscriber",
  "insurerIdpUserId": "163841234567890123",
  "brokerId": "...",
  "subscriberId": "..."
}

Use insurerIdpUserId as the subject of an RFC 8693 token exchange against your IdP client, to obtain a token that acts on behalf of that person. This exchange happens against the IdP directly, not against the Quarzo API.

Error reference for GET /v1/authentication/subjects/{externalUserId}:

StatusWhen
401The Authorization header is missing, the access token is invalid/expired, or the Broker Service Account is inactive.
403The token is valid but doesn't belong to a registered broker service account.
404No subscriber or broker user is registered under that externalUserId for your broker.

User authentication - broker advisor & subscriber ​

A subscriber or broker user signing into your app authenticates directly - no service account involved. This is a standard OAuth Authorization Code + PKCE flow against the same identity provider instance used for M2M above.

Request the roles scope we give you during onboarding, alongside the usual openid profile email, to receive the person's project roles (adviser / subscriber) in the resulting token - use these for application-level authorization.

This flow is otherwise unrelated to the M2M flow above: no service account, no JWT Bearer Grant, no token exchange. It's a plain federated login for a human.

How the two flows relate

externalUserId (used in the M2M actor lookup, above) is an identifier you assign when registering a subscriber or broker user with Quarzo - it is not derived from this login flow. In practice, use the same identifier you already use for that person in your own system in both places.

Website