Skip to content

In-app Personal Access Token expiry notification

Aishwarya Subramanian requested to merge in-app-expiry-notification into master

What does this MR do?

Problem Statement

With !33783 (merged), system administrators now have an option to toggle Enforcement of Personal Access Token Expiry.

When the enforcement is disabled, users can continue to use their PAT after the expiry date, unless it is explicitly revoked (ref).

Currently, the only way for a user to know if their token requires rotation is by visiting their Personal Access Tokens page.

What does this MR do?

This MR shows an in-app notification for the user when:

  • At least one of their PAT is about to expire (in the next 7 days)-
  • At least one of their PAT has expired-

The purpose of the notification is to encourage the user to create a new token on expiry. The follow-up issue enhances this behavior.

Banner visibility

There is no exclusive capability for token rotation currently. The logic to stop showing the notification is determined as below:

Notification type Logic
Expired token Stop showing if a new token has been created after we started notifying the user about the most recent expired token (i.e. 7 days before expiry)
Expiring token Stop showing if a new token has been created after we started notifying the user about the most recently expiring token

Following is an illustration to depict the notification banner behavior for a single PAT token:

Screen_Shot_2020-06-24_at_12.20.01_PM

When there is more than one token, the notification banner can be depicted as:

Screen_Shot_2020-06-24_at_12.25.06_PM

Please note that in case both Expired and Expiring soon cases are valid, the Expired notification takes precendence.

Banner dismissal

In case a user dismisses the banner, it will not show up for the next 7 days.

Mentions #214723 (closed)

Database Queries

We perform queries to find if the Rotation is required for Expired or Expiring tokens.

In worst case scenario, we may execute a total for 4 queries. Refer to the Cache section for optimization around this.

The query details are detailed below:

To check if rotation is required for Expired tokens, the following 2 queries are executed:
  1. Fetch the expires_at of the most recently expired token:
SELECT
    MAX("personal_access_tokens"."expires_at")
FROM
    "personal_access_tokens"
WHERE
    "personal_access_tokens"."user_id" = 644
    AND "personal_access_tokens"."impersonation" = FALSE
    AND ("personal_access_tokens"."revoked" = FALSE
        OR "personal_access_tokens"."revoked" IS NULL)
    AND (expires_at <= '2020-06-24 16:22:49.021349')
Time: 3.848 ms
  - planning: 0.336 ms
  - execution: 3.512 ms
    - I/O read: 3.414 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 0 from the buffer pool
  - reads: 3 (~24.00 KiB) from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

Execution Plan: https://explain.depesz.com/s/xPLE

  1. Fetch if new PATs have been created after we started notifying the user about the recent expired token
SELECT
    1 AS one
FROM
    "personal_access_tokens"
WHERE
    "personal_access_tokens"."user_id" = 644
    AND "personal_access_tokens"."impersonation" = FALSE
    AND (revoked = FALSE
        AND (expires_at >= NOW()
            OR expires_at IS NULL))
    AND (created_at >= '2020-06-13')
LIMIT 1
Time: 5.876 ms
  - planning: 0.305 ms
  - execution: 5.571 ms
    - I/O read: 5.442 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 0 from the buffer pool
  - reads: 4 (~32.00 KiB) from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

Execution Plan: https://explain.depesz.com/s/kyMF

To check if rotation is required for Expiring tokens, the following 2 queries are executed:
  1. Fetch the expires_at of the most recently expiring token:
SELECT
    MAX("personal_access_tokens"."expires_at")
FROM
    "personal_access_tokens"
WHERE
    "personal_access_tokens"."user_id" = 644
    AND "personal_access_tokens"."impersonation" = FALSE
    AND ("personal_access_tokens"."revoked" = FALSE
        OR "personal_access_tokens"."revoked" IS NULL)
    AND (expires_at > NOW()
        AND expires_at <= '2020-07-01 16:36:12.491102')
Time: 0.731 ms
  - planning: 0.650 ms
  - execution: 0.081 ms
    - I/O read: 0.000 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 3 (~24.00 KiB) from the buffer pool
  - reads: 0 from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

Execution plan: https://explain.depesz.com/s/xq4sl

  1. Fetch if new PATs have been created after we started notifying the user about the recent expiring token
SELECT
    1 AS one
FROM
    "personal_access_tokens"
WHERE
    "personal_access_tokens"."user_id" = 644
    AND "personal_access_tokens"."impersonation" = FALSE
    AND (revoked = FALSE
        AND (expires_at >= NOW()
            OR expires_at IS NULL))
    AND (created_at >= '2020-06-21')
LIMIT 1
Time: 4.862 ms
  - planning: 0.223 ms
  - execution: 4.639 ms
    - I/O read: 4.555 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 0 from the buffer pool
  - reads: 4 (~32.00 KiB) from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

Execution Plan: https://explain.depesz.com/s/OgiT

Caching

Since the notifications are shown is every page, we cache the results of expired? and expires_soon for a user to avoid making database queries for every call.

  • Cache key is based on user_id
  • Valid until end of day
  • Cleared when the user creates a new PAT, or revokes an existing PAT

Screenshots

Token expired

Screen_Shot_2020-06-18_at_5.37.36_PM

Token expiring soon

Screen_Shot_2020-06-18_at_5.36.30_PM

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • [-] Label as security and @ mention @gitlab-com/gl-security/appsec
  • [-] The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • [-] Security reports checked/validated by a reviewer from the AppSec team
Edited by Mayra Cabrera

Merge request reports