Files
nCovTrack-Backend/middleware/auth.go
2022-04-27 22:08:02 +08:00

70 lines
2.2 KiB
Go

package middleware
import (
"encoding/json"
"nCovTrack-Backend/global"
"nCovTrack-Backend/models"
"nCovTrack-Backend/utils"
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v4"
)
const UNAUTH_MSG = "unauthorized"
func Auth() gin.HandlerFunc {
return func(c *gin.Context) {
oldToken := c.Request.Header["Token"]
c.Writer.Header().Set("X-Token", "")
if len(oldToken) != 1 || oldToken[0] == "" {
utils.Err(c, http.StatusUnauthorized, http.StatusUnauthorized, UNAUTH_MSG)
c.Abort()
return
}
// Write the field of token to request header
claims := utils.ParseClaims(oldToken[0])
tokenClaims := models.TokenClaims{
ID: int(claims["id"].(float64)),
Username: claims["username"].(string),
Email: claims["email"].(string),
Role: int(claims["role"].(float64)),
Region: claims["region"].(string),
}
claimsByte, _ := json.Marshal(tokenClaims)
c.Request.Header.Add("claims", string(claimsByte))
// renew token, and judge the token's iat is expired or not
renewToken := utils.RenewToken(oldToken[0])
if renewToken == "" || !validAccountIssue(claims) {
utils.Err(c, http.StatusUnauthorized, http.StatusUnauthorized, UNAUTH_MSG)
c.Abort()
return
}
c.Writer.Header().Set("X-Token", renewToken)
c.Next()
}
}
// validAccountIssue validate token is valid or not
// If user change password, or logoff on all password, we need to judge use's token is valid?
// Due to the token is no status, so we need to record something on the server-end.
// We use the "IssueAt" field of token, to judge token expired or not.
// TODO: Move this to jwt utils
func validAccountIssue(claims jwt.MapClaims) bool {
iafStr := global.Redis.HGet(global.CHANGEPWD_REDIS_KEY, claims["email"].(string)).Val()
if iafStr == "" {
return true
}
iaf, _ := strconv.Atoi(iafStr)
// Due to we allow token renew, although it was expired, so the token validity period will more than token's validity period
tokenMaxValidSeconds := (global.TOKEN_EXPIRE_DAYS + global.ServerSettings.Jwt.RenewExpireDays) * 24 * 60 * 60
if time.Now().Unix()-int64(iaf) > int64(tokenMaxValidSeconds) {
global.Redis.HDel(global.CHANGEPWD_REDIS_KEY, claims["email"].(string))
return true
}
return int(claims["iat"].(float64)) > iaf
}