13 KiB
id, title, sidebar_label, description, keywords, image, hide_title, hide_table_of_contents
| id | title | sidebar_label | description | keywords | image | hide_title | hide_table_of_contents | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| auth | Auth API | Auth | Authentication portion of the Standard Notes API. |
|
/img/logo.png | false | 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" |
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
{
"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" |
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
{
"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" |
string |
The account email. |
Response
{
"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
{
"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
sessionincludes 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:
{
"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:
- When a user signs in
- When a user registers an account
- 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
{
"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:
-
Send a
POSTrequest to/session/token/refresh. The body should contain a JSON paylaod with therefresh_token:POST /session/token/refresh HTTP/1.1 Host: sync.standardnotes.org Authorization: Bearer <access token> { "refresh_token": "R_xxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" } -
The
refresh_tokenis validated on the server. Depending of the circumstances, there should be two outcomes:-
The provided
refresh_tokenis valid. If so, a new pair of tokens is generated and the following JSON response is returned:{ "token": "xxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx", "session": { "refresh_expiration": 1583020800, "refresh_token": "xxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx", } } -
The provided
refresh_tokenis expired. If so, the following JSON response is returned:HTTP Status Code:
400 Bad Request{ "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
sessionthat remains inactive for1 yearwill be terminated, along with alltokens
Tokens
| Name | Type | Expiration |
|---|---|---|
access |
Short-lived | 60 days |
refresh |
Long-lived | 1 year |
- A
refreshtoken is of single-use, while anaccesstoken can be used as long as it is not expired