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  }