Newer
Older
package rbac
import (
"time"
"github.com/golang-jwt/jwt"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var signingMethod = jwt.SigningMethodHS256 //jwt.SigningMethodPS256.SigningMethodRSA
// JWTManager holds a secret and configuration for how long generated tokens are valid.
type JWTManager struct {
secretKey string
tokenDuration time.Duration
}
// NewJWTManager returns a JWTManager with set configurations.
func NewJWTManager(secretKey string, tokenDuration time.Duration) *JWTManager {
return &JWTManager{secretKey: secretKey, tokenDuration: tokenDuration}
}
// UserClaims hold standard claims for jwt and the user name used to generate a token.
type UserClaims struct {
jwt.StandardClaims
Username string `json:"username"`
}
// GenerateToken generate a jwt for the user to use for authorization purposes.
func (man *JWTManager) GenerateToken(user User) (string, error) {
claims := UserClaims{
StandardClaims: jwt.StandardClaims{ExpiresAt: time.Now().Add(man.tokenDuration).Unix()},
}
token := jwt.NewWithClaims(signingMethod, claims)
return token.SignedString([]byte(man.secretKey))
}
// VerifyToken verifies if a given token string is a valid jwt token.
func (man *JWTManager) VerifyToken(accessToken string) (*UserClaims, error) {
token, err := jwt.ParseWithClaims(
accessToken,
&UserClaims{},
func(token *jwt.Token) (interface{}, error) {
_, ok := token.Method.(*jwt.SigningMethodHMAC)
if !ok {
return nil, status.Errorf(codes.Unauthenticated, "unexpected token signing method")
}
return []byte(man.secretKey), nil
},
)
if err != nil {
return nil, status.Errorf(codes.Unauthenticated, "invalid token: %v", err)
}
claims, ok := token.Claims.(*UserClaims)
if !ok {
return nil, status.Errorf(codes.Unauthenticated, "invalid token claims %v", ok)
}
return claims, nil
}
// GetClaimsFromToken returns the UserClaims associated to the provided token.
func (man *JWTManager) GetClaimsFromToken(token string) (*UserClaims, error) {
claims, err := man.VerifyToken(token)
if err != nil {
return nil, err
}
return claims, nil
}