Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions backend/sessions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
layout: page
title: Tips
nav_order: 550
parent: Sessions
---

# Sessions

The service that creates and refresh the session is the same: `accessTokenCreate`.

A user can have multiple sessions, typically one per device.

A session can have multiple access tokens. The access tokens have a lifetime of 2 hours,
after which they have to be refreshed. There can be more than one valid access token for a session at the same time,
but we always want to use the most recent one.

If there's no session, we create a temporary user, and a session is created for it.

If a `code` is sent (coming from the login-module by the frontend after authentication), the session is created for the user that logged in,
as described in the section [Creation of a session for a normal user (not a temporary user)](#creation-of-a-session-for-a-normal-user-not-a-temporary-user).

If there's already a session for the user (and no `code` is sent), the process is described in the section [Refreshing the token](#refreshing-the-token).


## Creation of a session for a normal user (not a temporary user)

A session is created when a user logs in.

This is the process of creating a session:

1. We call the login-module to get back:
- the access token
- the refresh token
- the expiration time of the access token
2. If the user doesn't exist in the database, we create it, otherwise we update the `latest_login_at`, `latest_activity_at`, and `latest_profile_sync_at` fields.
3. The session is created in the database with the refresh token. The access token is added to the session.
4. If there are already 10 sessions for the user, or more, we delete the oldest ones, to have a maximum of 10 sessions in database.
5. We return the access token with its expiration time.


### There's a limit of 10 concurrent sessions per user

We limit the number of concurrent sessions per user to 10.

This is to avoid bloating the database with too many sessions.


## Refreshing the token

This is the process of refreshing the token:

1. (Authentication middleware) We check that the token is valid and not expired (same as any authenticated request).
2. We retrieve the most recent token of the session. If the token used to call the refresh is not the most recent one,
we return the most recent token with its expiration time.
3. (From now on, we're working with the most recent token). If the token has been issued less than 5 minutes ago,
we return the token with its expiration time.
4. We get a lock for the session.
5. We call the login-module to refresh the token, with the refresh token of the session, and get back:
- the new access token
- the new refresh token
- the expiration time of the access token
6. We store the refresh token in the session, and store the new access token.
7. We delete expired old tokens for the session.
Comment on lines +58 to +64
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You get a lock but you don't say when you release it.
Getting a lock for a remote access is dangerous (if you loose request, you process is killed, ...), how do you protect against that?



### Only the most recent token can be used to refresh the token

If another token is used to refresh the token, the current most recent token is returned with its expiration time.


### A token can only be refreshed once

Because a token can only be refreshed by the most recent token, it implies that a token can only be refreshed once.


### A token can only be refreshed if it's not expired

If an expired token is used to refresh the token, access defined error is returned.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If an expired token is used to refresh the token, access defined error is returned.
If an expired token is used to refresh the token, access denied error is returned.

?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix, it's a 401 unauthorized error



### A token can only be refreshed 5 minutes after it was issued

It's not possible to refresh a token that was issued less than 5 minutes ago.

This was done because:
- There can be many tabs open in the browser. Each tab will ask for a refresh of the token at roughly the same time.
We don't want to have many refreshes going at the same time: it's completely useless.


### There a maximum number of access tokens for a session that can be present in database at one moment

This follows from the facts that:
- a token can only be refreshed once
- a token can only be refreshed after 5 minutes
- expired tokens are deleted on refresh

Since tokens are valid for 2 hours, we can have a maximum of 2 hours / 5 minutes = 24 tokens in the database at the same time.


## Logout

When a user logs out, the session and all the related tokens are deleted.


## Edge cases with the frontend

The tricky edge cases come from the frontend when:
- tabs are frozen when inactive and in background for some time
- the device goes into sleep


### What happens if the frontend tries to refresh a token that was already refreshed (that is not the most recent one)?

It will receive the most recent token with its expiration time.

With the expiration time, it will know when the token has to be refreshed again. Which can be right now.


### What happens when many tabs make a refresh request at the same time?

There is a lock for the session for the refresh process.

1. The first request gets the lock, and the token gets refreshed.
2. The other requests (already made before the refresh was done), are using tokens that are not the most recent anymore.
The most recent token (just refreshed) will be sent with its expiration time.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not clear, it will not be sent to the other requests, so it is not related with (2).

3. There might be other refresh requests that are made after the first one is done. Those will use the most recent token,
but since this token was issued less than 5 minutes ago, the token will simply be returned with its expiration time.