Skip to content
This repository has been archived by the owner on May 24, 2023. It is now read-only.

How to enable refresh token? #130

Open
rngallen opened this issue Apr 25, 2023 · 1 comment
Open

How to enable refresh token? #130

rngallen opened this issue Apr 25, 2023 · 1 comment

Comments

@rngallen
Copy link

How can I have refresh token when user authenticated?

@TomasVaras
Copy link

TomasVaras commented May 4, 2023

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()

	}

}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants