From 4f49b16079b27d7ce633619e4cddfdf2bffbc952 Mon Sep 17 00:00:00 2001 From: cashmere Date: Fri, 4 Sep 2026 09:05:24 +0200 Subject: initial commit --- www/json-api/api-auth.md | 271 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 www/json-api/api-auth.md (limited to 'www/json-api/api-auth.md') diff --git a/www/json-api/api-auth.md b/www/json-api/api-auth.md new file mode 100644 index 0000000..96854da --- /dev/null +++ b/www/json-api/api-auth.md @@ -0,0 +1,271 @@ +# JSON API: X +([⬑JSON API Index](index.md)) + +Jump to: + +* [Introduction](#intro) +* [Capabilities (Access Rights)](#capabilities) +* [Login](#login) + * [Anonymous User Logins](#login-anonymous) +* [Logout](#logout) +* [Whoami](#whoami) + +--- + + +# 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 responses 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](#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:** + +```json +{ +"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) + +- `/json/login?name=...&password=...` +- `/json/login?n=...&p=...` (for symmetry with existing login mechanism) + +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) + +```json +{ +"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 to 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: + +```json +{ +"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:** + + - `/json/logout?authToken=...token fetched by /login` + +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:** + +```json +{ +"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". -- cgit v1.3.1