This repository has been archived by the owner on Jun 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathspec.bs
263 lines (162 loc) · 16.5 KB
/
spec.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
<pre class="metadata">
Title: Brokered Authentication
Status: ED
ED: https://apps.wp-api.org/spec/
Shortname: wp-broker
Level: 1
Editor: Ryan McCue, Human Made, https://rmccue.io/
Abstract: This document describes the process for using a third-party ("broker") to automatically obtain OAuth client credentials for sites which recognise the broker.
Group: wp
</pre>
# Introduction
The Brokered Authentication protocol is designed as a way for client applications to dynamically register themselves as an application with a server via a third-party broker. This protocol is designed to allow applications to register once to access a distributed networks of servers. The protocol is designed to work with OAuth 1.0a to facilitate initial client registration and issuing of client credentials.
The protocol is designed to allow secure transmission of client credentials without requiring TLS on the server by using a verification request. This process is based on the process used by the [[Pingback]] and [[Webmention]] protocols for verification.
<pre class="biblio">
{
"pingback": {
"authors": [
"Stuart Langridge",
"Ian Hickson"
],
"href": "http://www.hixie.ch/specs/pingback/pingback-1.0",
"title": "Pingback 1.0"
}
}
</pre>
## Terminology
* <dfn>Broker</dfn>: The application registry which connects the Client to the Server.</dfn>
* <dfn>Client</dfn>: The end-user application which wishes to authenticate with the Server (in OAuth terminology, the agent of the resource owner).</dfn>
* <dfn>Server</dfn>: An HTTP server containing the resources the client wishes to access.</dfn>
# Connection Process
The connection process follows five steps, using three HTTP requests:
1. The initial step is the [[#broker-connection]], where the Client connects to the Broker to request credentials for a Server. The Broker does not complete this HTTP request ("Broker Connection Request") immediately.
2. The Broker then issues a [[#connection-request]] to the Server to request the Server issue credentials for an application.
3. The Server relays a set of client credentials to the Broker in the [[#verification-request]]. The Server generates the client credentials optimistically, but does not activate them until the request has been verified by the Broker.
4. The Broker verifies the connection request with the Server, and the Server activates the credentials.
5. The Broker provides the credentials to the Client via the Broker Connection Request in the [[#broker-connection-response]] and closes the request.
The Client is responsible for beginning the process by connecting to the Broker via a HTTP request using TLS. This HTTP request remains open until the [[#broker-connection-response]] step is completed.
This process requires the Broker to provide two endpoints:
* Initialization Endpoint: The endpoint used by the Client to start the process.
* Verification Endpoint: The endpoint used by the Server to verify the Connection Request is valid.
The Server is also required to provide one endpoint:
* Connection Request Endpoint: The endpoint used by the Broker to request credentials.
This Connection Request endpoint MUST be advertised using the WordPress REST API index (see [[#autodiscovery]]).
Broker Connection {#broker-connection}
-----------------
The Client starts the connection process by requesting credentials for a Server from the Broker. This is issued by a HTTP "POST" request to the Initialization Endpoint on the Broker, authenticated using the OAuth 1.0 protocol. The request body is constructed by using the "application/x-www-form-urlencoded" content type with the following REQUIRED parameter:
* <code>server_url</code>: The URL to connect to the Server.
The Broker MAY specify other parameters.
The <code>server_url</code> parameter MUST either specify the Connection Request Endpoint directly, or specify a URL where the Connection Request Endpoint can be discovered from. The Broker SHOULD apply the autodiscovery process to this URL per [[#autodiscovery]] before using as the Connection Request Endpoint.
The request parameters are constructed similarly to the Temporary Credential Request in OAuth 1.0. The empty <code>oauth_token</code> parameter MAY be omitted from the request, and the empty string MUST be used as the token secret value.
The request MUST be verified using OAuth 1.0. The Broker Connection Request MUST NOT be terminated until after the verification step or until an error occurs. The response is not complete until the Broker Connection Response stage.
The Broker responds to the request using the [[JSON]] content type. The response uses the "application/json" content-type header.
The Broker SHOULD immediately send the response headers with a 200 status code ("OK"), but MUST NOT send the body until the Broker Connection Response stage.
Note: This initial response ensures the connection remains open with most server configurations.
The Broker retrieves the pre-registered data for the Client using a Client Identifier. Brokers SHOULD use the identifier portion of the OAuth client credentials ("consumer key") as the client identifier. This Identifier MUST be publically available to allow Server configuration to whitelist or blacklist certain clients.
Credentials MUST NOT be cached by the Broker. The Server remains the single source of truth for credentials, and the credentials MAY be invalidated by the Server at any time.
### Error Handling
The Broker Connection is kept open until verification is completed. The Broker MAY cancel the connection without verification if the verification fails to complete in time, or a fatal error occurs on the Broker. In the event of an error, the Broker MUST send a response before closing the connection. The response is a JSON-formatted Error object, with the additional REQUIRED parameters:
* <code>status</code>: The literal string <code>error</code>.
Connection Request {#connection-request}
------------------
The Broker is responsible for the Connection Request to the Server to request credentials on behalf of the Client. The Broker uses the Client data obtained in the Broker Connection step.
Before the Broker issues the request, it MUST generate a verification token: an unguessable value passed to the Server and REQUIRED during the Verification Request. This ensures third-parties cannot generate requests independently.
The Broker then requests the credentials by a HTTP "POST" request to the Connection Request Endpoint. The request body is constructed by using the "application/x-www-form-urlencoded" content type with the following REQUIRED parameters:
* <code>client_id</code>: The Client Identifier.
* <code>broker</code>: A URI representing a unique identifier for the broker.
* <code>verifier</code>: The verification token.
* <code>callback_url</code>: The OAuth callback URL.
The <code>client_id</code> MUST be a string containing between one and 255 characters.
The <code>broker</code> parameter MUST be a URI which uniquely identifies the Broker. The Server SHOULD match the Broker identifier against a list of known Brokers and reject the request if the Broker is unknown.
The <code>verifier</code> parameter MUST be an alphanumeric string containing between one and 255 characters.
The <code>callback_url</code> parameter MUST be a URL representing the location the user will be sent after authorization.
The following OPTIONAL parameters may be included:
* <code>client_name</code>: A human-readable client name.
* <code>client_description</code>: A human-readable client description.
* <code>client_details</code>: A URL to access a HTML page describing the client.
These OPTIONAL parameters allow server administrators to identify new clients for security and privacy consideration.
Upon receipt of a Connection Request, the Server SHOULD queue and process the request asynchronously to prevent DoS attacks. However, the Server SHOULD check the <code>client_id</code> for validity synchronously.
For successful requests, the Server MUST respond with a 202 Accepted response. The response MAY contain a body for future extension. If a body is included, the body SHOULD be JSON-formatted data.
### Error Handling
For unsuccessful requests, the Server MUST respond with an appropriate HTTP error code. The Server SHOULD include a JSON response body containing an Error object.
If the verifier is invalid, the Server SHOULD issue a 400 Bad Request response with the machine-readable error code <code>ba.invalid_verifier</code>.
If the client ID is semantically invalid (for example, an empty string), the Server SHOULD issue a 400 Bad Request response with the machine-readable error code <code>ba.invalid_client_id</code>.
If the callback URL is invalid (for example, an empty string, or a blacklisted protocol), the Server SHOULD issue a 400 Bad Request response with the machine-readable error code <code>ba.invalid_callback</code>.
If a Server is using a whitelist or blacklist for client identifiers, and the client identifier is rejected by this process, the Server SHOULD issue a 400 Bad Request response with the machine-readable error code <code>ba.rejected_client</code>.
If the Broker is not known to the Server, the Server SHOULD issue a 400 Bad Request response with the machine-readable error code <code>ba.unknown_broker</code>.
Verification Request {#verification-request}
--------------------
The Server verfies that the Connection Request was valid by sending a request to the Verification Endpoint of the Broker. This serves a dual purpose of verifying that the request was valid, as well as passing the client credentials to the Broker.
Before sending the request, the Server MUST generate a new set of client credentials local to the server, which MUST NOT be active until after verification is complete. The credentials MUST consist of a unique identifier and a matching shared secret. These credentials SHOULD be the credentials for a new OAuth client on the Server. The credentials SHOULD be linked to the client identifier provided by the Broker.
To avoid resource exhaustion attacks, the generated credentials SHOULD be temporary and expire immediately after receiving a response to the Verification Request. Server implementations are encouraged to keep these credentials in runtime memory and only save them permanently after verification is complete.
The Server requests verification by a HTTP "POST" request to the Verification Endpoint. The request body is constructed by using the "application/x-www-form-urlencoded" content type with the following REQUIRED parameters:
* <code>verifier</code>: The verification token received from the Broker in the Connection Request step.
* <code>client_id</code>: The client identifier received from the Broker in the Connection Request.
* <code>client_token</code>: The generated credentials identifier.
* <code>client_secret</code>: The generated credentials shared-secret.
The Server MAY include other parameters in the request.
Since the request transmits plain text credentials in the request, the Broker MUST provide the Verification Endpoint over a transport-layer security mechanism such as TLS or SSL.
After receiving the Verification Request, the Broker first verifies that the verification token matches a request for the given client identifier, then responds to the Verification request with a 200 OK response. The response MAY include a body. If a body is included, the body SHOULD be JSON-formatted data.
Once the Server receives a 200 OK response from the Broker, it SHOULD mark the credentials as active. If the Server had not stored the credentials permanently, it SHOULD now store the credentials.
### Error Handling
For unsuccessful requests, the Broker MUST respond with an appropriate HTTP error code. The Broker SHOULD include a JSON response body containing an Error object.
If the Server receives an error from the Broker, it MUST NOT mark the credentials as active. It SHOULD discard the credentials to avoid resource exhaustion attacks.
If the verification token does not match an outstanding request, or does not match the client identifier, the Broker SHOULD issue a 400 Bad Request response with the machine-readable error code <code>ba.invalid_verifier</code>.
If the process has exceeded a time limit set by the Broker, the Broker SHOULD issue a 409 Conflict response with the machine-readable error code <code>ba.timed_out</code>.
Broker Connection Response {#broker-connection-response}
--------------------------
Once the Broker has received the client credentials from the Server and verified them, it then passes these back to the Client.
The Broker sends a response over the Broker Connection. This response is a JSON-formatted object, and encodes the following REQUIRED parameters:
* <code>client_token</code>: The generated credentials identifier.
* <code>client_secret</code>: The generated credentials shared-secret.
The Broker MAY include other parameters in the response.
# Data Formats
## Errors
An Error is a JSON-formatted object encoding a map of parameters. An Error object contains the following REQUIRED parameters:
* <code>code</code>: A machine-readable code as a JSON string used to identify the type of error that occurred.
* <code>message</code>: A human-readable description of the error that occurred, suitable for display to the end-user.
Codes beginning with <code>ba.</code> are reserved for this specification and future extensions and MUST NOT be used by vendor-specific extensions.
The response MAY contain the following OPTIONAL parameter:
* <code>data</code>: Additional data related to the error for use in processing or debugging.
Unless otherwise specified, Error objects MAY contain other parameters.
Autodiscovery {#autodiscovery}
=============
As the Server URL is typically supplied by an end-user, the autodiscovery process SHOULD be applied to this URL to find the Connection Request Endpoint. Broker implementations SHOULD NOT assume the supplied URL is the Connection Request Endpoint itself.
Given a Server URL, the process to discover the Connection Request Endpoint is as follows:
1. Set the Connection Request Endpoint to the Server URL.
1. Issue a HTTP "HEAD" request to the Server URL and obtain the HTTP response headers. If an error occurs during the request, or a HTTP error code is returned, mark the Server URL as invalid, and stop the discovery process.
2. If the headers contain <code>X-BA-Endpoint: connection-request</code>, stop the discovery process.
3. If the headers do not contain a <code>Link</code> header or the <code>Link</code> header does not contain a link with relation <code>https://api.w.org/</code>, stop the discovery process.
4. Issue a HTTP "GET" request to the URL specified in the link with relation <code>https://api.w.org/</code> and obtain the HTTP response body. If an error occurs during the request, or a HTTP error code is returned, mark the Server URL as invalid, and stop the discovery process.
5. If the response body is not JSON-formatted, mark the Server URL as invalid, and stop the discovery process.
6. Decode the response body. If the response body does not contain the <code>authentication.broker</code> key, or the value of the key is not a valid URL, mark the Server URL as invalid, and stop the discovery process.
7. Set the Connection Request Endpoint to the value of the <code>authentication.broker</code> parameter in the response body.
In pseudo-JavaScript code:
<pre class="lang-javascript">
function discover ( server_url ) {
let connection_request_endpoint = server_url
let response = send_http_request( 'HEAD', server_url )
if ( ! response or response.status !== 200 ) {
throw Error
}
if ( response.headers['X-BA-Endpoint'] == 'connection-request' ) {
return server_url
}
let links = parse_links( response.headers['Link'] )
if ( ! links or ! links['https://api.w.org/'] ) {
return server_url
}
let response = send_http_request( links['https://api.w.org/'] )
if ( ! response or response.status !== 200 ) {
throw Error
}
let data = JSON.parse( response.body )
if ( ! data or ! data.authentication or ! data.authentication.broker ) {
throw Error
}
return data.authentication.broker
}
</pre>
To facilitate quicker discovery, the Server SHOULD issue a <code>X-BA-Endpoint: connection-request</code> header from the Connection Request Endpoint. This allows the Broker to return immediately from the discovery process rather than checking the index.
The autodiscovery process MAY be cached by the Broker, although cached results SHOULD have a finite duration no longer than 24 hours, as the Server MAY change the API URL.
Note: Servers should take caching into account when changing the API URL, and allow up to 24 hours for the change to propagate.