documentation

This commit is contained in:
Robur 2021-10-06 11:57:42 +00:00
parent d926cf90b2
commit 78be1d42df
3 changed files with 165 additions and 3 deletions

View file

@ -0,0 +1,29 @@
## WebAuthn - authenticating users to services using public key cryptography
WebAuthn is a web standard published by the W3C. Its goal is to
standardize an interfacefor authenticating users to web-based
applications and services using public key cryptography. Modern web
browsers support WebAuthn functionality.
WebAuthn provides two funcitons: register and authenticate. Usually the
public and private keypair is stored on an external token (Yuikey etc.)
or part of the platform (TPM). After the public key is registered, it can
be used to authenticate to the same service.
This module does not preserve a database of registered public keys, their
credential ID, usernames and pending challenges - instead this data must
be stored by a client of this API in a database or other persistent
storage.
[WebAuthn specification at W3C](https://w3c.github.io/webauthn/)
A basic demonstration server is provided (`bin/webauthn_demo`),
running at [webauthn-demo.robur.coop](https://webauthn-demo.robur.coop).
## Documentation
[API documentation](https://roburio.github.io/webauthn/doc) is available online.
## Installation
`opam install webauthn` will install this library.

View file

@ -1,11 +1,48 @@
(** WebAuthn - authenticating users to services using public key cryptography
WebAuthn is a web standard published by the W3C. Its goal is to
standardize an interfacefor authenticating users to web-based
applications and services using public key cryptography. Modern web
browsers support WebAuthn functionality.
WebAuthn provides two funcitons: register and authenticate. Usually the
public and private keypair is stored on an external token (Yuikey etc.)
or part of the platform (TPM). After the public key is registered, it can
be used to authenticate to the same service.
This module implements at the moment only "fido-u2f" and "none"
attestations with P256 keys.
A common use of this module is that on startup a {!t} is created (using
{!create}). A public key can then be registered ({!register}) with a server
generated {!challenge}. When this is successfull, the client can be
authenticated {!authenticate}.
This module does not preserve a database of registered public keys, their
credential ID, usernames and pending challenges - instead this data must
be stored by a client of this API in a database or other persistent
storage.
{{:https://w3c.github.io/webauthn/}WebAuthn specification at W3C.}
*)
(** The type of a webauthn state, containing the [origin]. *)
type t
(** [create origin] is a webauthn state, or an error if the origin does not
meet the specification (schema must be https, the host must be a valid
hostname. An optional port is supported: https://example.com:4444 *)
val create : string -> (t, string) result
(** [rpid t] is the relying party ID. Specifically, it is the effective domain
of the origin. Using registrable domain suffix as the relying party ID is
currently unsupported. *)
val rpid : t -> string
(** The type os json decoding errors: context, message, and data. *)
type json_decoding_error = [ `Json_decoding of string * string * string ]
(** The variant of decoding errors with the various encoding formats. *)
type decoding_error = [
json_decoding_error
| `Base64_decoding of string * string * string
@ -15,6 +52,7 @@ type decoding_error = [
| `Attestation_object_decoding of string * string * string
]
(** The variant of errors. *)
type error = [
decoding_error
| `Unsupported_key_type of int
@ -29,24 +67,38 @@ type error = [
| `Signature_verification of string
]
(** [pp_error ppf e] pretty-prints the error [e] on [ppf]. *)
val pp_error : Format.formatter -> [< error ] -> unit
(** The abstract type of challenges. *)
type challenge
(** [generate_challenge ~size ()] generates a new challenge, and returns a pair
of the challenge and its Base64 URI safe encoding.
@raise Invalid_argument if size is smaller than 16. *)
val generate_challenge : ?size:int -> unit -> challenge * string
(** [challenge_to_string c] is a string representing this challenge. *)
val challenge_to_string : challenge -> string
(** [challenge_of_string s] decodes [s] as a challenge. *)
val challenge_of_string : string -> challenge option
(** [challenge_equal a b] is [true] if [a] and [b] are the same challenge. *)
val challenge_equal : challenge -> challenge -> bool
(** The type of credential identifiers. *)
type credential_id = string
(** The type for credential data. *)
type credential_data = {
aaguid : string ;
credential_id : credential_id ;
public_key : Mirage_crypto_ec.P256.Dsa.pub ;
}
(** The type for a registration. *)
type registration = {
user_present : bool ;
user_verified : bool ;
@ -57,11 +109,26 @@ type registration = {
certificate : X509.Certificate.t option ;
}
(** The type for a register_response. *)
type register_response
val register_response_of_string : string -> (register_response, json_decoding_error) result
val register : t -> register_response -> (challenge * registration, error) result
(** [register_response_of_string s] decodes the json encoded response
(consisting of a JSON dictionary with an attestationObject and
clientDataJSON - both Base64 URI safe encoded). The result is a
register_response or a decoding error. *)
val register_response_of_string : string ->
(register_response, json_decoding_error) result
(** [register t response] registers the response, and returns the used
challenge and a registration. The challenge needs to be verified to be
valid by the caller. If a direct attestation is used, the certificate
is returned -- and the signature is validated to establish the trust
chain between certificate and public key. The certificate should be
validated by the caller. *)
val register : t -> register_response ->
(challenge * registration, error) result
(** The type for an authentication. *)
type authentication = {
user_present : bool ;
user_verified : bool ;
@ -70,8 +137,21 @@ type authentication = {
client_extensions : (string * Yojson.Safe.t) list ;
}
(** The type for an authentication response. *)
type authenticate_response
val authenticate_response_of_string : string -> (authenticate_response, json_decoding_error) result
(** [authentication_response_of_string s] decodes the response (a JSON
dictionary of Base64 URI-safe encoded values: authenticatorData,
clientDataJSON, signature, userHandle). If decoding fails, an
error is reported. *)
val authenticate_response_of_string : string ->
(authenticate_response, json_decoding_error) result
(** [authenticate t public_key response] authenticates [response], by checking
the signature with the [public_key]. If it is valid, the used [challenge]
is returned together with the authentication. The challenge needs to be
validated by the caller, and then caller is responsible for looking up the
public key corresponding to the credential id returned by the client web
browser. *)
val authenticate : t -> Mirage_crypto_ec.P256.Dsa.pub -> authenticate_response ->
(challenge * authentication, error) result

View file

@ -0,0 +1,53 @@
opam-version: "2.0"
homepage: "https://github.com/roburio/webauthn"
dev-repo: "git+https://github.com/roburio/webauthn.git"
bug-reports: "https://github.com/roburio/webauthn/issues"
doc: "https://roburio.github.io/webauthn/doc"
maintainer: [ "team@robur.coop" ]
authors: [ "Reynir Björnsson <reynir@reynir.dk>" "Hannes Mehnert <hannes@mehnert.org>" ]
license: "BSD-2-Clause"
build: [
["dune" "subst"] {dev}
["dune" "build" "-p" name "-j" jobs]
["dune" "runtest" "-p" name "-j" jobs] {with-test}
]
depends: [
"ocaml" {>= "4.08.0"}
"dune" {>= "2.7"}
"dream" {dev}
"ppx_blob" {dev}
"cmdliner" {dev}
"logs" {dev}
"lwt" {dev}
"yojson"
"ppx_deriving_yojson"
"mirage-crypto-ec"
"mirage-crypto-rng"
"ocplib-endian"
"x509" {>= "0.13.0"}
"base64" {>= "3.1.0"}
"cstruct" {>= "6.0.0"}
]
synopsis: "WebAuthn - authenticating users to services using public key cryptography"
description: """
WebAuthn is a web standard published by the W3C. Its goal is to
standardize an interfacefor authenticating users to web-based
applications and services using public key cryptography. Modern web
browsers support WebAuthn functionality.
WebAuthn provides two funcitons: register and authenticate. Usually the
public and private keypair is stored on an external token (Yuikey etc.)
or part of the platform (TPM). After the public key is registered, it can
be used to authenticate to the same service.
This module does not preserve a database of registered public keys, their
credential ID, usernames and pending challenges - instead this data must
be stored by a client of this API in a database or other persistent
storage.
[Demo server](https://webauthn-demo.robur.coop)
[WebAuthn specification at W3C](https://w3c.github.io/webauthn/)
"""