Skip to content

Commit 5b65246

Browse files
committed
first readme draft
1 parent fbdb77b commit 5b65246

File tree

1 file changed

+86
-1
lines changed

1 file changed

+86
-1
lines changed

README.md

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,90 @@
11
# webauthn-swift
22

3+
This package provides a Swift implementation of the [WebAuthn API](https://w3c.github.io/webauthn) focused on making it
4+
easy to leverage the power of WebAuthn.
5+
36
🚨 This library is a proof of concept - do not use it in production yet!
47

5-
A Swift library for implementing the WebAuthn spec
8+
## Getting Started
9+
10+
**Adding the dependency**
11+
12+
Add the following entry in your `Package.swift` to start using `WebAuthn`:
13+
14+
```swift
15+
.package(url: "https://github.com/swift-server/webauthn-swift.git", branch: "main")
16+
```
17+
18+
and `WebAuthn` dependency to your target:
19+
20+
```swift
21+
.target(name: "MyApp", dependencies: [.product(name: "WebAuthn", package: "webauthn-swift")])
22+
```
23+
24+
## Usage
25+
26+
The library exposes just four core methods through the `WebAuthnManager` struct:
27+
28+
- `WebAuthnManager.beginRegistration()`
29+
- `WebAuthnManager.finishRegistration()`
30+
- `WebAuthnManager.beginAuthentication()`
31+
- `WebAuthnManager.finishAuthentication()`
32+
33+
Generally, the library makes the following assumptions about how a Relying Party implementing this library will
34+
interface with a webpage that will handle calling the WebAuthn API:
35+
36+
1. JSON is the preferred data type for transmitting registration and authentication options from the server to
37+
the webpage to feed to `navigator.credentials.create()` and `navigator.credentials.get()` respectively.
38+
39+
2. JSON is the preferred data type for transmitting WebAuthn responses from the browser to the Relying Party.
40+
41+
3. Bytes are not directly transmittable in either direction as JSON, and so should be encoded to and decoded
42+
from base64url. To make life a little bit easier there are two typealiases indicating whether something is expected,
43+
or returned, as base64/base64url:
44+
45+
- `public typealias URLEncodedBase64 = String`
46+
- `public typealias EncodedBase64 = String`
47+
48+
### Example flow:
49+
50+
#### Setup
51+
52+
53+
#### Registration
54+
55+
1. A user wants to signup on a website using WebAuthn. The client makes a request to the backend which implements this
56+
library. On request the backend calls the `beginRegistration(user:)` method and sends the returned
57+
`PublicKeyCredentialCreationOptions` back to the client.
58+
59+
2. The client passes the received `PublicKeyCredentialCreationOptions` via the WebAuthn API to
60+
`navigator.credentials.create()`. This in turn will prompt the user to create a new credential using an
61+
authenticator of their choice (TouchID, security keys, ...). The response must then be send back to the backend.
62+
63+
3. On request the backend calls the `finishRegistration(challenge:credentialCreationData:)` method with the previously
64+
generated challenge and the received authenticator response (from `navigator.credentials.create()`). If
65+
`finishRegistration` succeeds a new `Credential` object will be returned. This object should be persisted somewhere
66+
(e.g. a database) and linked to the user from step 1.
67+
68+
#### Authentication
69+
70+
1. A user wants to log in on a website using WebAuthn. When tapping the "Login" button the client send a request to
71+
the backend. The backend responds to this request with a call to `beginAuthentication()` which then in turn
72+
returns a new `PublicKeyCredentialRequestOptions`. This must be send back to the client so it can pass it to
73+
`navigator.credentials.get()`.
74+
2. Whatever `navigator.credentials.get()` returns will be send back to the backend, parsing it into
75+
`AuthenticationCredential`.
76+
```swift
77+
let authenticationCredential = try req.content.decode(AuthenticationCredential.self)
78+
```
79+
3. Next the backend calls
80+
`finishAuthentication(credential:expectedChallenge:credentialPublicKey:credentialCurrentSignCount:)`.
81+
- The `credential` parameter expects the decoded `AuthenticationCredential`
82+
- The `expectedChallenge` parameter expects the challenge previously generated
83+
from `beginAuthentication()` (e.g. through a session).
84+
- Query the persisted credential from [Registration](####registration) using the credential id from the decoded
85+
`AuthenticationCredential`. Pass this credential in the `credentialPublicKey` parameter and it's sign count to
86+
`credentialCurrentSignCount`.
87+
88+
4. If `finishAuthentication` succeeds you can safely login the user linked to the credential! `finishAuthentication`
89+
will return a `VerifiedAuthentication` with the updated sign count and a few other information. Use this to
90+
update the credential in the database.

0 commit comments

Comments
 (0)