diff options
-rw-r--r-- | meta.sr.ht/api.md | 10 | ||||
-rw-r--r-- | meta.sr.ht/delegated-oauth.md | 3 | ||||
-rw-r--r-- | meta.sr.ht/oauth-api.md | 173 | ||||
-rw-r--r-- | meta.sr.ht/user-api.md | 3 |
4 files changed, 187 insertions, 2 deletions
diff --git a/meta.sr.ht/api.md b/meta.sr.ht/api.md index 954bc42..d291a03 100644 --- a/meta.sr.ht/api.md +++ b/meta.sr.ht/api.md @@ -1,2 +1,8 @@ -There is an API, but it's probably going to change a lot so I don't really feel -like documenting it here. +# meta.sr.ht API + +There are two primary APIs for accessing meta.sr.ht programmatically: + +- [OAuth API](oauth-api.md): authenticating across all sr.ht services +- [User API](user-api.md): accessing information about the authenticated user + +Each is documented on their respective pages. diff --git a/meta.sr.ht/delegated-oauth.md b/meta.sr.ht/delegated-oauth.md new file mode 100644 index 0000000..56a6895 --- /dev/null +++ b/meta.sr.ht/delegated-oauth.md @@ -0,0 +1,3 @@ +# Delegated OAuth + +TODO: write this doc diff --git a/meta.sr.ht/oauth-api.md b/meta.sr.ht/oauth-api.md new file mode 100644 index 0000000..a7dc25e --- /dev/null +++ b/meta.sr.ht/oauth-api.md @@ -0,0 +1,173 @@ +# meta.sr.ht OAuth API + +The meta.sr.ht OAuth implementation is similar to other OAuth implementations, +but has some extensions - notably, support for *delegated authentication*. + +# Supported authentication profiles + +There are various ways, in order of complexity and flexibility, of +authenticating with the APIs around sr.ht. Your goal is to obtain an **access +token**, which can be used to authenticate with sr.ht APIs. + +## Personal Access Tokens + +The easiest and fastest way to authenticate with sr.ht is to [create a personal +access token](https://meta.sr.ht/oauth/personal-token). This token will have +unrestricted access to all sr.ht APIs and can be used like a normal access token +to authenticate API requests (see [Authenticating API +requests](#authenticating-api-requests)). + +**Warning**: do not give your personal access tokens to third parties. Any third +party which encourages you to give them a personal access token should instead +develop an OAuth client as described in the next section. + +## OAuth Clients + +Personal access tokens are suitable for authenticating yourself, but if you +intend to provide software that other sr.ht users can log into, you should +[create an OAuth client](https://meta.sr.ht/oauth/register) instead. The OAuth +flow allows end-users to grant your client only the privileges it requires to +execute its duties and to revoke this access at any time. This is accomplished +through an **OAuth exchange**: + +1. Direct the user (in a web browser) to a special page on meta.sr.ht where we + present them with the permissions you're asking for and they provide consent. +2. The user is redirected back to your application's **base redirect URI**. We + will add an **exchange token** to the query string. +3. Your application sends an HTTP request directly to meta.sr.ht using this + exchange token and your client credentials to obtain an access token. + +To this end, you need to have an HTTP server running somewhere (`localhost` is +suitable for testing) that the user can be redirected to upon consenting to the +permissions you requested. Decide on a URL we can redirect the user to in your +application, and fill out the base redirect URI accordingly. + +Upon submitting the form, your **client ID** and **client secret** will be shown +to you. **Record your client secret now**. It will not be shown to you again. + +### The OAuth consent page + +To start the exchange, direct the user to the following URL: + + https://meta.sr.ht/oauth/authorize + +Provide the following parameters in the query string: + +<dl> + <dt>client_id</dt> + <dd>The client ID assigned to you in the previous step.</dd> + <dt>scopes</dt> + <dd>A list of scopes you're requesting - see next section.</dd> + <dt>state</dt> + <dd>Optional: an arbitrary string - see notes.</dd> + <dt>redirect_uri</dt> + <dd>Optional: your application URI for redirect the user to - see notes.</dd> +</dl> + +The optional `state` field is returned to you after the redirect. One example +use-case of this field is generating a token before directing the user to the +authorization page and validating it after the redirect, to prevent users from +initiating the OAuth flow without you. Most users don't need to worry about +this. + +The optional `redirect_uri` field can allow you to specify a route more precise +than the base URI affords, for example to include a user ID. The `redirect_uri` +must begin with the `base_uri`. + +### OAuth scopes + +API endpoints on sr.ht generally require an access token valid for a specific +*scope* to be used. This allows you to only request access to the subset of the +API that you require. Scopes are written with the following notation(s): + + name + name:access + service/name:access + +`name` is the name of the OAuth scope, which is documented alongside the API +endpoints which require it (e.g. `/api/user/profile` requires the `profile` +scope). `access` is either `read` or `write`, and may be omitted (default: +`read`). `service` is the name of the service for which the scope is applicable. +If omitted, the default is `meta.sr.ht`. The following services are also +recognized: + +- `git.sr.ht` +- `builds.sr.ht` +- `todo.sr.ht` +- `lists.sr.ht` +- `man.sr.ht` +- `dispatch.sr.ht` + +For third-party services using delegated authentication, the service should be +set to their OAuth client ID. + +### The application redirect + +Once the user consents, they will be redirected to your `redirect_uri`, or the +`base_uri` for your client if unspecified. We will update your redirect URI with +some additional query string parameters you can use for the next steps: + +<dl> + <dt>exchange</dt> + <dd>An exchange token you can use to obtain an access token in the next step.</dd> + <dt>scopes</dt> + <dd>The list of OAuth scopes the user consented to.</dd> + <dt>error</dt> + <dd>If present, indicates that an error occurred in the process - see notes.</dd> + <dt>details</dt> + <dd>If present, a human friendly error string, if that human is an engineer.</dd> +</dl> + +Possible values for `error`: + +- `invalid_redirect` +- `invalid_scope` +- `user_declined` + +**Important**: the user is able to **edit** the scopes you've requested before +consenting. You must handle the case where the scopes returned in the redirect +do not match the scopes you requested. + +### Obtaining an access token + +Once your application retrieves the exchange token from the redirect, you can +submit an HTTP POST request to `https://meta.sr.ht/oauth/exchange`. The request +body should be `application/json` and include the following parameters: + +<dl> + <dt>client_id</dt> + <dd>The client ID assigned to you when you registered the application.</dd> + <dt>client_secret</dt> + <dd>The client secret assigned to you when you registered the application.</dd> + <dt>exchange</dt> + <dd>The exchange token issued in the previous step.</dd> +</dl> + +You will receive a response like this: + +```json +{ + "token": "your access token", + "expires": "%Y-%m-%dT%H:%M:%S" +} +``` + +You can now use this token for [Authenticating API +requests](#authenticating-api-requests). + +## Delegated OAuth + +Delegated OAuth is where you delegate authentication for your application +entirely to meta.sr.ht, both for logins *and* your own API. This is used +internally between sr.ht services but is also available to third parties. +[Delegated OAuth](delegated-oauth.md) is documented on its own page. + +# Authenticating API requests + +Authenticating your API request is simple once you have an access token. You +just need to set the `Authorization` header to `token your-access-token`. For +example: + + curl \ + -H Authorization:'token your-access-token' \ + https://meta.sr.ht/api/user/profile diff --git a/meta.sr.ht/user-api.md b/meta.sr.ht/user-api.md new file mode 100644 index 0000000..5606b4b --- /dev/null +++ b/meta.sr.ht/user-api.md @@ -0,0 +1,3 @@ +# meta.sr.ht user API + +TODO: write this doc |