Skip to content
This repository was archived by the owner on May 20, 2021. It is now read-only.

Latest commit

 

History

History
234 lines (164 loc) · 9.74 KB

File metadata and controls

234 lines (164 loc) · 9.74 KB

Session management

Introduction

The following document outlines the specifications for the sessions management of the Standard Notes syncing server system.

Overview

The proposed sessions management system will be part of the 004 release, which includes the new API version 20200115 on the server side.

Any account version can use this new API version. That includes 001, 002, 003 and the upcoming 004 version. Because the newest client will support these accounts, and the API version will still be hardcoded to 20200115. But only those who upgrade their account version to 004 will be able to use this new session management feature.

The following message will be shown to them once the account upgrade succeeds:

Your session with the server has been upgraded to the latest version. You will need to re-enter your account password on your other devices to continue syncing.


The SNJS library will be updated to use the new API version.

Models

Session

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
renew_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
  • access_token and refresh_token tokens are both generated using ActiveRecord::SecureToken
  • Sessions are created in the following cases:
    • When a user signs in
    • When a user registers a new account

Valid values for api_version:

  • 20200115

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 that will be available to manage sessions:

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 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

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

Security concerns

The following is a list of several threats and their corresponding mitigations for the proposed sessions system:

Token disclosure

A token may be disclosed to unauthorized users

Mitigation(s):

  • Clients must store tokens safely
  • Clients must use HTTPS when making request with the tokens

Token theft

An attacker may steal a token from the user's device and/or browser

Mitigation(s):

  • Tokens may be stolen in some way. Users have the ability to revoke any stolen tokens if necessary

Token Storage

  • Web: by default, localStorage is used on the web application.

  • Desktop: SNJS storage will be used. It leverages the system keychain through Electron.

  • Mobile: On this platform, the react-native-keychain library is used.


F.A.Q

  • What advantages does the use of a refresh_token bring?

    The sole purpose of the refresh_token is to extend a user session. This is done by generating new tokens, and invalidating the current ones.

    Also, it limits the use of user credentials by not requiring them to obtain a new access_token. This brings greater user experience than having to re-enter credentials every time the access_token is expired.

  • Why not use an access_token with a long expiration time?

    This is a major security risk. An attacker could potentially gain access to the access_token and abuse the user's account until the token is expired.

Terminology

  • JWT: A JSON Web Token is a compact, URL-safe means of representing claims to be transferred between two parties.
  • Access token: Used to access protected resources.
  • Refresh token: Used to obtain new access tokens.
  • API version: The version of the API in use.
  • Account version: The version of the SF specification used when creating this user's account. This value is updated when a user changes their password or updates their security version.

References