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.

Was this helpful?