From 12099199b7dfd61c8769494d60b8ab29e3733022 Mon Sep 17 00:00:00 2001 From: Emmanuel Gautier Date: Sat, 5 Oct 2024 19:15:01 +0200 Subject: [PATCH] feat: set the JWT expiration time in the future if the token has expired --- jwt/jwt_writer.go | 13 +++++++++ jwt/jwt_writer_test.go | 62 ++++++++++++++++++------------------------ 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/jwt/jwt_writer.go b/jwt/jwt_writer.go index 115a808..577b6e8 100644 --- a/jwt/jwt_writer.go +++ b/jwt/jwt_writer.go @@ -2,6 +2,7 @@ package jwt import ( "errors" + "time" "github.com/golang-jwt/jwt/v5" ) @@ -24,6 +25,18 @@ func NewJWTWriter(token string) (*JWTWriter, error) { } func (j *JWTWriter) SignWithMethodAndKey(method jwt.SigningMethod, key interface{}) (string, error) { + // If the token has expired, we will extend it for 5 minutes so that it can pass the verification + expirationTime, err := j.Token.Claims.GetExpirationTime() + if err == nil && expirationTime != nil && expirationTime.Before(time.Now()) { + claims := j.Token.Claims.(jwt.MapClaims) + newClaims := jwt.MapClaims{} + for k, v := range claims { + newClaims[k] = v + } + newClaims["exp"] = time.Now().Add(5 * time.Minute).Unix() + j.Token.Claims = newClaims + } + newToken := jwt.NewWithClaims(method, j.Token.Claims) tokenString, err := newToken.SignedString(key) diff --git a/jwt/jwt_writer_test.go b/jwt/jwt_writer_test.go index 185da22..0d35cb9 100644 --- a/jwt/jwt_writer_test.go +++ b/jwt/jwt_writer_test.go @@ -8,65 +8,57 @@ import ( "github.com/stretchr/testify/assert" ) -func TestJWTWriter_SignWithMethodAndRandomKey_WhenSigningMethodIsHS256(t *testing.T) { +func TestJWTWriter_SignWithMethodAndRandomKey_SigningMethodIsHS256(t *testing.T) { token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + tokenParsed, _, _ := new(libjwt.Parser).ParseUnverified(token, libjwt.MapClaims{}) writer, _ := jwt.NewJWTWriter(token) - token, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodHS256) + newToken, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodHS256) assert.NoError(t, err) assert.NotEmpty(t, token) -} - -func TestJWTWriter_SignWithMethodAndRandomKey_WhenSigningMethodIsRS256(t *testing.T) { - token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" - writer, _ := jwt.NewJWTWriter(token) + assert.NotEqual(t, token, newToken) - token, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodRS256) + newTokenParsed, _, err := new(libjwt.Parser).ParseUnverified(newToken, libjwt.MapClaims{}) assert.NoError(t, err) - assert.NotEmpty(t, token) + assert.Equal(t, libjwt.SigningMethodHS256, newTokenParsed.Method) + assert.Equal(t, tokenParsed.Claims, newTokenParsed.Claims) } -func TestJWTWriter_SignWithMethodAndRandomKey_WhenSigningMethodIsRS384(t *testing.T) { +func TestJWTWriter_SignWithMethodAndRandomKey_SigningMethodIsHS512(t *testing.T) { token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + tokenParsed, _, _ := new(libjwt.Parser).ParseUnverified(token, libjwt.MapClaims{}) writer, _ := jwt.NewJWTWriter(token) - token, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodRS384) + newToken, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodHS512) assert.NoError(t, err) assert.NotEmpty(t, token) -} + assert.NotEqual(t, token, newToken) -func TestJWTWriter_SignWithMethodAndRandomKey_WhenSigningMethodIsRS512(t *testing.T) { - token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" - writer, _ := jwt.NewJWTWriter(token) - - token, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodRS512) + newTokenParsed, _, err := new(libjwt.Parser).ParseUnverified(newToken, libjwt.MapClaims{}) assert.NoError(t, err) - assert.NotEmpty(t, token) + assert.Equal(t, libjwt.SigningMethodHS512, newTokenParsed.Method) + assert.Equal(t, tokenParsed.Claims, newTokenParsed.Claims) } -func TestJWTWriter_SignWithMethodAndRandomKey_WhenSigningMethodIsES256(t *testing.T) { - token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" +func TestJWTWriter_SignWithMethodAndKey_WhenTokenExpired(t *testing.T) { + token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzkwMjJ9.4Adcj3UFYzPUVaVF43FmMab6RlaQD8A9V8wFzzht-KQ" + tokenParsed, _, _ := new(libjwt.Parser).ParseUnverified(token, libjwt.MapClaims{}) writer, _ := jwt.NewJWTWriter(token) - token, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodES256) + newToken, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodHS256) assert.NoError(t, err) assert.NotEmpty(t, token) -} + assert.NotEqual(t, token, newToken) -func TestJWTWriter_SignWithMethodAndRandomKey_WhenSigningMethodIsES384(t *testing.T) { - token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" - writer, _ := jwt.NewJWTWriter(token) - - token, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodES384) + newTokenParsed, _, err := new(libjwt.Parser).ParseUnverified(newToken, libjwt.MapClaims{}) assert.NoError(t, err) - assert.NotEmpty(t, token) -} + assert.Equal(t, libjwt.SigningMethodHS256, newTokenParsed.Method) -func TestJWTWriter_SignWithMethodAndRandomKey_WhenSigningMethodIsES512(t *testing.T) { - token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" - writer, _ := jwt.NewJWTWriter(token) + subject, _ := tokenParsed.Claims.GetSubject() + newSubject, _ := newTokenParsed.Claims.GetSubject() + assert.Equal(t, subject, newSubject) - token, err := writer.SignWithMethodAndRandomKey(libjwt.SigningMethodES512) - assert.NoError(t, err) - assert.NotEmpty(t, token) + expirationTime, _ := tokenParsed.Claims.GetExpirationTime() + newExpirationTime, _ := newTokenParsed.Claims.GetExpirationTime() + assert.True(t, expirationTime.Before(newExpirationTime.Time)) }