Skip to main content

Auth API

POST /auth#

Registers a new user

apistringThe API version to use. Must not be null, otherwise oldest API version used. Latest value is "20200115"
createdstringInteger timestamp representing the date the client generated the account's encryption keys. Example "1622494310383"
emailstringThe account email.
ephemeralbooleanWhether the initial session created for this account is ephemeral ("Stay signed in" unchecked).
identifierstringShould equal the account email.
originationstringShould equal "registration"
passwordstringThe server password generated by the client from the user's master password.
pw_noncestringThe nonce generated by the client for the user's encryption key.
versionstringThe 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.

apistringThe API version to use. Must not be null, otherwise oldest API version used. Latest value is "20200115"
emailstringThe account email.
ephemeralbooleanWhether the session created for this account is ephemeral ("Stay signed in" unchecked).
passwordstringThe 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.

apistringThe API version to use. Must not be null, otherwise oldest API version used. Latest value is "20200115"
emailstringThe account email.

Response#

{
"identifier": "foo@example.com",
"pw_nonce": "d97ed41c581fe8c3e0dce7d2ee72afcb63f9f461ae875bae66e30ecf3d952900",
"version": "004"
}

POST /auth/change_pw#

Changes a user's password.

apistringThe API version to use. Must not be null, otherwise oldest API version used. Latest value is "20200115"
createdstringInteger timestamp representing the date the client generated the account's new encryption keys. Example "1622494310383"
identifierstringThe account email.
originationstringShould equal "password-change"
current_passwordstringThe old server password generated by the client from the user's master password.
new_passwordstringThe new server password generated by the client from the user's master password.
pw_noncestringThe nonce generated by the client for the user's encryption key.
versionstringThe 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#

FieldTypeDescription
uuidstringUnique identifier of the session
user_uuidstringUnique identifier of the user
user_agentstringThe user agent used to create the session
api_versionstringThe server API version used to create the session
access_tokenstringThe access token used to authenticate requests
refresh_tokenstringThe refresh token used to extend tokens
access_expirationdatetimeThe expiration time of the access token
renew_expirationdatetimeThe expiration time of the refresh token
created_atdatetimeDate and time of creation of the session
updated_atdatetimeLast 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:

MethodURLParamsDescriptionSuccessful response code
POST/auth/sign_outNoneTerminates the current session204
DELETE/sessionuuidTerminates the specified session by UUID204
DELETE/sessionsNoneTerminates all sessions, except the current one204
GET/sessionsNoneLists all sessions active sessions200
POST/session/token/refreshrefresh_tokenObtains new pair of access_token and refresh_token200

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:

  1. When a user signs in
  2. When a user registers an account
  3. 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:

  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"
    }
  2. 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:

      {
      "token": "xxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx",
      "session": {
      "refresh_expiration": 1583020800,
      "refresh_token": "xxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx",
      }
      }
    2. The provided refresh_token is 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 session that remains inactive for 1 year will be terminated, along with all tokens

Tokens#

NameTypeExpiration
accessShort-lived60 days
refreshLong-lived1 year
  • A refresh token is of single-use, while an access token can be used as long as it is not expired
Last updated on