Open rngallen opened 1 year ago
im trying to implement just that, this middleware only checks for the token on the header so I don't think you could implement a refresh token strategy with this middleware.
So lets say you have a jwt token that lasts for 30 min and you have a refresh token for 24 hours, you could do something like this.
func Protected() fiber.Handler {
return func(c *fiber.Ctx) error {
token := c.Cookies("token")
err := utilities.JwtChecker(token)
if err != nil {
refreshToken := c.Cookies("refresh_token")
if refreshToken == "" {
return c.SendStatus(fiber.StatusUnauthorized)
}
refreshClaims := new(utilities.Claims)
err := utilities.JwtDecoder(refreshToken, refreshClaims)
if err != nil {
return c.SendStatus(fiber.StatusUnauthorized)
}
//go find the user by userid
var user db.UserSchema
// if the user does not exist wich its going to be
// strange if it reaches this point, just send and internal status error
if err := db.GetUserById(refreshClaims.UserId, &user); err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
// generate new claims
claims := jwt.MapClaims{
"name": user.Name,
"email": user.Email,
"userId": user.UserId,
"project": user.Project,
"exp": time.Now().Add(time.Minute * 30).Unix(),
}
// create and sign the token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signinKey := []byte(os.Getenv("JWT_KEY"))
t, tokenErr := token.SignedString(signinKey)
if tokenErr != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
c.Cookie(&fiber.Cookie{
Name: "token",
Value: t,
HTTPOnly: true,
Expires: time.Now().Add(time.Minute * 30),
})
return c.Next()
}
return c.Next()
}
}
also you could replace the refresh token if its close to expiring
func RefreshTokenUpdate() fiber.Handler {
return func(c *fiber.Ctx) error {
refreshToken := c.Cookies("refresh_token")
if refreshToken == "" {
return c.SendStatus(fiber.StatusUnauthorized)
}
refreshClaims := new(utilities.Claims)
err := utilities.JwtDecoder(refreshToken, refreshClaims)
if err != nil {
return c.SendStatus(fiber.StatusUnauthorized)
}
expTime := time.Unix(refreshClaims.ExpiresAt.Unix(), 0)
diff := expTime.Sub(time.Now())
// fmt.Printf("Token expires in %.2f hours\n", diff.Hours())
if diff <= 5*time.Hour {
// create new refresh token
refreshClaims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(time.Hour * 24))
newRefreshToken := jwt.NewWithClaims(jwt.SigningMethodHS256, refreshClaims)
signinKey := []byte(os.Getenv("JWT_KEY"))
rt, rTokenErr := newRefreshToken.SignedString(signinKey)
if rTokenErr != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
c.Cookie(&fiber.Cookie{
Name: "refresh_token",
Value: rt,
Expires: time.Now().Add(24 * time.Hour),
HTTPOnly: true,
})
}
return c.Next()
}
}
How can I have refresh token when user authenticated?