fix: docs build (#1203)
This commit is contained in:
303
packages/docs/docs/specification/auth.md
Normal file
303
packages/docs/docs/specification/auth.md
Normal file
@@ -0,0 +1,303 @@
|
||||
---
|
||||
id: auth
|
||||
title: Auth API
|
||||
sidebar_label: Auth
|
||||
description: Authentication portion of the Standard Notes API.
|
||||
keywords:
|
||||
- standard notes
|
||||
- docs
|
||||
- notes app
|
||||
- end-to-end encryption
|
||||
- sync
|
||||
image: /img/logo.png
|
||||
hide_title: false
|
||||
hide_table_of_contents: false
|
||||
---
|
||||
|
||||
### POST /auth
|
||||
|
||||
**Registers a new user**
|
||||
|
||||
| | | |
|
||||
|-------------|---------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| api | `string` | The API version to use. Must not be null, otherwise oldest API version used. Latest value is "20200115" |
|
||||
| created | `string` | Integer timestamp representing the date the client generated the account's encryption keys. Example "1622494310383" |
|
||||
| email | `string` | The account email. |
|
||||
| ephemeral | `boolean` | Whether the initial session created for this account is ephemeral ("Stay signed in" unchecked). |
|
||||
| identifier | `string` | Should equal the account email. |
|
||||
| origination | `string` | Should equal "registration" |
|
||||
| password | `string` | The server password generated by the client from the user's master password. |
|
||||
| pw_nonce | `string` | The nonce generated by the client for the user's encryption key. |
|
||||
| version | `string` | The protocol version the client used to generate the user's encryption key. Latest is "004". |
|
||||
|
||||
#### Response
|
||||
|
||||
```JSON
|
||||
{
|
||||
"session": {
|
||||
"access_token": "1:457b1f4b-88c2-4328-bf32-fe7dd9431d62:WwKgTEDUoEhxECu6",
|
||||
"refresh_token": "1:457b1f4b-88c2-4328-bf32-fe7dd9431d62:G-qEoZsFtoj~RLL-",
|
||||
"access_expiration": 1627678312000,
|
||||
"refresh_expiration": 1654051238000
|
||||
},
|
||||
"key_params": {
|
||||
"created": "1622494310383",
|
||||
"identifier": "foo@example.com",
|
||||
"origination": "registration",
|
||||
"pw_nonce": "d97ed41c581fe8c3e0dce7d2ee72afcb63f9f461ae875bae66e30ecf3d952900",
|
||||
"version": "004"
|
||||
},
|
||||
"user": {
|
||||
"uuid": "682f9deb-b75f-4d97-91fa-6fd82a482db1",
|
||||
"email": "foo@example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### POST /auth/sign_in
|
||||
|
||||
**Authenticates a user and returns a session.**
|
||||
|
||||
| | | |
|
||||
|-------------|---------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| api | `string` | The API version to use. Must not be null, otherwise oldest API version used. Latest value is "20200115" |
|
||||
| email | `string` | The account email. |
|
||||
| ephemeral | `boolean` | Whether the session created for this account is ephemeral ("Stay signed in" unchecked). |
|
||||
| password | `string` | The server password generated by the client from the user's master password. |
|
||||
|
||||
#### Response
|
||||
|
||||
```JSON
|
||||
{
|
||||
"session": {
|
||||
"access_token": "1:ee03808d-dd05-417c-9c87-d471e49bcc49:Q~-UoIpDhdtkii_t",
|
||||
"refresh_token": "1:ee03808d-dd05-417c-9c87-d471e49bcc49:Jn8UWzeHx2H5nZI5",
|
||||
"access_expiration": 1627678779000,
|
||||
"refresh_expiration": 1654051705000
|
||||
},
|
||||
"key_params": {
|
||||
"created": "1622494310383",
|
||||
"identifier": "foo@example.com",
|
||||
"origination": "registration",
|
||||
"pw_nonce": "d97ed41c581fe8c3e0dce7d2ee72afcb63f9f461ae875bae66e30ecf3d952900",
|
||||
"version": "004"
|
||||
},
|
||||
"user": {
|
||||
"uuid": "682f9deb-b75f-4d97-91fa-6fd82a482db1",
|
||||
"email": "foo@example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /auth/params
|
||||
|
||||
**Queries the parameters used for key generation for an email address. Queried before signing into an account.**
|
||||
|
||||
| | | |
|
||||
|-------------|---------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| api | `string` | The API version to use. Must not be null, otherwise oldest API version used. Latest value is "20200115" |
|
||||
| email | `string` | The account email. |
|
||||
|
||||
#### Response
|
||||
|
||||
```JSON
|
||||
{
|
||||
"identifier": "foo@example.com",
|
||||
"pw_nonce": "d97ed41c581fe8c3e0dce7d2ee72afcb63f9f461ae875bae66e30ecf3d952900",
|
||||
"version": "004"
|
||||
}
|
||||
```
|
||||
|
||||
### POST /auth/change_pw
|
||||
|
||||
**Changes a user's password.**
|
||||
|
||||
| | | |
|
||||
|-------------|---------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| api | `string` | The API version to use. Must not be null, otherwise oldest API version used. Latest value is "20200115" |
|
||||
| created | `string` | Integer timestamp representing the date the client generated the account's new encryption keys. Example "1622494310383" |
|
||||
| identifier | `string` | The account email. |
|
||||
| origination | `string` | Should equal "password-change" |
|
||||
| current_password | `string` | The old server password generated by the client from the user's master password. |
|
||||
| new_password | `string` | The new server password generated by the client from the user's master password. |
|
||||
| pw_nonce | `string` | The nonce generated by the client for the user's encryption key. |
|
||||
| version | `string` | The protocol version the client used to generate the user's encryption key. Latest is "004". |
|
||||
|
||||
#### Response
|
||||
|
||||
```JSON
|
||||
{
|
||||
"session": {
|
||||
"access_token": "1:27d4fd8f-b730-4e0a-afd3-1600fb466aaa:HMgmZwV5k5ePt0vj",
|
||||
"refresh_token": "1:27d4fd8f-b730-4e0a-afd3-1600fb466aaa:wHuTeOB-qWGP3AE3",
|
||||
"access_expiration": 1627679129000,
|
||||
"refresh_expiration": 1654052055000
|
||||
},
|
||||
"key_params": {
|
||||
"created": "1622494310383",
|
||||
"identifier": "foo@example.com",
|
||||
"origination": "password-change",
|
||||
"pw_nonce": "be1974ff6fb1c541aa8c71fd3c66851b6492cf224b661c72daf44e0bef3096bb",
|
||||
"version": "004"
|
||||
},
|
||||
"user": {
|
||||
"uuid": "682f9deb-b75f-4d97-91fa-6fd82a482db1",
|
||||
"email": "foo@example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Sessions
|
||||
|
||||
### Session Model
|
||||
|
||||
| Field | Type | Description |
|
||||
|----------------|-----------|---------------------------------------------------|
|
||||
| uuid | `string` | Unique identifier of the session |
|
||||
| user_uuid | `string` | Unique identifier of the user |
|
||||
| user_agent | `string` | The user agent used to create the session |
|
||||
| api_version | `string` | The server API version used to create the session |
|
||||
| access_token | `string` | The access token used to authenticate requests |
|
||||
| refresh_token | `string` | The refresh token used to extend tokens |
|
||||
| access_expiration | `datetime` | The expiration time of the access token |
|
||||
| refresh_expiration | `datetime` | The expiration time of the refresh token |
|
||||
| created_at | `datetime` | Date and time of creation of the session |
|
||||
| updated_at | `datetime` | Last updated date and time of the session |
|
||||
|
||||
- Each `session` includes the API version they were created with. This way we can deny sessions for a given API version if we detect a vulnerability with that version in the future
|
||||
- Sessions are created in the following cases:
|
||||
- When a user signs in
|
||||
- When a user registers a new account
|
||||
|
||||
---
|
||||
|
||||
### Authenticated requests
|
||||
|
||||
The `Authorization` request header field is used by clients to make authenticated request. `Bearer` is the only authentication scheme allowed.
|
||||
|
||||
The client must send the `access` token generated by the session, in the `Authorization` header. For example:
|
||||
|
||||
```
|
||||
GET /sessions HTTP/1.1
|
||||
Host: sync.standardnotes.org
|
||||
Authorization: Bearer <access token>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Below is a list of endpoints related to session management:
|
||||
|
||||
| Method | URL | Params | Description | Successful response code |
|
||||
|-----------|--------------------------|---------------------|--------------------------------------------------------|--------------------------|
|
||||
|`POST` | /auth/sign_out | *None* | Terminates the current session | `204` |
|
||||
|`DELETE` | /session | **uuid** | Terminates the specified session by UUID | `204` |
|
||||
|`DELETE` | /sessions | *None* | Terminates all sessions, except the current one | `204` |
|
||||
|`GET` | /sessions | *None* | Lists all sessions active sessions | `200` |
|
||||
|`POST` | /session/token/refresh | **refresh_token** | Obtains new pair of `access_token` and `refresh_token` | `200` |
|
||||
|
||||
A successful request to `GET /sessions` returns the following JSON response:
|
||||
|
||||
```json
|
||||
{
|
||||
"sessions": [
|
||||
{
|
||||
"uuid": "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx",
|
||||
"user_agent": "<product> / <product-version> <comment>",
|
||||
"api_version": "xxxxyyzz",
|
||||
"current": "<boolean>",
|
||||
"created_at": "2020-01-01T00:00:00.000Z"
|
||||
}
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Obtaining tokens
|
||||
|
||||
Tokens can be obtained every time the user performs any of the following actions:
|
||||
|
||||
1. When a user signs in
|
||||
1. When a user registers an account
|
||||
1. When the tokens are refreshed
|
||||
|
||||
#### Refreshing tokens
|
||||
|
||||
When an expired `access_token` is provided in the `Authorization` HTTP header, the following JSON response is returned:
|
||||
|
||||
HTTP Status Code: `498 Expired Access Token`
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"tag": "expired-access-token",
|
||||
"message": "The provided access token has expired."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To continue accessing resources, the `access_token` must be refreshed. That is, the current `access_token` is replaced with a new one with an extended expiration date.
|
||||
|
||||
To refresh an `access_token`, a valid `refresh_token` is needed. This `refresh_token` must meet the following requirements:
|
||||
|
||||
- It should belong to the session of the `access_token`
|
||||
- It should not be expired
|
||||
|
||||
Since the `refresh_token` is of single-use, a new `refresh_token` is obtained when the `access_token` is refreshed.
|
||||
|
||||
Refreshing tokens is a process that is transparent to the user, meaning that the client will perform the requests to keep valid tokens without user intervention.
|
||||
|
||||
Here's how to refresh tokens:
|
||||
|
||||
1. Send a `POST` request to `/session/token/refresh`. The body should contain a JSON paylaod with the `refresh_token`:
|
||||
```
|
||||
POST /session/token/refresh HTTP/1.1
|
||||
Host: sync.standardnotes.org
|
||||
Authorization: Bearer <access token>
|
||||
|
||||
{
|
||||
"refresh_token": "R_xxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"
|
||||
}
|
||||
```
|
||||
|
||||
1. The `refresh_token` is validated on the server. Depending of the circumstances, there should be two outcomes:
|
||||
1. The provided `refresh_token` is valid. If so, a new pair of tokens is generated and the following JSON response is returned:
|
||||
```json
|
||||
{
|
||||
"token": "xxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx",
|
||||
"session": {
|
||||
"refresh_expiration": 1583020800,
|
||||
"refresh_token": "xxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx",
|
||||
}
|
||||
}
|
||||
```
|
||||
1. The provided `refresh_token` is expired. If so, the following JSON response is returned:
|
||||
|
||||
HTTP Status Code: `400 Bad Request`
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"tag": "expired-refresh-token",
|
||||
"message": "The refresh token has expired."
|
||||
}
|
||||
}
|
||||
```
|
||||
User must start a new session by re-entering their credentials.
|
||||
|
||||
### Expiration
|
||||
|
||||
#### Sessions
|
||||
|
||||
Sessions should be terminated after a period of inactivity. This is for best security practices.
|
||||
|
||||
`Long-lived sessions` are a good choice for our use case, because it can build a better user experience than expiring sessions for a short idle-timeout.
|
||||
|
||||
- A `session` that remains inactive for `1 year` will be terminated, along with all `tokens`
|
||||
|
||||
#### Tokens
|
||||
|
||||
| Name | Type | Expiration |
|
||||
|-----------|-------------|---------------|
|
||||
| `access` | Short-lived | `60 days` |
|
||||
| `refresh` | Long-lived | `1 year` |
|
||||
|
||||
- A `refresh` token is of single-use, while an `access` token can be used as long as it is not expired
|
||||
Reference in New Issue
Block a user