Skip to content

Commit

Permalink
Release 1.0.0
Browse files Browse the repository at this point in the history
- First stable release
- Improved documentation
  • Loading branch information
emlun committed Feb 12, 2019
2 parents 5ef8581 + fe56a7b commit 42f5a2d
Show file tree
Hide file tree
Showing 9 changed files with 715 additions and 18 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
language: java

branches:
except:
- tmp

env:
global:
secure: sX5sJd2EUgzIT7uQN0YxA3faVHymBG/QPZ/St5IPqoQIXjZAMYBM0D1MrVOYaSOhgVKOJt+5vwCYU7MlY9Ha0rUPJgUPT+6CkVgUVCsQ1e8srAzaYp4ceIYaW2XpUIwhKHPBezulV3nLANRs0FibEN+eqTgL5A/qKtsU49BtQ1iUAVFFOzGcR48avo1UYxS0FLw+7MRLgH5NA6KJVHiGChx9P3oLYAhPylgDzRv6iFf5H5v9azQI4eLo6bSQwm++j0UpH4t8m+at7eGuzNsadYY0M9SoUwuJxQZiwtImYJJtGJD92QtV9m+yny4+RocXchgZDj3e9vx06ZqXaeF3U3o49YUX5ACerVV12yOxGZsuuxfevaQa9Mk4xEOwGkhva5I+8vfo8MRxm7ymelExn25zpsMlmj6GjBio3z1q/FGYdyXrcGoVNrvAgozs+0yW2jYtDVo7DNu8J2mur/C/gmi+xA6rkuEJQIQ3hWuWYVe7DUzdii5MG9/9AdwI14b3uyezh1EJ8tza5MScDQijTvD9sGxarruKS59VuJapqrJSU5E87CnlU6gQx7qXJVGvpTXZOw7ZzsdszSDQ3Jc9uNBSdtBQ2i7egEyTE+RQWsdtje/H0s3ZYyIw8qrQ1kIUDQKk7jl8Uvwf+zn/36JBgZMVIIO0hmDFnyB9wBGd7lk=
Expand Down
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
== Version 1.0.0 ==

* Fixed URL in artifact POM
* Improved a few javadoc wordings


== Version 0.8.0 ==
Expand Down
297 changes: 286 additions & 11 deletions README
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
== java-webauthn-server

_Note: This is a work in progress. The https://www.w3.org/TR/webauthn/[Web
Authentication standard] is not yet finished, and additional pre-1.0 releases of
this library may introduce breaking API changes._
java-webauthn-server
====================
:toc:
:toc-placement: macro
:toc-title:

image:https://travis-ci.org/Yubico/java-webauthn-server.svg?branch=master["Build Status", link="https://travis-ci.org/Yubico/java-webauthn-server"]
image:https://coveralls.io/repos/github/Yubico/java-webauthn-server/badge.svg["Coverage Status", link="https://coveralls.io/github/Yubico/java-webauthn-server"]
Expand All @@ -14,18 +14,293 @@ for a server to support Web Authentication. This includes registering
authenticators and authenticating registered authenticators.


=== Planned breaking changes
== Table of contents

toc::[]


== Dependency configuration

Maven:

----------
<dependency>
<groupId>com.yubico</groupId>
<artifactId>webauthn-server-core</artifactId>
<version>1.0.0-RC2</version>
<scope>compile</scope>
</dependency>
----------

Gradle:

----------
compile 'com.yubico:webauthn-server-core:1.0.0-RC2'
----------


== Features

- Generates request objects suitable as parameters to
`navigator.credentials.create()` and `.get()`
- Performs all necessary
https://www.w3.org/TR/webauthn/#rp-operations[validation logic] on the
response from the client
- Optionally integrates with a "metadata service" to verify
https://www.w3.org/TR/webauthn/#sctn-attestation[authenticator attestations]
and annotate responses with additional authenticator metadata


=== Non-features

This library has no concept of accounts, sessions, permissions or identity
federation, and it's not an authentication framework; it only deals with
executing the WebAuthn authentication mechanism. Sessions, account management
and other higher level concepts can make use of this authentication mechanism,
but the authentication mechanism alone does not make a security system.


== Documentation

See the
link:https://yubico.github.io/java-webauthn-server/webauthn-server-core/com/yubico/webauthn/package-summary.html[Javadoc]
for in-depth API documentation.


== Quick start

Implement the
link:https://yubico.github.io/java-webauthn-server/webauthn-server-core/com/yubico/webauthn/CredentialRepository.html[`CredentialRepository`]
interface with your database access logic. See
link:https://github.com/Yubico/java-webauthn-server/blob/master/webauthn-server-demo/src/main/java/demo/webauthn/InMemoryRegistrationStorage.java[`InMemoryRegistrationStorage`]
for an example.

Instantiate the
link:https://yubico.github.io/java-webauthn-server/webauthn-server-core/com/yubico/webauthn/RelyingParty.html[`RelyingParty`]
class:

[source,java]
----------
RelyingPartyIdentity rpIdentity = RelyingPartyIdentity.builder()
.id("example.com")
.name("Example Application")
.build();

RelyingParty rp = RelyingParty.builder()
.identity(rpIdentity)
.credentialRepository(new MyCredentialRepository())
.build();
----------


=== Registration

Initiate a registration ceremony:

[source,java]
----------
byte[] userHandle = new byte[64];
random.nextBytes(userHandle);

PublicKeyCredentialCreationOptions request = rp.startRegistration(StartRegistrationOptions.builder()
.user(UserIdentity.builder()
.name("alice")
.displayName("Alice Hypothetical")
.id(new ByteArray(userHandle))
.build())
.build());
----------

Serialize `request` to JSON and send it to the client:

[source,java]
----------
import com.fasterxml.jackson.databind.ObjectMapper;

ObjectMapper jsonMapper = new ObjectMapper()
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.setSerializationInclusion(Include.NON_ABSENT)
.registerModule(new Jdk8Module());

String json = jsonMapper.writeValueAsString(request);
return json;
----------

Get the response from the client:

[source,java]
----------
String responseJson = /* ... */;
PublicKeyCredential<AuthenticatorAttestationResponse, ClientRegistrationExtensionOutputs> pkc =
jsonMapper.readValue(responseJson, new TypeReference<PublicKeyCredential<AuthenticatorAttestationResponse, ClientRegistrationExtensionOutputs>>(){});
----------

Validate the response:

[source,java]
----------
try {
RegistrationResult result = rp.finishRegistration(FinishRegistrationOptions.builder()
.request(request)
.response(pkc)
.build());
} catch (RegistrationFailedException e) { /* ... */ }
----------

Update your database:

[source,java]
----------
storeCredential("alice", result.getKeyId(), result.getPublicKeyCose());
----------


=== Authentication

Initiate an authentication ceremony:


[source,java]
----------
AssertionRequest request = rp.startAssertion(StartAssertionOptions.builder()
.username(Optional.of("alice"))
.build());
String json = jsonMapper.writeValueAsString(request);
return json;
----------

Validate the response:

[source,java]
----------
String responseJson = /* ... */;

PublicKeyCredential<AuthenticatorAssertionResponse, ClientAssertionExtensionOutputs> pkc =
jsonMapper.readValue(responseJson, new TypeReference<PublicKeyCredential<AuthenticatorAssertionResponse, ClientAssertionExtensionOutputs>>() {
});

try {
AssertionResult result = rp.finishAssertion(FinishAssertionOptions.builder()
.request(request)
.response(pkc)
.build());

if (result.isSuccess()) {
return result.getUsername();
}
} catch (AssertionFailedException e) { /* ... */ }
throw new RuntimeException("Authentication failed");
----------

For more detailed example usage, see
link:webauthn-server-demo[`webauthn-server-demo`] for a complete demo server.


== Architecture

The library tries to place as few requirements on the overall application
architecture as possible. For this reason it is stateless and free from side
effects, and does not directly interact with any database. This means it is
database agnostic and thread safe. The following diagram illustrates an example
architecture for an application using the library.

image::https://raw.githubusercontent.com/Yubico/java-webauthn-server/master/docs/img/demo-architecture.svg["Example application architecture",align="center"]

The application manages all state and database access, and communicates with the
library via POJO representations of requests and responses. The following
diagram illustrates the data flow during a WebAuthn registration or
authentication ceremony.

image::https://raw.githubusercontent.com/Yubico/java-webauthn-server/master/docs/img/demo-sequence-diagram.svg["WebAuthn ceremony sequence diagram",align="center"]

In this diagram, the *Client* is the user's browser and the application's
client-side scripts. The *Server* is the application and its business logic, the
*Library* is this library, and the *Users* database stores registered WebAuthn
credentials.

. The client requests to start the ceremony, for example by submitting a form.
The `username` may or may not be known at this point. For example, the user
might be requesting to create a new account, or we might be using
username-less authentication.

. If the user does not already have a
https://www.w3.org/TR/webauthn/#user-handle[user handle], the application
creates one in some application-specific way.

. The application may choose to authenticate the user with a password or the
like before proceeding.

. The application calls one of the library's "start" methods to generate a
parameter object to be passed to `navigator.credentials.create()` or `.get()`
on the client.

. The library generates a random challenge and an assortment of other arguments
depending on configuration set by the application.

. If the `username` is known, the library uses a read-only database adapter
provided by the application to look up the user's credentials.

. The returned list of https://www.w3.org/TR/webauthn/#credential-id[credential
IDs] is used to populate the
https://www.w3.org/TR/webauthn/#dom-publickeycredentialcreationoptions-excludecredentials[`excludeCredentials`]
or
https://www.w3.org/TR/webauthn/#dom-publickeycredentialrequestoptions-allowcredentials[`allowCredentials`]
parameter.

. The library returns a `request` object which can be serialized to JSON and
passed as the `publicKey` argument to `navigator.credentials.create()` or
`.get()`. For registration ceremonies this will be a
https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialcreationoptions[`PublicKeyCredentialCreationOptions`],
and for authentication ceremonies it will be a
https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialrequestoptions[`PublicKeyCredentialRequestOptions`].
The application stores the `request` in temporary storage.

. The application's client-side script runs `navigator.credentials.create()` or
`.get()` with `response` as the `publicKey` argument.

. The user confirms the operation and the client returns a
https://www.w3.org/TR/webauthn/#public-key-credential[`PublicKeyCredential`]
object `response` to the application.

. The application retrieves the `request` from temporary storage and passes
`request` and `response` to one of the library's "finish" methods to run the
response validation logic.

. The library verifies that the `response` contents - challenge, origin, etc. -
are valid.

. If this is an authentication ceremony, the library uses the database adapter
to look up the public key for the credential named in `response.id`.

. The database adapter returns the public key.

. The library verifies the authentication signature.

. The library returns a POJO representation of the result of the ceremony. For
registration ceremonies, this will include the credential ID and public key of
the new credential. The application may also opt in to also getting
information about the authenticator model and whether the authenticator
attestation is trusted. For authentication ceremonies, this will include the
username and user handle, the credential ID of the credential used, and the
new https://www.w3.org/TR/webauthn/#signature-counter[signature counter] value
for the credential.

. The application inspects the result object and takes any appropriate actions
as defined by its business logic.

None.
. If the result is not satisfactory, the application reports failure to the
client.

. If the result is satisfactory, the application proceeds with storing the new
credential if this is a registration ceremony.

=== Example Usage
. If this is an authentication ceremony, the application updates the signature
counter stored in the database for the credential.

See link:webauthn-server-demo[`webauthn-server-demo`] for a complete demo
server, which stores authenticator registrations temporarily in memory.
. Finally, the application reports success and resumes its business logic.


=== Building
== Building

Use the included
https://docs.gradle.org/current/userguide/gradle_wrapper.html[Gradle wrapper] to
Expand Down
Loading

0 comments on commit 42f5a2d

Please sign in to comment.