github.com/lovung/GoCleanArchitecture@v0.0.0-20210302152432-50d91fd29f9f/pkg/jwtutil/jwt.go (about) 1 package jwtutil 2 3 import ( 4 "fmt" 5 "sync" 6 "time" 7 8 "github.com/dgrijalva/jwt-go" 9 ) 10 11 var ( 12 once sync.Once 13 jwtSecret []byte 14 aExpDuration time.Duration 15 rExpDuration time.Duration 16 ) 17 18 // Error constant for jwt auth 19 var ( 20 ErrInvalidAlg = fmt.Errorf("invalid alg") 21 ) 22 23 // InitJWTSession initializes variables for JWT Session 24 func InitJWTSession(secret string, aExpDur, rExpDur time.Duration) { 25 once.Do(func() { 26 jwtSecret = []byte(secret) 27 aExpDuration = aExpDur 28 rExpDuration = rExpDur 29 }) 30 } 31 32 // GenerateToken generates JWT for authentication 33 func GenerateToken(claims AuthClaims) (aTokenStr, rTokenStr string, err error) { 34 aTokenStr, err = generateJWT(claims, aExpDuration) 35 if err != nil { 36 return "", "", err 37 } 38 39 rTokenStr, err = generateJWT(claims, rExpDuration) 40 41 return aTokenStr, rTokenStr, err 42 } 43 44 // TODO: consider using Redis to revoke token per user 45 func generateJWT(claims AuthClaims, expDur time.Duration) (tokenStr string, err error) { 46 claims.StandardClaims = jwt.StandardClaims{ 47 IssuedAt: claims.IssueTime.Unix(), 48 ExpiresAt: claims.IssueTime.Add(expDur).Unix(), 49 } 50 51 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 52 tokenStr, err = token.SignedString(jwtSecret) 53 54 return tokenStr, err 55 } 56 57 // VerifyToken validates JWT and extract userId and officeID 58 func VerifyToken(tokenStr string) (AuthClaims, error) { 59 token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) { 60 if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { 61 return nil, ErrInvalidAlg 62 } 63 return jwtSecret, nil 64 }) 65 66 if err != nil { 67 return AuthClaims{}, err 68 } 69 70 claims, ok := token.Claims.(jwt.MapClaims) 71 if !ok { 72 return AuthClaims{}, err 73 } 74 75 authClaims := AuthClaims{ 76 UserID: uint64(claims["user_id"].(float64)), 77 } 78 79 return authClaims, nil 80 }