367 lines
11 KiB
Markdown
367 lines
11 KiB
Markdown
# REST or JSON-RPC authenticator
|
|
|
|
This authenticator permits authentication of Tinode users and creation of Tinode accounts using a separate process as a
|
|
source of truth. For instance, if accounts are managed by corporate LDAP, this service allows handling of Tinode
|
|
authentication using the same LDAP service.
|
|
|
|
This authenticator calls a designated authentication service over HTTP(S) POST. A skeleton implementation of a server
|
|
is provided for reference at [rest-auth](../../../rest-auth/). The requests may be handled either by a single endpoint
|
|
or by separate per-request endpoints.
|
|
|
|
Request and response payloads are formatted as JSON. Some of the request or response fields are context-dependent and
|
|
may be skipped.
|
|
|
|
<!-- TOC depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->
|
|
|
|
- [REST or JSON-RPC authenticator](#rest-or-json-rpc-authenticator)
|
|
- [Configuration](#configuration)
|
|
- [Request](#request)
|
|
- [Response](#response)
|
|
- [Recognized error responses](#recognized-error-responses)
|
|
- [The server must implement the following endpoints:](#the-server-must-implement-the-following-endpoints)
|
|
- [`add` Add new authentication record](#add-add-new-authentication-record)
|
|
- [Sample request](#sample-request)
|
|
- [Sample response (rec values may change)](#sample-response-rec-values-may-change)
|
|
- [`auth` Request for authentication](#auth-request-for-authentication)
|
|
- [Sample request](#sample-request)
|
|
- [Sample response when the account already exists (optional challenge included)](#sample-response-when-the-account-already-exists-optional-challenge-included)
|
|
- [Sample response when the account needs to be created by Tinode](#sample-response-when-the-account-needs-to-be-created-by-tinode)
|
|
- [`checkunique` Checks if provided authentication record is unique.](#checkunique-checks-if-provided-authentication-record-is-unique)
|
|
- [Sample request](#sample-request)
|
|
- [Sample response](#sample-response)
|
|
- [`del` Requests to delete authentication record.](#del-requests-to-delete-authentication-record)
|
|
- [Sample request](#sample-request)
|
|
- [Sample response](#sample-response)
|
|
- [`gen` Generate authentication secret.](#gen-generate-authentication-secret)
|
|
- [Sample request](#sample-request)
|
|
- [Sample response](#sample-response)
|
|
- [`link` Requests server to link new account ID to authentication record.](#link-requests-server-to-link-new-account-id-to-authentication-record)
|
|
- [Sample request](#sample-request)
|
|
- [Sample response](#sample-response)
|
|
- [`upd` Update authentication record.](#upd-update-authentication-record)
|
|
- [Sample request](#sample-request)
|
|
- [Sample response](#sample-response)
|
|
- [`rtagns` Get a list of restricted tag namespaces.](#rtagns-get-a-list-of-restricted-tag-namespaces)
|
|
- [Sample request](#sample-request)
|
|
- [Sample response](#sample-response)
|
|
|
|
<!-- /TOC -->
|
|
|
|
## Configuration
|
|
|
|
Add the following section to the `auth_config` in [tinode.conf](../../tinode.conf):
|
|
|
|
```js
|
|
...
|
|
"auth_config": {
|
|
...
|
|
"rest": {
|
|
// ServerUrl is the URL of the authentication server to call. The URL must be absolute:
|
|
// it must include the scheme, such as http or https, and the host name.
|
|
"server_url": "http://127.0.0.1:5000/",
|
|
// Authentication server is allowed to create new accounts.
|
|
"allow_new_accounts": true,
|
|
// Use separate endpoints, i.e. add request name to serverUrl path when making requests:
|
|
// http://127.0.0.1:5000/add
|
|
"use_separate_endpoints": true
|
|
},
|
|
...
|
|
},
|
|
```
|
|
If you want to use your authenticator **instead** of stock `basic` (login-password) authentication,
|
|
add logical renaming and disable `rest` at the original name:
|
|
```js
|
|
...
|
|
"auth_config": {
|
|
"logical_names": ["basic:rest", "rest:"],
|
|
"rest": { ... },
|
|
...
|
|
},
|
|
...
|
|
```
|
|
|
|
## Request
|
|
|
|
```js
|
|
{
|
|
"endpoint": "auth", // string, one of the endpoints as described below, optional.
|
|
"secret": "Ym9iOmJvYjEyMw==", // authentication secret as provided by the client,
|
|
// base64-encoded bytes, optional.
|
|
"addr": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", // string, IPv4 or IPv6 address of
|
|
// the client making the request, optional.
|
|
"rec": { // authentication record, optional.
|
|
{
|
|
"uid": "LELEQHDWbgY", // user ID, int64 base64-encoded
|
|
"authlvl": "auth", // authentication level
|
|
"lifetime": "10000s", // lifetime of this record in seconds or as time.Duration string;
|
|
// see https://golang.org/pkg/time/#Duration for format.
|
|
"features": 1, // bitmap of features as integer or as a string of feature characters:
|
|
// "validated" (V) or "no login" (L)".
|
|
"tags": ["email:alice@example.com"], // Tags associated with this authentication record.
|
|
"state": "ok", // optional account state.
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Response
|
|
|
|
```js
|
|
{
|
|
"err": "internal", // string, error message in case of an error.
|
|
"rec": { // authentication record.
|
|
... // the same as `request.rec`
|
|
},
|
|
"byteval": "Ym9iOmJvYjEyMw==", // array of bytes, optional
|
|
"ts": "2018-12-04T15:17:02.627Z", // time stamp, optional
|
|
"boolval": true, // boolean value, optional
|
|
"strarr": ["abc", "def"], // array of strings, optoional
|
|
"newacc": { // data to use for creating a new account.
|
|
// Default access mode
|
|
"auth": "JRWPS",
|
|
"anon": "N",
|
|
"public": {...}, // user's public data, see /docs/API.md#trusted-public-and-private-fields
|
|
"trusted": {...}, // user's trusted data, see /docs/API.md#trusted-public-and-private-fields
|
|
"private": {...} // user's private data, see /docs/API.md#trusted-public-and-private-fields
|
|
}
|
|
}
|
|
```
|
|
|
|
## Recognized error responses
|
|
|
|
The error is returned as json:
|
|
|
|
```json
|
|
{ "err": "error-message" }
|
|
```
|
|
|
|
See [here](../../store/types/types.go#L24) for an up to date list of supported error messages.
|
|
|
|
* "internal": database failure or other internal catch-all failure.
|
|
* "malformed": request cannot be parsed or otherwise wrong.
|
|
* "failed": authentication failed (wrong login or password, etc).
|
|
* "duplicate value": duplicate credential, i.e. attempt to create a record with a non-unique login.
|
|
* "unsupported": the operation is not supported.
|
|
* "expired": the secret has expired.
|
|
* "policy": policy violation, e.g. password too weak.
|
|
* "credentials": credentials like email or captcha must be validated.
|
|
* "not found": the object was not found.
|
|
* "denied": the operation is not permitted.
|
|
|
|
## The server must implement the following endpoints:
|
|
|
|
### `add` Add new authentication record
|
|
|
|
This endpoint requests server to add a new authentication record. This endpoint is generally used for account creation.
|
|
If accounts are managed externally, it's likely to be unused and should generally return an error `"unsupported"`.
|
|
|
|
#### Sample request
|
|
```json
|
|
{
|
|
"endpoint": "add",
|
|
"secret": "Ym9iOmJvYjEyMw==",
|
|
"addr": "111.22.33.44",
|
|
"rec": {
|
|
"uid": "LELEQHDWbgY",
|
|
"lifetime": "10000s",
|
|
"features": 2,
|
|
"tags": ["email:alice@example.com"]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Sample response (rec values may change)
|
|
```json
|
|
{
|
|
"rec": {
|
|
"uid": "LELEQHDWbgY",
|
|
"authlvl": "auth",
|
|
"lifetime": "5000s",
|
|
"features": 1,
|
|
"tags": ["email:alice@example.com", "uname:alice"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### `auth` Request for authentication
|
|
|
|
Request to authenticate a user. Client (Tinode) provides a secret, authentication server responds with a user record.
|
|
If this is a very first login and the server manages the accounts, the server may return `newacc` object which will
|
|
be used by client (Tinode) to create the account. The server may optionally return a challenge as `byteval`.
|
|
|
|
#### Sample request
|
|
```json
|
|
{
|
|
"endpoint": "auth",
|
|
"secret": "Ym9iOmJvYjEyMw==",
|
|
"addr": "111.22.33.44"
|
|
}
|
|
```
|
|
|
|
#### Sample response when the account already exists (optional challenge included)
|
|
```json
|
|
{
|
|
"rec": {
|
|
"uid": "LELEQHDWbgY",
|
|
"authlvl": "auth",
|
|
"state": "ok"
|
|
},
|
|
"byteval": "9X6m3tWeBEMlDxlcFAABAAEAbVs"
|
|
}
|
|
```
|
|
|
|
#### Sample response when the account needs to be created by Tinode
|
|
```js
|
|
{
|
|
"rec": {
|
|
"state": "suspended", // Or "ok".
|
|
"authlvl": "auth",
|
|
"lifetime": "5000s",
|
|
"features": 1,
|
|
"tags": ["email:alice@example.com", "uname:alice"]
|
|
},
|
|
"newacc": {
|
|
"auth": "JRWPS",
|
|
"anon": "N",
|
|
"public": {/* see /docs/API.md#trusted-public-and-private-fields */},
|
|
"trusted": {/* see /docs/API.md#trusted-public-and-private-fields */},
|
|
"private": {/* see /docs/API.md#trusted-public-and-private-fields */}
|
|
}
|
|
}
|
|
```
|
|
|
|
### `checkunique` Checks if provided authentication record is unique.
|
|
|
|
Request is used for account creation. If accounts are managed by the server, the server should respond with
|
|
an error `"unsupported"`.
|
|
|
|
#### Sample request
|
|
```json
|
|
{
|
|
"endpoint": "checkunique",
|
|
"secret": "Ym9iOmJvYjEyMw==",
|
|
"addr": "111.22.33.44"
|
|
}
|
|
```
|
|
|
|
#### Sample response
|
|
```json
|
|
{
|
|
"boolval": true
|
|
}
|
|
```
|
|
|
|
### `del` Requests to delete authentication record.
|
|
|
|
If accounts are managed by the server, the server should respond with an error `"unsupported"`.
|
|
|
|
#### Sample request
|
|
```json
|
|
{
|
|
"endpoint": "del",
|
|
"rec": {
|
|
"uid": "LELEQHDWbgY",
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Sample response
|
|
```json
|
|
{}
|
|
```
|
|
|
|
|
|
### `gen` Generate authentication secret.
|
|
|
|
If accounts are managed by the server, the server should respond with an error `"unsupported"`.
|
|
|
|
#### Sample request
|
|
```json
|
|
{
|
|
"endpoint": "gen",
|
|
"rec": {
|
|
"uid": "LELEQHDWbgY",
|
|
"authlvl": "auth",
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Sample response
|
|
```json
|
|
{
|
|
"byteval": "9X6m3tWeBEMlDxlcFAABAAEAbVs",
|
|
"ts": "2018-12-04T15:17:02.627Z",
|
|
}
|
|
```
|
|
|
|
|
|
### `link` Requests server to link new account ID to authentication record.
|
|
|
|
If server requested Tinode to create a new account, this endpoint is used to link the new Tinode user ID with the
|
|
server's authentication record. If linking is successful, the server should respond with a non-empty json.
|
|
|
|
#### Sample request
|
|
```json
|
|
{
|
|
"endpoint": "link",
|
|
"secret": "Ym9iOmJvYjEyMw==",
|
|
"rec": {
|
|
"uid": "LELEQHDWbgY",
|
|
"authlvl": "auth",
|
|
},
|
|
}
|
|
```
|
|
|
|
#### Sample response
|
|
```json
|
|
{}
|
|
```
|
|
|
|
|
|
### `upd` Update authentication record.
|
|
|
|
If accounts are managed by the server, the server should respond with an error `"unsupported"`.
|
|
|
|
#### Sample request
|
|
```json
|
|
{
|
|
"endpoint": "upd",
|
|
"secret": "Ym9iOmJvYjEyMw==",
|
|
"addr": "111.22.33.44",
|
|
"rec": {
|
|
"uid": "LELEQHDWbgY",
|
|
"authlvl": "auth",
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Sample response
|
|
```json
|
|
{}
|
|
```
|
|
|
|
### `rtagns` Get a list of restricted tag namespaces.
|
|
|
|
Server may enforce certain tag namespaces (tag prefixes) to be restricted, i.e. not editable by the user.
|
|
These are also used in Tinode discovery mechanism (e.g. searching for users, contact sync). See
|
|
[API docs](/docs/API.md#fnd-and-tags-finding-users-and-topics) for details.
|
|
|
|
The server may optionally provide a regular expression to validate search tokens before rewriting them as prefixed tags.
|
|
I.e. if server allows only logins of 3-8 ASCII letters and numbers then the regexp could be `^[a-z0-9_]{3,8}$`
|
|
which is base64-encoded as `XlthLXowLTlfXXszLDh9JA==`.
|
|
|
|
#### Sample request
|
|
```json
|
|
{
|
|
"endpoint": "rtagns",
|
|
}
|
|
```
|
|
|
|
#### Sample response
|
|
```json
|
|
{
|
|
"strarr": ["basic", "email", "tel"],
|
|
"byteval": "XlthLXowLTlfXXszLDh9JA=="
|
|
}
|
|
```
|