github.com/annwntech/go-micro/v2@v2.9.5/auth/token/jwt/jwt.go (about)

     1  package jwt
     2  
     3  import (
     4  	"encoding/base64"
     5  	"time"
     6  
     7  	"github.com/dgrijalva/jwt-go"
     8  	"github.com/annwntech/go-micro/v2/auth"
     9  	"github.com/annwntech/go-micro/v2/auth/token"
    10  )
    11  
    12  // authClaims to be encoded in the JWT
    13  type authClaims struct {
    14  	Type     string            `json:"type"`
    15  	Scopes   []string          `json:"scopes"`
    16  	Metadata map[string]string `json:"metadata"`
    17  
    18  	jwt.StandardClaims
    19  }
    20  
    21  // JWT implementation of token provider
    22  type JWT struct {
    23  	opts token.Options
    24  }
    25  
    26  // NewTokenProvider returns an initialized basic provider
    27  func NewTokenProvider(opts ...token.Option) token.Provider {
    28  	return &JWT{
    29  		opts: token.NewOptions(opts...),
    30  	}
    31  }
    32  
    33  // Generate a new JWT
    34  func (j *JWT) Generate(acc *auth.Account, opts ...token.GenerateOption) (*token.Token, error) {
    35  	// decode the private key
    36  	priv, err := base64.StdEncoding.DecodeString(j.opts.PrivateKey)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	// parse the private key
    42  	key, err := jwt.ParseRSAPrivateKeyFromPEM(priv)
    43  	if err != nil {
    44  		return nil, token.ErrEncodingToken
    45  	}
    46  
    47  	// parse the options
    48  	options := token.NewGenerateOptions(opts...)
    49  
    50  	// generate the JWT
    51  	expiry := time.Now().Add(options.Expiry)
    52  	t := jwt.NewWithClaims(jwt.SigningMethodRS256, authClaims{
    53  		acc.Type, acc.Scopes, acc.Metadata, jwt.StandardClaims{
    54  			Subject:   acc.ID,
    55  			Issuer:    acc.Issuer,
    56  			ExpiresAt: expiry.Unix(),
    57  		},
    58  	})
    59  	tok, err := t.SignedString(key)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	// return the token
    65  	return &token.Token{
    66  		Token:   tok,
    67  		Expiry:  expiry,
    68  		Created: time.Now(),
    69  	}, nil
    70  }
    71  
    72  // Inspect a JWT
    73  func (j *JWT) Inspect(t string) (*auth.Account, error) {
    74  	// decode the public key
    75  	pub, err := base64.StdEncoding.DecodeString(j.opts.PublicKey)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	// parse the public key
    81  	res, err := jwt.ParseWithClaims(t, &authClaims{}, func(token *jwt.Token) (interface{}, error) {
    82  		return jwt.ParseRSAPublicKeyFromPEM(pub)
    83  	})
    84  	if err != nil {
    85  		return nil, token.ErrInvalidToken
    86  	}
    87  
    88  	// validate the token
    89  	if !res.Valid {
    90  		return nil, token.ErrInvalidToken
    91  	}
    92  	claims, ok := res.Claims.(*authClaims)
    93  	if !ok {
    94  		return nil, token.ErrInvalidToken
    95  	}
    96  
    97  	// return the token
    98  	return &auth.Account{
    99  		ID:       claims.Subject,
   100  		Issuer:   claims.Issuer,
   101  		Type:     claims.Type,
   102  		Scopes:   claims.Scopes,
   103  		Metadata: claims.Metadata,
   104  	}, nil
   105  }
   106  
   107  // String returns JWT
   108  func (j *JWT) String() string {
   109  	return "jwt"
   110  }