Skip to content
Discussions/App Development/Enabling auth-services on a running MainNet participant for party-scoped private contract queries?Forum ↗

Enabling auth-services on a running MainNet participant for party-scoped private contract queries?

App Development3 posts43 viewsLast activity Apr 2026
WE
web3OP
Mar 2026

Hi everyone,

We’re building a governance dApp (DAOs, proposals, voting) on Canton MainNet with a self-hosted participant (web34ever::12205...). Go backend talks to the participant via gRPC Ledger API.

We’re adding private contracts where the operator party is excluded from observers:

template DAO with
    admin      : Party
    members    : [Party]
    visibility : DAOVisibility
  where
    signatory admin
    observer case visibility of
              Public  -> [operator] <> members
              Private -> members   -- operator excluded

From researching this forum (thanks WallaceKelly & bernhard — your posts on JWT authorization, actAs/readAs semantics, and PQS vs JSON API were exactly what we needed), we understand that:

  • Per-party JWT with actAs=[memberParty] is required to query private contracts — operator readAs won’t work
  • actAs implies readAs, so a single right grant is sufficient
  • JSON API is fine for our scale (~50-200 DAOs), no need for PQS yet
  • Ledger API User creation via /v2/users + /v2/users/{id}/rights is the right pattern

Two remaining questions:

1. Adding auth-services to an already-running MainNet participant

We did not configure ledger-api.auth-services when we initially set up our participant. We plan to add:

canton.participants.web34ever {
  ledger-api {
    auth-services = [{
      type = jwt-rs-256-crt
      certificate = "/path/to/our-public.crt"
    }]
  }
}

Our backend would sign JWTs with the corresponding private key, including actAs=[partyId] claims for each user.

Are there any gotchas with enabling auth on a participant that already has existing contracts and allocated parties? Does a restart with auth-services added require any migration, or is it purely additive?

2. Coexistence with Splice validator stack

We’re also preparing for Splice validator onboarding (splice-validator-app + splice-wallet-app). Does the Splice stack configure its own auth on the participant (e.g. Keycloak)? If so, can multiple auth-services entries coexist — ours (cert-based) alongside Splice’s (JWKS)?

auth-services = [
  { type = jwt-rs-256-crt, certificate = "our-key.crt" },       # our backend
  { type = jwt-jwks, url = "http://keycloak:8080/.../jwks" }     # splice stack
]

Or would we need to consolidate into a single auth provider?

Any pointers appreciated. Happy to share more about our contract model if helpful.

Thanks!

JA
Jatin_Pandya_cf
Apr 2026

hey @web3
so on above, some pointers I’d give is

  • Canton stores auth configuration at the process level so your contracts, parties, and transaction history live in the participant’s database and are completely unaffected by adding auth-servicesAFIK the change affects only how the Ledger API authenticates incoming requests going forward.

  • the user Identity management layer is separate from auth-services configuration. The users and their actAs/readAs rights you’ve created persist in the participant DB. Auth-services just controls how the participant verifies that the JWT presented actually belongs to the claimed user. Your existing user/rights setup carries over intact.

  • When you onboard with the Splice the validator app configures its own auth against the participant’s Ledger API using the OIDC provider you specify at onboarding time (Auth0 or Keycloak). Splice expects to be the configured auth provider by default in its Docker Compose config. It will set the ledger-api-auth Kubernetes secret or the LEDGER_API_AUTH_* env vars which typically overwrite your configuration if you’re using the Splice deployment tooling.

  • also Recommended is to set Splice’s splice-app-validator-ledger-api-auth secret to point to your Keycloak instance but ensure the participant itself has both auth entries configured in your own config file, not overridden by Splice or your custom auth.

EV
evoandro
Apr 2026

Your setup looks correct.

  1. Adding auth-services later

Yes — you can add ledger-api.auth-services to an existing MainNet participant without migration.

You just:

  • update config
  • restart participant
  • start sending JWTs

Existing:

  • contracts
  • parties
  • data

will continue working normally.

Main thing to remember:
after enabling auth, every Ledger API request must include a valid JWT.

Your per-party JWT approach with:

actAs=[partyId]

is the correct design for private contracts.


  1. Splice + your auth together

Yes — multiple auth-services can coexist.

Example:

auth-services = [
  { type = jwt-rs-256-crt, certificate = "our.crt" },
  { type = jwt-jwks, url = "http://keycloak/.../jwks" }
]

This is supported.

So:

  • your backend can use cert-signed JWTs
  • Splice can use Keycloak/JWKS

at the same time.

Just make sure JWT claims (actAs, aud, expiration, etc.) are configured correctly.


One important note:

If a contract is private and operator is excluded:

Private -> members

then operator truly cannot read/query it.

So your backend must always issue JWTs for the actual member party when accessing private contracts.

Your architecture already matches this properly.

← Back to Discussions