go-micro.dev/v5@v5.12.0/auth/jwt/token/jwt.go (about)

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