
Standards-first WebAuthn and passkey building blocks: typed protocol models, strict validation, backend ceremony services, client orchestration, and modular transport, storage, crypto and attestation adapters.
Standards-first Kotlin Multiplatform building blocks for WebAuthn and passkey integrations.
This project helps teams implement passwordless login without rebuilding the hardest parts from scratch. It gives you typed protocol models, strict validation, backend ceremony services, platform passkey clients, and optional transport/adaptation modules that stay close to the WebAuthn specification.
Start with the mobile-first public documentation for Android, iOS, Compose, full-stack examples, and generated API reference entry points.
This repo focuses on those needs:
| Android | iOS |
|---|---|
WebAuthn has two ceremony pairs:
create)get)Each pair has a server start step and a server finish step, with the platform authenticator in the middle.
sequenceDiagram
autonumber
actor User
participant App as Client App
participant Auth as Platform Authenticator
participant RP as Relying Party Server
note over RP,App: Registration ceremony
App->>RP: registration/start request
RP-->>App: registration/start response (challenge + options)
App->>Auth: navigator.credentials.create / platform create
Auth-->>App: RegistrationResponse
App->>RP: registration/finish (credential response)
RP-->>App: verified registration
note over RP,App: Authentication ceremony
App->>RP: authentication/start request
RP-->>App: authentication/start response (challenge + options)
App->>Auth: navigator.credentials.get / platform get
Auth-->>App: AuthenticationResponse
App->>RP: authentication/finish (credential response)
RP-->>App: verified sign-inThe finish payload carries each credential response once. The server derives ceremony type, challenge,
and origin from its signed clientDataJSON; clients must not echo those values as independent claims.
Validation and trust decisions are server responsibilities: challenge/origin/type checks, authenticator
data rules, signature/attestation verification, counter handling, and policy decisions.
The repository follows a layered model that keeps protocol and validation concerns separate from transport and platform adapters.
flowchart TB
CLIENT["Client stack<br/>Shared orchestration and platform bridges"]
SERVER["JVM server stack<br/>Ceremonies, storage and HTTP adapters"]
CRYPTO["Cryptography boundary<br/>Crypto contracts and implementations"]
FOUNDATION["Shared foundation<br/>Validation, serialization and runtime"]
MODEL["Protocol model<br/>Typed WebAuthn contracts"]
CLIENT --> FOUNDATION
CLIENT --> MODEL
SERVER --> FOUNDATION
SERVER --> CRYPTO
CRYPTO --> FOUNDATION
FOUNDATION --> MODELThe overview shows logical responsibility areas rather than every Gradle dependency. See the architecture guide for the reference integration and focused core, client, and server dependency views.
core/ contains reusable protocol, validation, runtime, serialization, and crypto contracts.client/ contains typed platform operations, generic ceremony flow, platform bridges, Compose helpers, and client transport.server/ contains JVM server services, Ktor/store adapters, JVM crypto, and optional trust metadata.sample/ contains runnable samples and demo entry points; these modules are not published.docs/site/ contains the authored public documentation and site-specific assets; the build stages
verified repository docs and generated API reference alongside it.webauthn-runtime-core: shared coroutine/failure boundary helpers for adapters.webauthn-model: typed protocol/value contracts.webauthn-json-api: replaceable JSON codec boundary.webauthn-protocol: strict codec-neutral protocol interpretation.webauthn-core: standards-first ceremony validation.webauthn-client-core: typed platform operations, raw responses, and shared error mapping.webauthn-client-flow: state-free ceremony flow with opaque backend state.webauthn-client-ktor: codec-neutral Ktor backend transport with caller-owned engine and wire contract.webauthn-client-ktor-kotlinx: opt-in default /webauthn/* Kotlinx contract.webauthn-client-defaults: recommended platform composition with an explicit Kotlinx codec override seam.webauthn-client-compose: Compose integration.webauthn-client-prf-crypto: optional PRF-derived application cryptography.Most module READMEs follow this baseline structure (adapted per module when needed):
What it provides: the module's owned responsibilities.When to use: where it belongs in an integration.How to use: practical API snippets plus required caller responsibilities.How it fits in the system: dependency and data-flow context.Pitfalls/limits: common misuse patterns and intentional boundaries.Status: maturity and readiness signal.Recommended adoption paths:
model -> core -> crypto-api -> server-core-jvm (+ server-ktor if you want HTTP adapters).client-core -> client-flow -> platform bridge (+ client-compose for Compose UI).client-prf-crypto only when you need PRF-derived application crypto.The coordinated release train uses one version for the full published surface. JVM and Android dependency configurations can use the BOM; Kotlin Multiplatform common and Native source sets should put that same version on each artifact because Java Platform constraints are not available to Native variants.
repositories {
google()
mavenCentral()
}Use only the modules your app actually wires in. In Kotlin Multiplatform projects, shared modules belong in commonMain, while concrete platform bridges belong in the matching platform source set.
For the default Kotlinx backend contract and recommended Android/iOS platform composition, use
webauthn-client-flow plus webauthn-client-ktor-kotlinx in common code and
webauthn-client-defaults in each platform source set:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-flow:<version>")
implementation("io.github.szijpeter:webauthn-client-ktor-kotlinx:<version>")
}
androidMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-defaults:<version>")
}
iosMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-defaults:<version>")
}
}
}The app still creates its own Ktor HttpClient and engine. The defaults artifact selects the
Android JSON implementation and platform construction only; PasskeyFlow leaves presentation state
and backend exception policy application-owned.
Android hosts must also add a Credential Manager provider such as
androidx.credentials:credentials-play-services-auth; the WebAuthn client modules provide the API
bridge but deliberately leave provider-runtime selection to the application.
Use the lower-level modules when you supply your own WebAuthnJsonCodec, Ktor contract codec, or
platform construction. This dependency-pure consumer fixture deliberately does not resolve
webauthn-json-kotlinx through the neutral client modules:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-core:<version>")
implementation("io.github.szijpeter:webauthn-client-json-core:<version>")
implementation("io.github.szijpeter:webauthn-client-flow:<version>")
implementation("io.github.szijpeter:webauthn-client-ktor:<version>")
implementation("io.github.szijpeter:webauthn-json-api:<version>")
}
androidMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-platform:<version>")
}
iosMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-platform:<version>")
}
}
}JVM/Ktor server example:
dependencies {
implementation(platform("io.github.szijpeter:webauthn-bom:<version>"))
implementation("io.github.szijpeter:webauthn-server-core-jvm")
implementation("io.github.szijpeter:webauthn-server-jvm-crypto")
implementation("io.github.szijpeter:webauthn-server-ktor")
implementation("io.github.szijpeter:webauthn-server-store-exposed")
}Composition notes:
webauthn-server-* dependencies.webauthn-client-platform to each platform source set that instantiates a concrete platform client.commonMain only needs the common modules.sample/compose-passkey, sample/compose-passkey-android, and sample/compose-passkey-ios.Published to Maven Central (latest version is shown in the Maven Central badge above). Maintainers can still validate publication locally with:
./gradlew publishToMavenLocal --stacktraceUse:
webauthn-modelwebauthn-corewebauthn-crypto-apiwebauthn-server-jvm-cryptowebauthn-server-core-jvmwebauthn-server-ktor if you want route adapterswebauthn-server-store-exposed if you want an Exposed-backed store implementationUse:
webauthn-client-corewebauthn-client-flow for generic start/prompt/finish orchestrationwebauthn-client-json-core if you exchange raw JSON with a host/backendwebauthn-client-platformwebauthn-client-defaults for the recommended batteries-included platform setupwebauthn-client-compose for Compose helperswebauthn-client-prf-crypto for PRF-based key derivation and encryption helperswebauthn-client-ktor for codec-neutral Ktor backendswebauthn-client-ktor-kotlinx for the default /webauthn/* contractStart with:
sample/backend-ktorsample/compose-passkeysample/compose-passkey-iossample/passkey-cli for a macOS-first experimental native-authenticator CLI POCDesktop and CLI strategy notes for this repo live in docs/DESKTOP_CLI_STRATEGY.md.
| Module | Who it is for |
|---|---|
platform:bom |
Consumers who want aligned versions across published artifacts |
webauthn-cbor-core |
Parser/crypto modules needing strict low-level CBOR byte scanning primitives |
webauthn-model |
Teams that want typed WebAuthn models and value wrappers |
webauthn-json-api |
Teams selecting a JSON implementation without exposing serializer-specific types |
webauthn-protocol |
Teams interpreting raw WebAuthn binary protocol data without selecting a codec |
webauthn-runtime-core |
Shared coroutine-safe error/cancellation boundary helpers for adapter modules |
webauthn-json-kotlinx |
Teams mapping JSON/CBOR DTOs to typed models |
webauthn-core |
Teams validating ceremonies and authenticator data |
webauthn-crypto-api |
Teams plugging crypto/attestation implementations into validation and server flows |
webauthn-server-jvm-crypto |
JVM backends that want Signum-first hashing, signature, and attestation verification |
webauthn-server-core-jvm |
JVM backends that need registration/authentication ceremony services |
webauthn-server-ktor |
Ktor backends that want ready-made WebAuthn routes |
webauthn-server-store-exposed |
JVM backends storing WebAuthn state through Exposed |
webauthn-client-core |
Apps and adapters that need typed platform operations, raw credential responses, capabilities, and shared error mapping |
webauthn-client-flow |
Apps coordinating backend start/finish with opaque continuation state and application-defined output |
webauthn-client-ktor |
Apps adapting generic flow backends to Ktor while owning the engine and wire codec |
webauthn-client-ktor-kotlinx |
Apps using the repository's default /webauthn/* Kotlinx contract |
webauthn-client-json-core |
Apps or SDKs that need raw JSON interoperability on top of typed clients |
webauthn-client-compose |
Compose apps that want lifecycle-aware platform clients and remembered generic flows while retaining application-owned UI state |
webauthn-client-platform |
Android apps using Credential Manager or iOS apps using AuthenticationServices |
webauthn-client-defaults |
Apps that want the recommended platform setup with Kotlinx defaults and an explicit codec override |
webauthn-client-prf-crypto |
Client apps deriving crypto sessions from WebAuthn PRF extension outputs |
webauthn-attestation-mds |
Backends that want optional FIDO Metadata Service trust anchors |
This repository is publicly released and still pre-1.0.
Current state:
PasskeyFlow orchestration and raw platform responses.kotlinx-serialization is now on 1.10.0 together with Signum 0.12.0 and indispensable 3.20.0; captured Android assertion-vector regressions are green on this combined dependency set.SECURITY.md.docs/PUBLIC_LAUNCH_CHECKLIST.md.docs/MAVEN_CENTRAL.md.Renovate.tools/agent/setup-hooks.sh
tools/agent/quality-gate.sh --mode fast --scope changed --block false
tools/agent/quality-gate.sh --mode strict --scope changed --block false
./gradlew apiCheck --stacktrace
./gradlew publishToMavenLocal --stacktracedocs/wiki/README.mddocs/CLIENT_FIRST_EXECUTION.mddocs/CLIENT_API_BENCHMARKS.mddocs/IMPLEMENTATION_STATUS.mddocs/ROADMAP.mddocs/ai/STEERING.mdLicense: Apache-2.0. See LICENSE.
Standards-first Kotlin Multiplatform building blocks for WebAuthn and passkey integrations.
This project helps teams implement passwordless login without rebuilding the hardest parts from scratch. It gives you typed protocol models, strict validation, backend ceremony services, platform passkey clients, and optional transport/adaptation modules that stay close to the WebAuthn specification.
Start with the mobile-first public documentation for Android, iOS, Compose, full-stack examples, and generated API reference entry points.
This repo focuses on those needs:
| Android | iOS |
|---|---|
WebAuthn has two ceremony pairs:
create)get)Each pair has a server start step and a server finish step, with the platform authenticator in the middle.
sequenceDiagram
autonumber
actor User
participant App as Client App
participant Auth as Platform Authenticator
participant RP as Relying Party Server
note over RP,App: Registration ceremony
App->>RP: registration/start request
RP-->>App: registration/start response (challenge + options)
App->>Auth: navigator.credentials.create / platform create
Auth-->>App: RegistrationResponse
App->>RP: registration/finish (credential response)
RP-->>App: verified registration
note over RP,App: Authentication ceremony
App->>RP: authentication/start request
RP-->>App: authentication/start response (challenge + options)
App->>Auth: navigator.credentials.get / platform get
Auth-->>App: AuthenticationResponse
App->>RP: authentication/finish (credential response)
RP-->>App: verified sign-inThe finish payload carries each credential response once. The server derives ceremony type, challenge,
and origin from its signed clientDataJSON; clients must not echo those values as independent claims.
Validation and trust decisions are server responsibilities: challenge/origin/type checks, authenticator
data rules, signature/attestation verification, counter handling, and policy decisions.
The repository follows a layered model that keeps protocol and validation concerns separate from transport and platform adapters.
flowchart TB
CLIENT["Client stack<br/>Shared orchestration and platform bridges"]
SERVER["JVM server stack<br/>Ceremonies, storage and HTTP adapters"]
CRYPTO["Cryptography boundary<br/>Crypto contracts and implementations"]
FOUNDATION["Shared foundation<br/>Validation, serialization and runtime"]
MODEL["Protocol model<br/>Typed WebAuthn contracts"]
CLIENT --> FOUNDATION
CLIENT --> MODEL
SERVER --> FOUNDATION
SERVER --> CRYPTO
CRYPTO --> FOUNDATION
FOUNDATION --> MODELThe overview shows logical responsibility areas rather than every Gradle dependency. See the architecture guide for the reference integration and focused core, client, and server dependency views.
core/ contains reusable protocol, validation, runtime, serialization, and crypto contracts.client/ contains typed platform operations, generic ceremony flow, platform bridges, Compose helpers, and client transport.server/ contains JVM server services, Ktor/store adapters, JVM crypto, and optional trust metadata.sample/ contains runnable samples and demo entry points; these modules are not published.docs/site/ contains the authored public documentation and site-specific assets; the build stages
verified repository docs and generated API reference alongside it.webauthn-runtime-core: shared coroutine/failure boundary helpers for adapters.webauthn-model: typed protocol/value contracts.webauthn-json-api: replaceable JSON codec boundary.webauthn-protocol: strict codec-neutral protocol interpretation.webauthn-core: standards-first ceremony validation.webauthn-client-core: typed platform operations, raw responses, and shared error mapping.webauthn-client-flow: state-free ceremony flow with opaque backend state.webauthn-client-ktor: codec-neutral Ktor backend transport with caller-owned engine and wire contract.webauthn-client-ktor-kotlinx: opt-in default /webauthn/* Kotlinx contract.webauthn-client-defaults: recommended platform composition with an explicit Kotlinx codec override seam.webauthn-client-compose: Compose integration.webauthn-client-prf-crypto: optional PRF-derived application cryptography.Most module READMEs follow this baseline structure (adapted per module when needed):
What it provides: the module's owned responsibilities.When to use: where it belongs in an integration.How to use: practical API snippets plus required caller responsibilities.How it fits in the system: dependency and data-flow context.Pitfalls/limits: common misuse patterns and intentional boundaries.Status: maturity and readiness signal.Recommended adoption paths:
model -> core -> crypto-api -> server-core-jvm (+ server-ktor if you want HTTP adapters).client-core -> client-flow -> platform bridge (+ client-compose for Compose UI).client-prf-crypto only when you need PRF-derived application crypto.The coordinated release train uses one version for the full published surface. JVM and Android dependency configurations can use the BOM; Kotlin Multiplatform common and Native source sets should put that same version on each artifact because Java Platform constraints are not available to Native variants.
repositories {
google()
mavenCentral()
}Use only the modules your app actually wires in. In Kotlin Multiplatform projects, shared modules belong in commonMain, while concrete platform bridges belong in the matching platform source set.
For the default Kotlinx backend contract and recommended Android/iOS platform composition, use
webauthn-client-flow plus webauthn-client-ktor-kotlinx in common code and
webauthn-client-defaults in each platform source set:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-flow:<version>")
implementation("io.github.szijpeter:webauthn-client-ktor-kotlinx:<version>")
}
androidMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-defaults:<version>")
}
iosMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-defaults:<version>")
}
}
}The app still creates its own Ktor HttpClient and engine. The defaults artifact selects the
Android JSON implementation and platform construction only; PasskeyFlow leaves presentation state
and backend exception policy application-owned.
Android hosts must also add a Credential Manager provider such as
androidx.credentials:credentials-play-services-auth; the WebAuthn client modules provide the API
bridge but deliberately leave provider-runtime selection to the application.
Use the lower-level modules when you supply your own WebAuthnJsonCodec, Ktor contract codec, or
platform construction. This dependency-pure consumer fixture deliberately does not resolve
webauthn-json-kotlinx through the neutral client modules:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-core:<version>")
implementation("io.github.szijpeter:webauthn-client-json-core:<version>")
implementation("io.github.szijpeter:webauthn-client-flow:<version>")
implementation("io.github.szijpeter:webauthn-client-ktor:<version>")
implementation("io.github.szijpeter:webauthn-json-api:<version>")
}
androidMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-platform:<version>")
}
iosMain.dependencies {
implementation("io.github.szijpeter:webauthn-client-platform:<version>")
}
}
}JVM/Ktor server example:
dependencies {
implementation(platform("io.github.szijpeter:webauthn-bom:<version>"))
implementation("io.github.szijpeter:webauthn-server-core-jvm")
implementation("io.github.szijpeter:webauthn-server-jvm-crypto")
implementation("io.github.szijpeter:webauthn-server-ktor")
implementation("io.github.szijpeter:webauthn-server-store-exposed")
}Composition notes:
webauthn-server-* dependencies.webauthn-client-platform to each platform source set that instantiates a concrete platform client.commonMain only needs the common modules.sample/compose-passkey, sample/compose-passkey-android, and sample/compose-passkey-ios.Published to Maven Central (latest version is shown in the Maven Central badge above). Maintainers can still validate publication locally with:
./gradlew publishToMavenLocal --stacktraceUse:
webauthn-modelwebauthn-corewebauthn-crypto-apiwebauthn-server-jvm-cryptowebauthn-server-core-jvmwebauthn-server-ktor if you want route adapterswebauthn-server-store-exposed if you want an Exposed-backed store implementationUse:
webauthn-client-corewebauthn-client-flow for generic start/prompt/finish orchestrationwebauthn-client-json-core if you exchange raw JSON with a host/backendwebauthn-client-platformwebauthn-client-defaults for the recommended batteries-included platform setupwebauthn-client-compose for Compose helperswebauthn-client-prf-crypto for PRF-based key derivation and encryption helperswebauthn-client-ktor for codec-neutral Ktor backendswebauthn-client-ktor-kotlinx for the default /webauthn/* contractStart with:
sample/backend-ktorsample/compose-passkeysample/compose-passkey-iossample/passkey-cli for a macOS-first experimental native-authenticator CLI POCDesktop and CLI strategy notes for this repo live in docs/DESKTOP_CLI_STRATEGY.md.
| Module | Who it is for |
|---|---|
platform:bom |
Consumers who want aligned versions across published artifacts |
webauthn-cbor-core |
Parser/crypto modules needing strict low-level CBOR byte scanning primitives |
webauthn-model |
Teams that want typed WebAuthn models and value wrappers |
webauthn-json-api |
Teams selecting a JSON implementation without exposing serializer-specific types |
webauthn-protocol |
Teams interpreting raw WebAuthn binary protocol data without selecting a codec |
webauthn-runtime-core |
Shared coroutine-safe error/cancellation boundary helpers for adapter modules |
webauthn-json-kotlinx |
Teams mapping JSON/CBOR DTOs to typed models |
webauthn-core |
Teams validating ceremonies and authenticator data |
webauthn-crypto-api |
Teams plugging crypto/attestation implementations into validation and server flows |
webauthn-server-jvm-crypto |
JVM backends that want Signum-first hashing, signature, and attestation verification |
webauthn-server-core-jvm |
JVM backends that need registration/authentication ceremony services |
webauthn-server-ktor |
Ktor backends that want ready-made WebAuthn routes |
webauthn-server-store-exposed |
JVM backends storing WebAuthn state through Exposed |
webauthn-client-core |
Apps and adapters that need typed platform operations, raw credential responses, capabilities, and shared error mapping |
webauthn-client-flow |
Apps coordinating backend start/finish with opaque continuation state and application-defined output |
webauthn-client-ktor |
Apps adapting generic flow backends to Ktor while owning the engine and wire codec |
webauthn-client-ktor-kotlinx |
Apps using the repository's default /webauthn/* Kotlinx contract |
webauthn-client-json-core |
Apps or SDKs that need raw JSON interoperability on top of typed clients |
webauthn-client-compose |
Compose apps that want lifecycle-aware platform clients and remembered generic flows while retaining application-owned UI state |
webauthn-client-platform |
Android apps using Credential Manager or iOS apps using AuthenticationServices |
webauthn-client-defaults |
Apps that want the recommended platform setup with Kotlinx defaults and an explicit codec override |
webauthn-client-prf-crypto |
Client apps deriving crypto sessions from WebAuthn PRF extension outputs |
webauthn-attestation-mds |
Backends that want optional FIDO Metadata Service trust anchors |
This repository is publicly released and still pre-1.0.
Current state:
PasskeyFlow orchestration and raw platform responses.kotlinx-serialization is now on 1.10.0 together with Signum 0.12.0 and indispensable 3.20.0; captured Android assertion-vector regressions are green on this combined dependency set.SECURITY.md.docs/PUBLIC_LAUNCH_CHECKLIST.md.docs/MAVEN_CENTRAL.md.Renovate.tools/agent/setup-hooks.sh
tools/agent/quality-gate.sh --mode fast --scope changed --block false
tools/agent/quality-gate.sh --mode strict --scope changed --block false
./gradlew apiCheck --stacktrace
./gradlew publishToMavenLocal --stacktracedocs/wiki/README.mddocs/CLIENT_FIRST_EXECUTION.mddocs/CLIENT_API_BENCHMARKS.mddocs/IMPLEMENTATION_STATUS.mddocs/ROADMAP.mddocs/ai/STEERING.mdLicense: Apache-2.0. See LICENSE.