Skip to content

Conversation

rsempe
Copy link
Collaborator

@rsempe rsempe commented Jul 3, 2025

Description

We currently renew the authorisation token for each request made by users.

This is pointless in most cases because the token expires after 3 hours (2h24 to be exact).

The aim of this PR is to renew the token only when it expires.

@rsempe rsempe force-pushed the misc/renew-token branch from 85bb6b3 to 4d935ce Compare July 3, 2025 16:30
@mariohd
Copy link
Contributor

mariohd commented Jul 3, 2025

TL;DR;
This will not renew the token when expired and will logout the user.

Let's have an example scenario

Consider:
The token is expired.
The user make the request.

Execution:
before_action runs and token is expired, it tries to renew the token.
To renew, it checks if current_user exists and to do that, it calls decoded_token(verify_exp: true).

decoded_token(verify_exp: true) will raise JWT::ExpiredSignature and front will logout the user.

lago-api(dev)> token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTc1MTU2NTI4OX0.cYSMYKB2m6sFF-ed1StpiYKfcBhZJJ9dUYVSrIR6gt0"
=> "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTc1MTU2NTI4OX0.cYSMYKB2m6sFF-ed1StpiYKfcBhZJJ9dUYVSrIR6gt0"
lago-api(dev)> JWT.decode(token, ENV["SECRET_KEY_BASE"], false, {algorithm: "HS256"})
=> [{"sub" => 1, "exp" => 1751565289}, {"alg" => "HS256"}]
lago-api(dev)> JWT.decode(token, ENV["SECRET_KEY_BASE"], true, {algorithm: "HS256"})
(lago-api):5:in '<main>': Signature has expired (JWT::ExpiredSignature)

If we want to renew the token correctly, we have decode with the attribute exp_leeway: <time_in_int>.

lago-api(dev)> JWT.decode(token, ENV["SECRET_KEY_BASE"], true, {algorithm: "HS256", exp_leeway: 30.minutes.to_i})
=> [{"sub" => 1, "exp" => 1751565289}, {"alg" => "HS256"}]

This will renew the token 30 min before it expires.

Copy link
Contributor

@mariohd mariohd left a comment

Choose a reason for hiding this comment

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

def decode_options
{
algorithm: "HS256"
}
end

This will make the token get renewed before expired and actually renew the token.

  def decode_options
    {
      algorithm: "HS256",
      exp_leeway: 30.minutes.to_i
    }
  end

@rsempe
Copy link
Collaborator Author

rsempe commented Jul 4, 2025

@mariohd It works, because @decoded_token is already set previously with verify_exp: false.
And we're calling @decoded_token ||= JWT.decode(...).

But yeah, not really fan of this.
About exp_leeway, this is used apparently to accept a token even if it's expired, no? 🤔

@mariohd
Copy link
Contributor

mariohd commented Jul 4, 2025

Oh you right!

But in that case, we are always decoding with false because the result will be stored at the instance variable and we never decode again with verifications.

About exp_leeway, it's an extra time we allow.

For example, token expires in 2h24m and we have a leeway of 36min. We will consider the token valid for 3h. If the token was expired more than 3h, it would raise the exception and logout the user.

The goal is renew the token after it passed those 2h24 min. I would suggest that we decode the token with true and leeway and then check if the exp is bigger than the current time.

If it is, token is still valid with exp only.
If not, token needs the leeway to be valid, i.e renew it!

@rsempe rsempe merged commit 0477cb2 into main Jul 4, 2025
14 checks passed
@rsempe rsempe deleted the misc/renew-token branch July 4, 2025 12:48
diegocharles pushed a commit that referenced this pull request Jul 11, 2025
## Description

We currently renew the authorisation token for each request made by
users.

This is pointless in most cases because the token expires after 3 hours
(2h24 to be exact).

The aim of this PR is to renew the token only when it expires.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants