Fossil

JSON API: X
Login

(⬑JSON API Index)

Jump to:


Introduction

FIXME: Ross found a bug: /info/479aadb1d2645601 (sending the authToken via POST.envelope isn't working. It should be.)

The authentication-related operations are described in this section (ordered alphabetically by operation name).

The JSON API ties in to/piggybacks on fossil's existing cookie-based login mechanism, but we must also keep in mind that not all JSON-using clients support cookies. Cookie-capable clients can rely on cookies for authentication, whereas non-cookie-aware clients will need to keep track of the so-called "auth token" which is created via a login request, and pass it in with each request (either as a GET parameter or a property of the top-level POST request envelope) to prove to fossil that they are authorized to access the requested resources. For most intents and purposes, the "auth token" and the "login cookie" are the same thing (or serve the same purpose), and the auth token is in fact just the value part of the login cookie (which has a project-specific key).

Note that fossil has two conventional user names which can show up in various response but do not refer to specific people: nobody and anonymous. The nobody user is anyone who is not logged in. The anonymous user is logged in but has no persistent user data (no associated user name, email address, or similar). Normally the guest (nobody) user has more access restrictions. The distinction between the two is largely historical - it is a mechanism to keep bots from following the multitudes of links generated by the HTML interface (especially the ZIP files), while allowing interested users to do so by logging in as the anonymous user (which bots have (or had, at the time) a harder time doing because the password is randomly generated and protected from brute-force attacks by hashing). In the JSON API, the distinction between anonymous and nobody is not expected to be as prominent as it is in the HTML interface because the reasons for the distinction don't apply in quite the same ways to the JSON interface. It is possible, however, that a given repo locks out guest access to, e.g. the wiki or tickets, while still allowing anonymous (logged in) access.

Capabilities (Access Rights)

The "cap" request returns information about the so-called "capabilities" (access rights) of the currently logged in user. This command is basically the same as the "whoami" command, but returns capabilities in a more exanded form (same data, different representation) and does not include the authToken in the response.

TODO: consider combining this and whoami into a single whoami response. We don't need both. We also don't really need the permissionFlags member - the same info is already [in a more cryptic form] in the capabilities string.

Status: implemented 201109xx.

Required privileges: none

Request: /json/cap

In CLI mode, permissions are not used/honored, and this command will report that the caller has all permissions (which he effectively does).

Response payload example:

{
"userName":"json-demo",
"capabilities":"hgjorxz", /* raw fossil permissions list */
"permissionFlags":{ /* Same info in a somewhat friendlier form */
 "setup": false,
 "admin": false,
 "delete": false,
 "password": false,
 "query": false,
 "checkin": false,
 "checkout": true,
 "history": true,
 "clone": false,
 "readWiki": true,
 "createWiki": false,
 "appendWiki": false,
 "editWiki": false,
 "readTicket": true,
 "createTicket": false,
 "appendTicket": false,
 "editTicket": false,
 "attachFile": false,
 "createTicketReport": false,
 "readPrivate": false,
 "zip": true,
 "xferPrivate": false
 }
}

FIXME: several new permissions have been added to fossil since this API was implemented.

Login

Status: implemented 20110915 (anonymous login 20110918)

Required privileges: none

Request: (see below for Anonymous user special case)

Or POST.payload: { "name": ..., "password": ...}

(POST is highly preferred because it keeps the password out of web server logs!)

Response payload example: (structure changed 20111001)

{
"authToken":"...",
"name":"json-demo",
"capabilities":"hgjorxz",
"loginCookieName": "fossil-XXXXX" /*project-specific cookie name*/
/* TODO: add authTokenExpiry timestamp (cookie expiry time) */
}

We "should" be able to inherit fossil's REMOTE_USER handling without any special support, but that is untested so far. (If you happen to test this, please update this doc with (or otherwise report) your results!)

The response also sets the conventional fossil login cookie (for clients which can make use of cookies), using fossil's existing mechanism for this.

Further requests which require authentication must include the authToken (from the returned payload value) in the request (or it must be available via fossil's standard cookie) or access may (depending on the request) be denied. The authToken may optionally be set in the request envelope or as a GET parameter, and it must be given if the request requires restricted access to a resource. e.g. if reading tickets is disabled for the guest user then all non-guest users must send authentication info in their requests in order to be able to fetch ticket info.

Cookie-aware clients should send the login-generated cookie with each request, in which case they do not need explicitly include the authToken in the JSON envelope/GET arguments. If submitted, the authToken is used, otherwise the cookie, if set, is used. Note that fossil uses a project-dependent cookie name in order to help thwart attacks, so there is no simple mapping of cookie name to auth token. That said, the cookie's value is also the auth token's value.

Special case: when accessing fossil over a local server instance which was started with the --localauth flag, the authToken is ignored (neither validated nor used for any form of authentication).

Anonymous User Logins

The Anonymous user requires special handling because he has a random password.

First fetch the password and the so-called "captcha seed" via this request:

/json/anonymousPassword

It will return a payload in the form:

{
"seed": a_32_bit_unsigned_integer,
"password": "1234abcd" /*hexadecimal STRING*/
}

The "seed" and "password" values of the response payload must be set as the "anonymousSeed" and "password" fields (respectively) of the subsequent login request. The login request is identical to non-anonymous login except that extra "anonymousSeed" property is required.

The password value may be time-limited, and may eventually become invalidated due to old age. This is unspecified.

Potential** (low-probability) bug regarding the seed value:** from what i hear, some unusual JSON platforms don't support full 32-bit precision. If absolutely necessary we could chop off a bit or two from the seed value (if it ever becomes a problem and if DRH blesses it). Or we could just make it a double.

Logout

Status: implemented 20110916

Required privileges: none, but must be logged in

Request:

Or: set the authToken property of the POST envelope (as opposed to the POST.payload)

Or: fossil's normal cookie mechanism is the fallback for the auth token.

Response payload: The same as the "whoami" response, containing the info for the "nobody" user.

This request requires the authentication token, and subsequent logouts without an intervening login will fail with the "auth token not provided" error. In effect this request removes the login entry from the user account, making the token invalid for future requests. In HTTP mode, on success fossil's login cookie is unset by this call.

Whoami

This request fetches the current user's login name, capabilities, and auth token. This can be used to check whether a login is active when the client has not explicitly logged in (e.g. was logged in automatically via a pre-existing cookie).

Status: implemented 20110922

Required privileges: none

Request: /json/whoami

Response payload example:

{
"name": "nobody",
"capabilities": "o",
"authToken": "fossil auth token (only for logged-in users)"
}

The reason authToken is included in the response is because it gives client-side JavaScript code a way of fetching/checking for the auth token at app startup. The token is normally sent as a cookie but parsing the cookies in the browser is tedious, and fossil has a project-dependent cookie name (which complicates parsing a bit). If client code digs the cookie out of the browser, the app still wouldn't know if the token is still valid, whereas whoami won't (or shouldn't!) return an expired auth token. If the request does not include authentication info (via the cookie, GET param, or request envelope) then the response will not contain the authToken property and the user's name will be "nobody".