|
1
|
# JSON API: X |
|
2
|
([⬑JSON API Index](index.md)) |
|
3
|
|
|
4
|
Jump to: |
|
5
|
|
|
6
|
* [Introduction](#intro) |
|
7
|
* [Capabilities (Access Rights)](#capabilities) |
|
8
|
* [Login](#login) |
|
9
|
* [Anonymous User Logins](#login-anonymous) |
|
10
|
* [Logout](#logout) |
|
11
|
* [Whoami](#whoami) |
|
12
|
|
|
13
|
--- |
|
14
|
|
|
15
|
<a id="intro"></a> |
|
16
|
# Introduction |
|
17
|
|
|
18
|
**FIXME:** Ross found a bug: |
|
19
|
[](/info/479aadb1d2645601) |
|
20
|
(sending the authToken via `POST.envelope` isn't working. It should be.) |
|
21
|
|
|
22
|
The authentication-related operations are described in this section |
|
23
|
(ordered alphabetically by operation name). |
|
24
|
|
|
25
|
The JSON API ties in to/piggybacks on fossil's existing cookie-based |
|
26
|
login mechanism, but we must also keep in mind that not all JSON-using |
|
27
|
clients support cookies. Cookie-capable clients can rely on cookies for |
|
28
|
authentication, whereas non-cookie-aware clients will need to keep track |
|
29
|
of the so-called "auth token" which is created via a login request, and |
|
30
|
pass it in with each request (either as a GET parameter or a property of |
|
31
|
the top-level POST request envelope) to prove to fossil that they are |
|
32
|
authorized to access the requested resources. For most intents and |
|
33
|
purposes, the "auth token" and the "login cookie" are the same thing (or |
|
34
|
serve the same purpose), and the auth token is in fact just the value |
|
35
|
part of the login cookie (which has a project-specific key). |
|
36
|
|
|
37
|
Note that fossil has two conventional user names which can show up in |
|
38
|
various responses but do not refer to specific people: nobody and |
|
39
|
anonymous. The nobody user is anyone who is not logged in. The anonymous |
|
40
|
user is logged in but has no persistent user data (no associated user |
|
41
|
name, email address, or similar). Normally the guest (nobody) user has |
|
42
|
more access restrictions. The distinction between the two is largely |
|
43
|
historical - it is a mechanism to keep bots from following the |
|
44
|
multitudes of links generated by the HTML interface (especially the ZIP |
|
45
|
files), while allowing interested users to do so by logging in as the |
|
46
|
anonymous user (which bots have (or *had*, at the time) a harder time |
|
47
|
doing because the password is randomly generated and protected from |
|
48
|
brute-force attacks by hashing). In the JSON API, the distinction |
|
49
|
between anonymous and nobody is not expected to be as prominent as it is |
|
50
|
in the HTML interface because the reasons for the distinction don't |
|
51
|
apply in *quite* the same ways to the JSON interface. It is possible, |
|
52
|
however, that a given repo locks out guest access to, e.g. the wiki or |
|
53
|
tickets, while still allowing anonymous (logged in) access. |
|
54
|
|
|
55
|
<a id="capabilities"></a> |
|
56
|
# Capabilities (Access Rights) |
|
57
|
|
|
58
|
The "cap" request returns information about the so-called "capabilities" |
|
59
|
(access rights) of the currently logged in user. This command is |
|
60
|
basically the same as the "whoami" command, but returns capabilities in |
|
61
|
a more exanded form (same data, different representation) and does not |
|
62
|
include the authToken in the response. |
|
63
|
|
|
64
|
TODO: consider combining this and [whoami](#whoami) into a single |
|
65
|
whoami response. We don't need both. We also don't really need the |
|
66
|
permissionFlags member - the same info is already \[in a more cryptic form\] |
|
67
|
in the capabilities string. |
|
68
|
|
|
69
|
**Status:** implemented 201109xx. |
|
70
|
|
|
71
|
**Required privileges:** none |
|
72
|
|
|
73
|
**Request:** `/json/cap` |
|
74
|
|
|
75
|
In CLI mode, permissions are not used/honored, and this command will |
|
76
|
report that the caller has all permissions (which he effectively does). |
|
77
|
|
|
78
|
**Response payload example:** |
|
79
|
|
|
80
|
```json |
|
81
|
{ |
|
82
|
"userName":"json-demo", |
|
83
|
"capabilities":"hgjorxz", /* raw fossil permissions list */ |
|
84
|
"permissionFlags":{ /* Same info in a somewhat friendlier form */ |
|
85
|
"setup": false, |
|
86
|
"admin": false, |
|
87
|
"delete": false, |
|
88
|
"password": false, |
|
89
|
"query": false, |
|
90
|
"checkin": false, |
|
91
|
"checkout": true, |
|
92
|
"history": true, |
|
93
|
"clone": false, |
|
94
|
"readWiki": true, |
|
95
|
"createWiki": false, |
|
96
|
"appendWiki": false, |
|
97
|
"editWiki": false, |
|
98
|
"readTicket": true, |
|
99
|
"createTicket": false, |
|
100
|
"appendTicket": false, |
|
101
|
"editTicket": false, |
|
102
|
"attachFile": false, |
|
103
|
"createTicketReport": false, |
|
104
|
"readPrivate": false, |
|
105
|
"zip": true, |
|
106
|
"xferPrivate": false |
|
107
|
} |
|
108
|
} |
|
109
|
``` |
|
110
|
|
|
111
|
**FIXME:** several new permissions have been added to fossil since |
|
112
|
this API was implemented. |
|
113
|
|
|
114
|
|
|
115
|
<a id="login"></a> |
|
116
|
# Login |
|
117
|
|
|
118
|
**Status:** implemented 20110915 (anonymous login 20110918) |
|
119
|
|
|
120
|
**Required privileges:** none |
|
121
|
|
|
122
|
**Request:** (see below for Anonymous user special case) |
|
123
|
|
|
124
|
- `/json/login?name=...&password=...` |
|
125
|
- `/json/login?n=...&p=...` (for symmetry with existing login mechanism) |
|
126
|
|
|
127
|
Or `POST.payload`: `{ "name": ..., "password": ...}` |
|
128
|
|
|
129
|
(POST is highly preferred because it keeps the password out of web |
|
130
|
server logs!) |
|
131
|
|
|
132
|
**Response payload example:** (structure changed 20111001) |
|
133
|
|
|
134
|
```json |
|
135
|
{ |
|
136
|
"authToken":"...", |
|
137
|
"name":"json-demo", |
|
138
|
"capabilities":"hgjorxz", |
|
139
|
"loginCookieName": "fossil-XXXXX" /*project-specific cookie name*/ |
|
140
|
/* TODO: add authTokenExpiry timestamp (cookie expiry time) */ |
|
141
|
} |
|
142
|
``` |
|
143
|
|
|
144
|
We "should" be able to inherit fossil's `REMOTE_USER` handling without |
|
145
|
any special support, but that is untested so far. (If you happen to test |
|
146
|
this, please update this doc with (or otherwise report) your results!) |
|
147
|
|
|
148
|
The response *also* sets the conventional fossil login cookie (for |
|
149
|
clients which can make use of cookies), using fossil's existing |
|
150
|
mechanism for this. |
|
151
|
|
|
152
|
Further requests which require authentication must include the |
|
153
|
`authToken` (from the returned payload value) in the request (or it must |
|
154
|
be available via fossil's standard cookie) or access may (depending on |
|
155
|
the request) be denied. The `authToken` may optionally be set in the |
|
156
|
request envelope or as a GET parameter, and it *must* be given if the |
|
157
|
request requires restricted access to a resource. e.g. if reading |
|
158
|
tickets is disabled for the guest user then all non-guest users must |
|
159
|
send authentication info in their requests in order to be able to fetch |
|
160
|
ticket info. |
|
161
|
|
|
162
|
Cookie-aware clients should send the login-generated cookie with each |
|
163
|
request, in which case they do not need to explicitly include the |
|
164
|
`authToken` in the JSON envelope/GET arguments. If submitted, the |
|
165
|
`authToken` is used, otherwise the cookie, if set, is used. Note that |
|
166
|
fossil uses a project-dependent cookie name in order to help thwart |
|
167
|
attacks, so there is no simple mapping of cookie *name* to auth |
|
168
|
token. That said, the cookie's *value* is also the auth token's value. |
|
169
|
|
|
170
|
> Special case: when accessing fossil over a local server instance |
|
171
|
which was started with the `--localauth` flag, the `authToken` is ignored |
|
172
|
(neither validated nor used for any form of authentication). |
|
173
|
|
|
174
|
|
|
175
|
<a id="login-anonymous"></a> |
|
176
|
## Anonymous User Logins |
|
177
|
|
|
178
|
The Anonymous user requires special handling because he has a random |
|
179
|
password. |
|
180
|
|
|
181
|
First fetch the password and the so-called "captcha seed" via this |
|
182
|
request: |
|
183
|
|
|
184
|
`/json/anonymousPassword` |
|
185
|
|
|
186
|
It will return a payload in the form: |
|
187
|
|
|
188
|
```json |
|
189
|
{ |
|
190
|
"seed": a_32_bit_unsigned_integer, |
|
191
|
"password": "1234abcd" /*hexadecimal STRING*/ |
|
192
|
} |
|
193
|
``` |
|
194
|
|
|
195
|
The "seed" and "password" values of the response payload must be set as |
|
196
|
the "anonymousSeed" and "password" fields (respectively) of the |
|
197
|
subsequent login request. The login request is identical to |
|
198
|
non-anonymous login except that extra "anonymousSeed" property is |
|
199
|
required. |
|
200
|
|
|
201
|
The password value *may* be time-limited, and *may* eventually become |
|
202
|
invalidated due to old age. This is unspecified. |
|
203
|
|
|
204
|
***Potential***** (low-probability) bug regarding the seed value:** from |
|
205
|
what I hear, some unusual JSON platforms don't support full 32-bit |
|
206
|
precision. If absolutely necessary we could chop off a bit or two from |
|
207
|
the seed value (*if* it ever becomes a problem and if DRH blesses it). |
|
208
|
Or we could just make it a double. |
|
209
|
|
|
210
|
|
|
211
|
<a id="logout"></a> |
|
212
|
# Logout |
|
213
|
|
|
214
|
**Status:** implemented 20110916 |
|
215
|
|
|
216
|
**Required privileges:** none, but must be logged in |
|
217
|
|
|
218
|
**Request:** |
|
219
|
|
|
220
|
- `/json/logout?authToken=...token fetched by /login` |
|
221
|
|
|
222
|
Or: set the `authToken` property of the POST envelope (as opposed to the |
|
223
|
`POST.payload`) |
|
224
|
|
|
225
|
Or: fossil's normal cookie mechanism is the fallback for the auth token. |
|
226
|
|
|
227
|
**Response payload:** The same as the "whoami" response, containing the |
|
228
|
info for the "nobody" user. |
|
229
|
|
|
230
|
This request requires the authentication token, and subsequent logouts |
|
231
|
without an intervening login will fail with the "auth token not |
|
232
|
provided" error. In effect this request removes the login entry from the |
|
233
|
user account, making the token invalid for future requests. In HTTP |
|
234
|
mode, on success fossil's login cookie is unset by this call. |
|
235
|
|
|
236
|
|
|
237
|
<a id="whoami"></a> |
|
238
|
# Whoami |
|
239
|
|
|
240
|
This request fetches the current user's login name, capabilities, and |
|
241
|
auth token. This can be used to check whether a login is active when the |
|
242
|
client has not explicitly logged in (e.g. was logged in automatically |
|
243
|
via a pre-existing cookie). |
|
244
|
|
|
245
|
**Status:** implemented 20110922 |
|
246
|
|
|
247
|
**Required privileges:** none |
|
248
|
|
|
249
|
**Request:** `/json/whoami` |
|
250
|
|
|
251
|
**Response payload example:** |
|
252
|
|
|
253
|
```json |
|
254
|
{ |
|
255
|
"name": "nobody", |
|
256
|
"capabilities": "o", |
|
257
|
"authToken": "fossil auth token (only for logged-in users)" |
|
258
|
} |
|
259
|
``` |
|
260
|
|
|
261
|
The reason authToken is included in the response is because it gives |
|
262
|
client-side JavaScript code a way of fetching/checking for the auth |
|
263
|
token at app startup. The token is normally sent as a cookie but parsing |
|
264
|
the cookies in the browser is tedious, and fossil has a |
|
265
|
project-dependent cookie name (which complicates parsing a bit). If |
|
266
|
client code digs the cookie out of the browser, the app still wouldn't |
|
267
|
know if the token is still valid, whereas whoami won't (or shouldn't!) |
|
268
|
return an expired auth token. If the request does not include |
|
269
|
authentication info (via the cookie, GET param, or request envelope) |
|
270
|
then the response will not contain the authToken property and the user's |
|
271
|
name will be "nobody". |
|
272
|
|