package auth import ( "fmt" "net/http" "time" "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" ) const ( CtxRequestHeaderUserId = "user_id" ctxRequestHeaderAuthorization = "Authorization" ctxRequestCookieAuthorization = "ak" ctxRequestTokenExpired = "expired" ) func Auth(authKey string) gin.HandlerFunc { return func(ctx *gin.Context) { var ( err error tk = ctx.Request.Header.Get(ctxRequestHeaderAuthorization) ) if tk == "" { tk, err = ctx.Cookie(ctxRequestCookieAuthorization) if err != nil { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"msg": "auth failed"}) return } tk = "Bearer " + tk } if len(tk) < 8 { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"msg": "auth failed"}) return } token, err := jwt.Parse(tk[7:], func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return []byte(authKey), nil }) if err != nil || !token.Valid { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"msg": "auth failed"}) return } mapClaims := token.Claims.(jwt.MapClaims) expired := int64(mapClaims[ctxRequestTokenExpired].(float64)) if expired < time.Now().Unix() { // Only cookie is blank value, check token expired if _, err := ctx.Cookie(ctxRequestCookieAuthorization); err != nil { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"msg": "auth failed, token timeout"}) return } } ctx.Set(CtxRequestHeaderUserId, int(mapClaims[CtxRequestHeaderUserId].(float64))) } }