76 lines
1.9 KiB
Go
76 lines
1.9 KiB
Go
package middlewares
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"time"
|
|
|
|
"gitea.konchin.com/go2025/backend/models"
|
|
"gitea.konchin.com/go2025/backend/types"
|
|
"github.com/golang-jwt/jwt/v5"
|
|
"github.com/spf13/viper"
|
|
"github.com/uptrace/bunrouter"
|
|
)
|
|
|
|
func (self *Handlers) CheckRefreshToken(
|
|
next bunrouter.HandlerFunc,
|
|
) bunrouter.HandlerFunc {
|
|
return func(w http.ResponseWriter, req bunrouter.Request) error {
|
|
ctx := req.Context()
|
|
|
|
refreshTokenCookie, err := req.Cookie("refresh_token")
|
|
if err != nil {
|
|
return HTTPError{
|
|
StatusCode: http.StatusUnauthorized,
|
|
Message: "user did not login",
|
|
OriginError: err,
|
|
}
|
|
}
|
|
|
|
var claim models.RefreshTokenClaim
|
|
token, err := jwt.ParseWithClaims(refreshTokenCookie.Value, &claim,
|
|
func(*jwt.Token) (interface{}, error) {
|
|
return []byte(viper.GetString("refresh-token-secret")), nil
|
|
})
|
|
if err != nil {
|
|
return HTTPError{
|
|
StatusCode: http.StatusUnauthorized,
|
|
Message: "refresh token jwt cannot parse",
|
|
OriginError: err,
|
|
}
|
|
}
|
|
if !token.Valid {
|
|
return HTTPError{
|
|
StatusCode: http.StatusUnauthorized,
|
|
Message: "refresh token jwt invalid",
|
|
}
|
|
}
|
|
|
|
// check time and refresh
|
|
timeLeft := claim.ExpiresAt.Time.Sub(time.Now()) / time.Second
|
|
if int64(timeLeft) < viper.GetInt64("refresh-token-timeout")/2 {
|
|
session, err := self.db.UpdateRefreshToken(ctx, claim.UserId)
|
|
if err != nil {
|
|
return HTTPError{
|
|
StatusCode: http.StatusInternalServerError,
|
|
Message: "upsert session failed",
|
|
OriginError: err,
|
|
}
|
|
}
|
|
|
|
http.SetCookie(w, &http.Cookie{
|
|
Name: "refresh_token",
|
|
Value: session.RefreshToken,
|
|
Path: "/",
|
|
Secure: viper.GetBool("https"),
|
|
Expires: claim.ExpiresAt.Time,
|
|
HttpOnly: true,
|
|
SameSite: http.SameSiteLaxMode,
|
|
})
|
|
}
|
|
|
|
ctx = context.WithValue(ctx, types.RefreshToken(""), claim)
|
|
return next(w, req.WithContext(ctx))
|
|
}
|
|
}
|