Client Authentication#

For most production mobile apps, client authentication happens transparently: attestation handles client identity, and the OAuth client configured for HAAPI uses no-authentication because hardware-backed attestation already proves the client’s authenticity. When attestation cannot be used — older devices, simulators, or any flow that uses the Dynamic Client Registration fallback — the client must authenticate by another method.

The Three Methods#

Secret. The client sends a static shared secret on the token request. Easy to set up; appropriate only for development or controlled environments because the secret is identical for every install of the app.

val authMethod = ClientAuthenticationMethodConfiguration.Secret(secret = "foo")

Mutual TLS (MTLS). The client presents a client certificate during the TLS handshake, and the Curity Identity Server validates it against its configured trust store. The SDK checks the server’s certificate in return: on iOS the platform validates the certificate chain and the pinned certificate or public-key hash must then match a certificate of that chain; on Android the SDK validates it against the configured trust store, or, with pinned keys, the platform validates the chain first and a pinned key is then required on one of its certificates. On both platforms, pinning tightens platform trust rather than replacing it. Strong, but requires certificate provisioning and renewal infrastructure.

Signed JWT client assertion. The client builds a JWT (using a symmetric or asymmetric key pair) and presents it as client_assertion. The server is configured with the matching public key (or shared secret) to verify the assertion. Provides cryptographic proof of possession without TLS-level coupling and integrates cleanly with key-rotation processes.

Choosing a Method#

Production deployments that need a fallback typically use Signed JWT (asymmetric) — keys are easy to rotate, the signing material can live in the device Keychain or Keystore, and the server’s configuration is decoupled from the transport. MTLS suits environments where a public-key infrastructure already exists. Secret stays in development and prototyping; do not ship it.

When you configure a DcrConfiguration or set useAttestation to false, the client authentication method must be set to something other than None. Otherwise the flow fails before reaching the server.

Was this helpful?