Skip to content
This repository was archived by the owner on Mar 25, 2024. It is now read-only.

Commit 9320271

Browse files
committed
Reformat README, add language hints on code blocks
1 parent fbd3817 commit 9320271

1 file changed

Lines changed: 75 additions & 98 deletions

File tree

README.md

Lines changed: 75 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,14 @@ A PHP implementation of the FIDO U2F authentication standard
44

55
## Introduction
66

7-
This library is designed to allow easy integration of U2F hardware keys to an
8-
existing user authentication scheme. It handles the parsing and validating all
9-
of the raw message formats, and translates them into standard PHP objects.
7+
This library is designed to allow easy integration of U2F hardware keys to an existing user authentication scheme.
8+
It handles the parsing and validating all of the raw message formats, and translates them into standard PHP objects.
109

11-
Note that use of the word "key" here refers to a USB "key" or dongle; however,
12-
the device may connect with the browser over a different protocol (such as
13-
Bluetooth or NFC). Unless otherwise stated, "key" should be interpreted to mean
14-
"FIDO U2F Token".
10+
Note that use of the word "key" here refers to a USB "key" or dongle; however, the device may connect with the browser over a different protocol (such as Bluetooth or NFC).
11+
Unless otherwise stated, "key" should be interpreted to mean "FIDO U2F Token".
1512

16-
There are two main operations that you will need to understand for a successful
17-
integration: registration and authentication. Registration is the act of
18-
associating a key that the end-user is physically in posession of with their
19-
existing account; authentication is where that key is used to cryptographically
20-
sign a message from your application to verify posession of said key.
13+
There are two main operations that you will need to understand for a successful integration: registration and authentication.
14+
Registration is the act of associating a key that the end-user is physically in posession of with their existing account; authentication is where that key is used to cryptographically sign a message from your application to verify posession of said key.
2115

2216
Additional resources:
2317

@@ -26,153 +20,136 @@ Additional resources:
2620

2721
## Usage
2822

29-
Usage will be described in three parts: setup, registration, and
30-
authentication. The code in setup should be used before both registration and
31-
authentication.
23+
Usage will be described in three parts: setup, registration, and authentication.
24+
The code in setup should be used before both registration and authentication.
3225

33-
The API is designed to "fail loudly"; that is, failures will throw an
34-
exception, ensuring that return values are always the result of a successful
35-
operation. This reduces the need for complex error checking and handling during
36-
use, since the whole thing can be simply wrapped in a `try/catch` block and
37-
assume that everything went well if no exceptions are caught.
26+
The API is designed to "fail loudly"; that is, failures will throw an exception, ensuring that return values are always the result of a successful operation.
27+
This reduces the need for complex error checking and handling during use, since the whole thing can be simply wrapped in a `try/catch` block and assume that everything went well if no exceptions are caught.
3828

3929
### Setup
4030

41-
All operations are performed by the U2F Server class, so it needs to be
42-
instanciated and configured:
31+
All operations are performed by the U2F Server class, so it needs to be instanciated and configured:
4332

44-
use Firehed\U2F\Server;
45-
$server = new Server();
46-
$server->setTrustedCAs(glob('path/to/certs/*.pem'))
47-
->setAppId('https://u2f.example.com');
33+
```php
34+
use Firehed\U2F\Server;
35+
$server = new Server();
36+
$server->setTrustedCAs(glob('path/to/certs/*.pem'))
37+
->setAppId('https://u2f.example.com');
38+
```
4839

49-
The trusted CAs are whitelisted vendors, and must be an array of absolute paths
50-
to PEM-formatted CA certs (as strings). Some provider certificates are provided
51-
in the `CACerts/` directory in the repository root; in a deployed project,
52-
these should be available via `$PROJECT_ROOT/vendor/firehed/u2f/CACerts/*.pem`.
40+
The trusted CAs are whitelisted vendors, and must be an array of absolute paths to PEM-formatted CA certs (as strings).
41+
Some provider certificates are provided in the `CACerts/` directory in the repository root; in a deployed project, these should be available via `$PROJECT_ROOT/vendor/firehed/u2f/CACerts/*.pem`.
5342

54-
You may also choose to disable CA verification, by calling
55-
`->disableCAVerification()` instead of `setTrustedCAs()`. This removes trust in
56-
the hardware vendors, but ensures that as new vendors issue tokens, they will
57-
be forward-compatible with your website.
43+
You may also choose to disable CA verification, by calling `->disableCAVerification()` instead of `setTrustedCAs()`.
44+
This removes trust in the hardware vendors, but ensures that as new vendors issue tokens, they will be forward-compatible with your website.
5845

59-
The URI provided to `setAppId()` must be the HTTPS domain component of your
60-
website. See [FIDO U2F AppID and Facet Specification](https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-appid-and-facets.html#appid-example-1)
61-
for additional information.
46+
The URI provided to `setAppId()` must be the HTTPS domain component of your website. See [FIDO U2F AppID and Facet Specification](https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-appid-and-facets.html#appid-example-1) for additional information.
6247

63-
The client needs an U2F Javascript API implementation; the example code below
64-
is based on [Google's implementation](https://github.com/google/u2f-ref-code/blob/master/u2f-gae-demo/war/js/u2f-api.js)
48+
The client needs an U2F Javascript API implementation; the example code below is based on [Google's implementation](https://github.com/google/u2f-ref-code/blob/master/u2f-gae-demo/war/js/u2f-api.js)
6549

6650
### Registration
6751

68-
Registering a token to a user's account is a two-step process: generating
69-
a challenge, and verifying the response to that challenge.
52+
Registering a token to a user's account is a two-step process: generating a challenge, and verifying the response to that challenge.
7053

7154
#### Genrating the challenge
7255

7356
Start by generating a challenge:
7457

75-
$request = $server->generateRegisterRequest();
58+
```php
59+
$request = $server->generateRegisterRequest();
60+
```
7661

77-
Store this object temporarily (probably in a session) since it is needed during
78-
verification, and send it to the user as JSON.
62+
Store this object temporarily (probably in a session) since it is needed during verification, and send it to the user as JSON.
7963

80-
If the user has already registered one or more keys, you must also generate
81-
sign requests for the existing registrations:
64+
If the user has already registered one or more keys, you must also generate sign requests for the existing registrations:
8265

83-
$registrations = $user->getU2FRegistrations();
84-
$sign_requests = $server->generateSignRequests($registrations);
66+
```php
67+
$registrations = $user->getU2FRegistrations();
68+
$sign_requests = $server->generateSignRequests($registrations);
69+
```
8570

8671
Send the sign requests to the user as JSON as well.
8772

8873
Pass both of these values into the U2F JS API:
8974

90-
var request = JSON.parse(register_request_from_php);
91-
var sign_requests = JSON.parse(sign_requests_from_php);
92-
u2f.register([request], sign_requests, complete_registration_callback);
75+
```js
76+
var request = JSON.parse(register_request_from_php);
77+
var sign_requests = JSON.parse(sign_requests_from_php);
78+
u2f.register([request], sign_requests, complete_registration_callback);
79+
```
9380

94-
The `complete_registration_callback` should stringify the response object and
95-
POST it to your server for verification, described below.
81+
The `complete_registration_callback` should stringify the response object and POST it to your server for verification, described below.
9682

9783
#### Verifying the response
9884

9985
When a response is received, it should be POSTed to your server and verified:
10086

101-
use Firehed\U2F\RegisterResponse;
102-
$server->setRegisterRequest($previously_generated_request);
103-
$response = RegisterResponse::fromJson($_POST['some_form_field']);
104-
$registration = $server->register($response)
105-
// (store Registration)
87+
```php
88+
use Firehed\U2F\RegisterResponse;
89+
$server->setRegisterRequest($previously_generated_request);
90+
$response = RegisterResponse::fromJson($_POST['some_form_field']);
91+
$registration = $server->register($response)
92+
// (store Registration)
93+
```
10694

107-
The `$registration` should be associated with the user (typically by persisting
108-
to a database).
95+
The `$registration` should be associated with the user (typically by persisting to a database).
10996

110-
Registrations SHOULD be persisted as a one-to-many relationship with the user,
111-
since a user may own multiple keys and may want to associate all of them with
112-
their account (e.g. a backup key is kept on a spouse's keychain). It is
113-
RECOMMENDED to use `(user_id, $registration->getKeyHandleWeb())` as a unique
114-
composite identifier.
97+
Registrations SHOULD be persisted as a one-to-many relationship with the user, since a user may own multiple keys and may want to associate all of them with their account (e.g. a backup key is kept on a spouse's keychain). It is RECOMMENDED to use `(user_id, $registration->getKeyHandleWeb())` as a unique composite identifier.
11598

116-
At minimum, a persisted Registration must store the Key Handle, Counter, and
117-
Public Key; implementations SHOULD also store the Attestation Certificate
99+
At minimum, a persisted Registration must store the Key Handle, Counter, and Public Key; implementations SHOULD also store the Attestation Certificate
118100

119-
This is not a requirement of the specification, but leads to a better user
120-
experience.
101+
This is not a requirement of the specification, but leads to a better user experience.
121102

122103
### Authentication
123104

124-
Authentication is a similar process as registration: generate challenges to
125-
sign for each of the user's registrations, and validate the response when
126-
received.
105+
Authentication is a similar process as registration: generate challenges to sign for each of the user's registrations, and validate the response when received.
127106

128107
#### Generating the challenge:
129108

130109
This is done identically to registration:
131110

132-
$registrations = $user->getU2FRegistrations();
133-
$sign_requests = $server->generateSignRequests($registrations);
111+
```php
112+
$registrations = $user->getU2FRegistrations();
113+
$sign_requests = $server->generateSignRequests($registrations);
114+
```
134115

135-
Store these in the session for use in the next step, JSON-encode them, and send
136-
these to the user to pass into the U2F JS API:
116+
Store these in the session for use in the next step, JSON-encode them, and send these to the user to pass into the U2F JS API:
137117

138-
var sign_requests = JSON.parse(sign_requests_from_php);
139-
u2f.sign(sign_requests, complete_auth_callback);
118+
```js
119+
var sign_requests = JSON.parse(sign_requests_from_php);
120+
u2f.sign(sign_requests, complete_auth_callback);
121+
```
140122

141-
Like registration, the `complete_auth_callback` should POST the stringified
142-
response to the server for verification.
123+
Like registration, the `complete_auth_callback` should POST the stringified response to the server for verification.
143124

144125
#### Verifying the response
145126

146127
This is also similar to registration:
147128

148-
use Firehed\U2F\SignResponse;
149-
$server->setRegistrations($user->getU2FRegistrations()
150-
->setSignRequests($previously_generated_requests);
151-
$response = SignResponse::fromJson($_POST['some_form_field']);
152-
$registration = $server->authenticate($response);
153-
// (update Registration in storage with above)
129+
```php
130+
use Firehed\U2F\SignResponse;
131+
$server->setRegistrations($user->getU2FRegistrations()
132+
->setSignRequests($previously_generated_requests);
133+
$response = SignResponse::fromJson($_POST['some_form_field']);
134+
$registration = $server->authenticate($response);
135+
// (update Registration in storage with above)
136+
```
154137

155-
If no exception is thrown, `$registration` will be a Registration object with
156-
an updated `counter`; you MUST persist this updated counter to wherever the
157-
registrations are stored. Failure to do so **is insecure** and exposes your
158-
application to token cloning attacks.
138+
If no exception is thrown, `$registration` will be a Registration object with an updated `counter`; you MUST persist this updated counter to wherever the registrations are stored.
139+
Failure to do so **is insecure** and exposes your application to token cloning attacks.
159140

160141
## Demo
161142

162-
You may try all of this at https://u2f.ericstern.com, and see the corresponding
163-
code at https://github.com/Firehed/u2f-php-examples
143+
You may try all of this at https://u2f.ericstern.com, and see the corresponding code at https://github.com/Firehed/u2f-php-examples
164144

165-
The example code is only designed to show how the APIs interact with each
166-
other, and intentionally leaves out best practices such as use of routers and
167-
dependency inversion containers to keep the examples as simple as possible. See
168-
its README for more information.
145+
The example code is only designed to show how the APIs interact with each other, and intentionally leaves out best practices such as use of routers and dependency inversion containers to keep the examples as simple as possible.
146+
See its README for more information.
169147

170148
## Tests
171149

172150
If you are using Arcanist, `arc unit` workflows will work as expected.
173151

174-
Otherwise, all tests are in the `tests/` directory and can be run with
175-
`vendor/bin/phpunit tests/`.
152+
Otherwise, all tests are in the `tests/` directory and can be run with `vendor/bin/phpunit tests/`.
176153

177154
## License
178155
(TBD)

0 commit comments

Comments
 (0)