webauthn4j: server side passkey verification in Java, with reproducible builds
A portable Java library for WebAuthn(Passkeys) server side verification
At a glance
- What is it?
- WebAuthn4J is a Java library for verifying WebAuthn and passkey registration and authentication responses on the server, with every attestation statement format supported and conformance against the FIDO Alliance test tools. It is also one of the few libraries whose release artifacts you can rebuild byte for byte and compare against Maven Central.
- Who is it for?
- Adopt webauthn4j if you are adding passkeys to a Java or JVM backend and you want the verification rules, the attestation handling and the FIDO conformance already done for you, rather than assembling them from the specification yourself. Do not adopt it if you need a client side or browser side WebAuthn implementation, since this is the server half only.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The server half of passkeys, and the conformance claim
WebAuthn4J is described as a portable Java library for WebAuthn, that is passkeys, server side verification, and the word portable covers both the deployment and the usage. The conformance statement is specific rather than decorative. All mandatory test cases and the optional Android Key attestation test cases of the FIDO2 Test Tools provided by the FIDO Alliance are passed, which is the functional certification suite rather than a self-written test corpus. That matters because WebAuthn verification is where the subtle failures live, in origin checking, in challenge freshness, in the attestation chain and in the extensions, and a library that passes the alliance test tools has been through the cases that catch those. The library is written in Java but is described as Kotlin friendly, since public members are marked with NotNull or Nullable annotations to declare nullability explicitly, which matters when the consumer is Kotlin and the nullability contract is enforced by the compiler.
Every attestation statement format is supported
The README states that all attestation statement formats are supported, and then lists them: Packed attestation, FIDO U2F attestation, Android Key attestation, Android SafetyNet attestation, TPM attestation, Apple Anonymous attestation, None attestation and Apple App Attest attestation. The spread tells you what the library is built for, since that list covers hardware authenticators from different eras, phone platform attestation, Windows hardware, Apple platform services and the no attestation case. The None format deserves attention because it is the one that carries no cryptographic evidence of the authenticator, which is a policy decision for the relying party rather than a technical failure. Apple App Attest is a different flow from WebAuthn proper, and the README points to the reference documentation for verifying it, so the library reaches into adjacent verification problems rather than stopping at the FIDO boundary.
Maven Central coordinates and a Java 17 floor
The library is published to Maven Central and the README shows the dependency block to copy into a Maven project, with the version held in a property so it can be bumped in one place:
<properties>
...
<!-- Use the latest version whenever possible. -->
<webauthn4j.version>0.31.11.RELEASE</webauthn4j.version>
...
</properties>
<dependencies>
...
<dependency>
<groupId>com.webauthn4j</groupId>
<artifactId>webauthn4j-core</artifactId>
<version>${webauthn4j.version}</version>
</dependency>
...
</dependencies>The prerequisite for using the library at all is Java 17 or later, which is a consequence of the project being written for modern JVMs rather than an arbitrary choice. The build itself is Gradle based, and the wrapper is invoked from the root of the source tree, where the README explains that gradlew serves as a cross-platform, self-contained bootstrap mechanism for the build, so you do not need Gradle installed. The core artifact is the one to depend on, with the other modules in the tree being optional pieces around it.
Reproducible builds you can check with a script
The project states that it is committed to software supply chain security and that all release artifacts support reproducible builds, meaning you can rebuild from source and verify the result is bit-for-bit identical to the artifacts published on Maven Central. The exact JDK version used for each release is listed in the release notes, and the build pins it through a toolchain parameter:
git clone https://github.com/webauthn4j/webauthn4j.git
cd webauthn4j
git checkout <VERSION>.RELEASE
./gradlew jar -PtoolchainJdkVersion=<JDK_VERSION>The comparison itself is a shell script that walks the built jars, computes a SHA-256 for each, fetches the same artifact from Maven Central and compares the two hashes, printing MATCH or MISMATCH per module, and the README states that all modules should show MATCH. For a library that verifies authentication ceremonies, being able to confirm that the bytecode you run is the bytecode that was published is a stronger guarantee than a signature over a checksum, and it is unusual to see the verification procedure shipped in the README.
Registration is parse, verify, persist
The usage section shows the flow rather than describing it, and the first block is the registration path. The JSON string comes from the front end, it is parsed into a registration data object, and the parse can fail with a DataConversionException that the code catches and rethrows, which the comment explains is there for applications that want to handle a malformed WebAuthn structure themselves:
String registrationResponseJSON = "<registrationResponseJSON>"; /* set registrationResponseJSON received from frontend */
RegistrationData registrationData;
try {
registrationData = webAuthnManager.parseRegistrationResponseJSON(registrationResponseJSON);
} catch (DataConversionException e) {
// If you would like to handle WebAuthn data structure parse error, please catch DataConversionException
throw e;
}
// Server properties
Origin origin = null /* set origin */;
String rpId = null /* set rpId */;
Challenge challenge = null /* set challenge */;
byte[] tokenBindingId = null /* set tokenBindingId */;
ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, tokenBindingId);The server property is the security boundary of the whole flow, since the origin, the relying party id and the challenge are what the library checks the response against. The expectations object adds the acceptable credential types, whether user verification is required, which defaults to false, and whether user presence is required, which defaults to true. The verification call throws a VerificationException on failure, and then the code builds a credential record from the attestation object, the collected client data, the client extensions and the transports, and persists it, with a comment that instructs you to persist it because it is used later in the authentication process.
The module split and the build plugins behind it
The repository tree shows a library that is split along the lines of its optional features rather than along convenience. There is webauthn4j-core for the verification logic, webauthn4j-core-async for an asynchronous variant, webauthn4j-metadata and webauthn4j-metadata-async for authenticator metadata, webauthn4j-appattest for the Apple App Attest support, webauthn4j-util and webauthn4j-test, plus an integration-tests directory. The build directory is as interesting as the source. There is a buildSrc/ directory and four custom Gradle plugins in the tree, optional-dependencies-plugin, maven-central-publish-plugin, test-with-security-provider-plugin and toolchain-pinning-plugin, and the last two are the ones that back the reproducibility claim, since pinning the toolchain and running the tests against a specific security provider are exactly the two things that otherwise make a build non-deterministic. The project is published to Maven Central from this build, and the jitpack.yml file shows it is also consumable through JitPack.
Who depends on it, and how often it ships
The list of projects using WebAuthn4J is a strong adoption signal, and it is a mix of frameworks and products. Keycloak and the Red Hat build of Keycloak use it, as does Quarkus Security, and Spring Security provides passkeys support in its spring-security-web module, maintained by the Spring Security project rather than by this one. WebAuthn4J also ships its own Spring Security extension, maintained by the WebAuthn4J project, and Eclipse Vert.x Auth, OpenAM and OpenUnison are listed as users. Two things follow from that arrangement. First, the library is a de facto dependency of a large part of the JVM identity ecosystem, so stability matters more here than novelty. Second, the release cadence is monthly rather than occasional, with 0.31.9.RELEASE on 2026-08-01, 0.31.10.RELEASE on 2026-09-01 and 0.31.11.RELEASE on 2026-10-02, the last push was on 2026-10-20, and the licence is Apache 2.0 with the full text in LICENSE.txt.
Editorial conclusion
Adopt webauthn4j if you are adding passkeys to a Java or JVM backend and you want the verification rules, the attestation handling and the FIDO conformance already done for you, rather than assembling them from the specification yourself. Do not adopt it if you need a client side or browser side WebAuthn implementation, since this is the server half only. Verify first that you are on Java 17 or later, that you understand what your authenticator attestation says about the device before you trust a key, and that you persist the CredentialRecord the library hands you, because the README is explicit that the credential record is what the authentication step later relies on.
Frequently asked questions
What is WebAuthn4J?
It is a portable Java library for server side WebAuthn, that is passkey, verification. It parses and validates registration and authentication responses, and it passes all mandatory test cases and the optional Android Key attestation cases of the FIDO Alliance FIDO2 Test Tools.
Which attestation statement formats does WebAuthn4J support?
All of them, according to the README: Packed, FIDO U2F, Android Key, Android SafetyNet, TPM, Apple Anonymous, None and Apple App Attest attestation. Verification of Apple App Attest is documented separately in the reference documentation.
How do I add WebAuthn4J to a Maven project?
Add the webauthn4j-core dependency with the groupId com.webauthn4j, keeping the version in a webauthn4j.version property as the README does. The library requires Java 17 or later.
Can I verify that the published jar matches the source?
Yes. The project supports reproducible builds, and the README gives a script that rebuilds the jars with a pinned toolchain via toolchainJdkVersion, computes a SHA-256 for each and compares it with the artifact downloaded from Maven Central, printing MATCH or MISMATCH per module.
What must my server keep after a successful registration?
The credential record, built from the attestation object, the collected client data, the client extensions and the transports, and the README comments instruct you to persist it because it is used later in the authentication process.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/webauthn4j-webauthn4j)Was this useful?