Client Authentication (Driver Layer)#
When attestation cannot be used — older devices, simulators, or any Dynamic Client Registration fallback path — the client must authenticate by another method. Configure the chosen method when constructing HaapiTokenManager. For the concept and the three available methods, see Client Authentication .
Secret#
A static shared secret. Easy to set up; appropriate only for development or controlled environments because the secret is identical for every install.
let clientAuth = ClientAuthenticationMethodSecret("foo")
let haapiTokenManager = HaapiTokenManagerBuilder(
tokenEndpoint: tokenEndpoint,
clientId: clientId
)
.setClientAuthenticationMethod(method: clientAuth)
.build() val authMethod = ClientAuthenticationMethodConfiguration.Secret(secret = "foo")
val haapiTokenManager = HaapiTokenManager.Builder(
clientId = clientId,
tokenEndpointUri = tokenEndpointUri
)
.setClientAuthenticationMethodConfiguration(authMethod)
.build() Mutual TLS#
Mutual-TLS authentication: the client presents a certificate during the TLS handshake. The server validates the certificate against a configured trust store, or against pinned public-key hashes.
// Using a bundled PKCS12 keystore + server PEM:
let clientAuth = try ClientAuthenticationMethodMTLS(
pkcs12Filename: "client.p12",
pkcs12Passphrase: "passphrase",
serverPEMFilename: "server.pem",
isValidatingHostname: true,
bundle: Bundle.main
)
// Or with pinned server public-key hash:
let clientAuthPinned = try ClientAuthenticationMethodMTLS(
pkcs12Filename: "client.p12",
pkcs12Passphrase: "passphrase",
serverKeyPinnings: [
KeyPinning(
hostname: "idsvr.example.com",
publicKeyHash: "Kjuy4mT3fbeDozRNP6rTjWRYmbs79Begb5Roq+DUu7s="
)
],
bundle: Bundle.main
) // Using bundled client keystore + server trust store:
val mtls = ClientAuthenticationMethodConfiguration.Mtls(
clientKeyStore = myClientKeyStore,
clientKeyStorePassword = "passphrase",
serverTrustStore = myServerTrustStore
)
// Or with pinned server public-key hash:
val mtlsPinned = ClientAuthenticationMethodConfiguration.MtlsKeyHash(
clientKeyStore = myClientKeyStore,
clientKeyStorePassword = "passphrase",
serverKeyPinnings = setOf(
ClientAuthenticationMethodConfiguration.MtlsKeyHash.KeyPinning(
hostname = "idsvr.example.com",
publicKeyHash = "Kjuy4mT3fbeDozRNP6rTjWRYmbs79Begb5Roq+CNwiG="
)
),
isValidatingHostname = true
) Signed JWT#
Build a JWT signed with an asymmetric or symmetric key and present it as client_assertion. The server is configured with the matching public key (asymmetric) or shared secret (symmetric) to verify the assertion.
// Asymmetric (recommended for production):
let asymConfig = try ClientAuthenticationMethodJWTAsymmetric(
pemFilename: "rsa-private-key.pem",
signatureAlgorithm: .rs256,
bundle: Bundle.main
)
// Symmetric (HMAC):
let symConfig = ClientAuthenticationMethodJWTSymmetric(
signatureAlgorithm: .hs256,
secretKey: "shared-secret-key"
) // Asymmetric:
val asym = ClientAuthenticationMethodConfiguration.SignedJwt.Asymmetric(
clientKeyStore = myClientKeyStore,
clientKeyStorePassword = "passphrase",
alias = "signing-key",
algorithmIdentifier =
ClientAuthenticationMethodConfiguration.SignedJwt.Asymmetric.AlgorithmIdentifier.ES256
)
// Symmetric:
val sym = ClientAuthenticationMethodConfiguration.SignedJwt.Symmetric(
secretKey = "shared-secret-key",
signatureAlgorithm =
ClientAuthenticationMethodConfiguration.SignedJwt.Symmetric.SignatureAlgorithm.HS256
) When configuring DCR fallback or setting useAttestation to false, the client authentication method must be set to one of the methods above — not the default None. Otherwise the flow fails before reaching the server.
How to implement this: Client Authentication (concept) · Dynamic Client Registration (DCR) · How to Configure DCR Fallback