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. 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.
- REST or JSON-RPC authenticator
- Configuration
- Request
- Response
- Recognized error responses
- The server must implement the following endpoints:
add
Add new authentication recordauth
Request for authenticationcheckunique
Checks if provided authentication record is unique.del
Requests to delete authentication record.gen
Generate authentication secret.link
Requests server to link new account ID to authentication record.upd
Update authentication record.rtagns
Get a list of restricted tag namespaces.
Add the following section to the auth_config
in tinode.conf:
...
"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:
...
"auth_config": {
"logical_names": ["basic:rest", "rest:"],
"rest": { ... },
...
},
...
{
"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.
}
}
}
{
"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
}
}
The error is returned as json:
{ "err": "error-message" }
See here 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.
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"
.
{
"endpoint": "add",
"secret": "Ym9iOmJvYjEyMw==",
"addr": "111.22.33.44",
"rec": {
"uid": "LELEQHDWbgY",
"lifetime": "10000s",
"features": 2,
"tags": ["email:alice@example.com"]
}
}
{
"rec": {
"uid": "LELEQHDWbgY",
"authlvl": "auth",
"lifetime": "5000s",
"features": 1,
"tags": ["email:alice@example.com", "uname:alice"]
}
}
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
.
{
"endpoint": "auth",
"secret": "Ym9iOmJvYjEyMw==",
"addr": "111.22.33.44"
}
{
"rec": {
"uid": "LELEQHDWbgY",
"authlvl": "auth",
"state": "ok"
},
"byteval": "9X6m3tWeBEMlDxlcFAABAAEAbVs"
}
{
"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 */}
}
}
Request is used for account creation. If accounts are managed by the server, the server should respond with
an error "unsupported"
.
{
"endpoint": "checkunique",
"secret": "Ym9iOmJvYjEyMw==",
"addr": "111.22.33.44"
}
{
"boolval": true
}
If accounts are managed by the server, the server should respond with an error "unsupported"
.
{
"endpoint": "del",
"rec": {
"uid": "LELEQHDWbgY",
}
}
{}
If accounts are managed by the server, the server should respond with an error "unsupported"
.
{
"endpoint": "gen",
"rec": {
"uid": "LELEQHDWbgY",
"authlvl": "auth",
}
}
{
"byteval": "9X6m3tWeBEMlDxlcFAABAAEAbVs",
"ts": "2018-12-04T15:17:02.627Z",
}
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.
{
"endpoint": "link",
"secret": "Ym9iOmJvYjEyMw==",
"rec": {
"uid": "LELEQHDWbgY",
"authlvl": "auth",
},
}
{}
If accounts are managed by the server, the server should respond with an error "unsupported"
.
{
"endpoint": "upd",
"secret": "Ym9iOmJvYjEyMw==",
"addr": "111.22.33.44",
"rec": {
"uid": "LELEQHDWbgY",
"authlvl": "auth",
}
}
{}
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 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==
.
{
"endpoint": "rtagns",
}
{
"strarr": ["basic", "email", "tel"],
"byteval": "XlthLXowLTlfXXszLDh9JA=="
}