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 } if mapClaims, ok := token.Claims.(jwt.MapClaims); ok { if expired, ok := mapClaims[ctxRequestTokenExpired].(float64); ok { if int64(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 } } } if uid, ok := mapClaims[CtxRequestHeaderUserId].(float64); ok { ctx.Set(CtxRequestHeaderUserId, int(uid)) } } } }