/api/v1/oauth_clients
Seeding of the OAuth clients declared in the server configuration. Defined in
crates/rest/src/oauth_clients.rs.
Internal. This route is not authenticated with a user credential at all:
it requires the Etwin-Internal-Auth header, whose value is the internal key
of the running instance. It exists so that the boot sequence can register the
clients of [seed.app] against a backend that is already serving, and it is
not part of the surface an application may use.
The path is oauth_clients, with an underscore, as it is mounted in
crates/rest/src/lib.rs.
An application that wants to use OAuth should read Eternaltwin for OAuth; the browser flow itself is listed under Internal endpoints.
POST /
Creates the client, or updates it in place when one already exists under the
same key or id. Answers with the stored client.
Headers
| Header | Value |
|---|---|
Etwin-Internal-Auth | The instance's internal authentication key. |
Body
| Field | Type | Meaning |
|---|---|---|
id | UUID or null | Pin the client to this identifier. Omit to let the server allocate one. |
key | string | Stable handle, ^[a-z_][a-z0-9_]{1,31}@clients$. |
display_name | string | Shown on the consent screen, ^[A-Za-z_ ()-]{2,32}$. |
app_uri | URL | Homepage of the application. |
callback_uri | URL | Where an authorization is redirected back to. |
secret | string | Client secret, as lowercase hexadecimal of its UTF-8 bytes. |
allowed_scopes | object or absent | The scopes this client may request. |
allowed_scopes is an object of four booleans, base, forum_read,
forum_write and forum_moderate, not the space-separated string of the
OAuth scope parameter.
Omitting allowed_scopes leaves the client's current allowance alone, and on
an insert stores no allowance at all — read back as base alone. An upsert
that does not mention scopes never widens what a client may ask for.
Example
POST /api/v1/oauth_clients
Content-Type: application/json
Etwin-Internal-Auth: dev
{
"id": "e1484871-29a7-41b1-8c3f-0aa334be1c40",
"key": "alpha_dev@clients",
"display_name": "alpha",
"app_uri": "http://alpha.localhost/",
"callback_uri": "http://alpha.localhost/oauth/callback",
"secret": "646576",
"allowed_scopes": {
"base": true,
"forum_read": true,
"forum_write": true,
"forum_moderate": false
}
}
{
"type": "OauthClient",
"id": "e1484871-29a7-41b1-8c3f-0aa334be1c40",
"key": "alpha_dev@clients",
"display_name": "alpha",
"app_uri": "http://alpha.localhost/",
"callback_uri": "http://alpha.localhost/oauth/callback",
"owner": null
}
The response never carries the secret, hashed or otherwise, and owner is
null for a system client: it belongs to the instance rather than to a
member.
Errors
| Status | Body | When |
|---|---|---|
| 401 | {"error": "missing internal authentication header"} | No Etwin-Internal-Auth. |
| 403 | {"error": "invalid internal authentication key"} | Wrong key. |
| 500 | {"error": "internal error"} | The store refused the upsert. |