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

     1  package jwt
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/annwntech/go-micro/v2/auth"
     8  	"github.com/annwntech/go-micro/v2/auth/rules"
     9  	"github.com/annwntech/go-micro/v2/auth/token"
    10  	"github.com/annwntech/go-micro/v2/auth/token/jwt"
    11  )
    12  
    13  // NewAuth returns a new instance of the Auth service
    14  func NewAuth(opts ...auth.Option) auth.Auth {
    15  	j := new(jwtAuth)
    16  	j.Init(opts...)
    17  	return j
    18  }
    19  
    20  type jwtAuth struct {
    21  	options auth.Options
    22  	token   token.Provider
    23  	rules   []*auth.Rule
    24  
    25  	sync.Mutex
    26  }
    27  
    28  func (j *jwtAuth) String() string {
    29  	return "jwt"
    30  }
    31  
    32  func (j *jwtAuth) Init(opts ...auth.Option) {
    33  	j.Lock()
    34  	defer j.Unlock()
    35  
    36  	for _, o := range opts {
    37  		o(&j.options)
    38  	}
    39  
    40  	j.token = jwt.NewTokenProvider(
    41  		token.WithPrivateKey(j.options.PrivateKey),
    42  		token.WithPublicKey(j.options.PublicKey),
    43  	)
    44  }
    45  
    46  func (j *jwtAuth) Options() auth.Options {
    47  	j.Lock()
    48  	defer j.Unlock()
    49  	return j.options
    50  }
    51  
    52  func (j *jwtAuth) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
    53  	options := auth.NewGenerateOptions(opts...)
    54  	if len(options.Issuer) == 0 {
    55  		options.Issuer = j.Options().Issuer
    56  	}
    57  	name := options.Name
    58  	if name == "" {
    59  		name = id
    60  	}
    61  	account := &auth.Account{
    62  		ID:       id,
    63  		Type:     options.Type,
    64  		Scopes:   options.Scopes,
    65  		Metadata: options.Metadata,
    66  		Issuer:   options.Issuer,
    67  		Name:     name,
    68  	}
    69  
    70  	// generate a JWT secret which can be provided to the Token() method
    71  	// and exchanged for an access token
    72  	secret, err := j.token.Generate(account, token.WithExpiry(time.Hour*24*365))
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	account.Secret = secret.Token
    77  
    78  	// return the account
    79  	return account, nil
    80  }
    81  
    82  func (j *jwtAuth) Grant(rule *auth.Rule) error {
    83  	j.Lock()
    84  	defer j.Unlock()
    85  	j.rules = append(j.rules, rule)
    86  	return nil
    87  }
    88  
    89  func (j *jwtAuth) Revoke(rule *auth.Rule) error {
    90  	j.Lock()
    91  	defer j.Unlock()
    92  
    93  	rules := []*auth.Rule{}
    94  	for _, r := range j.rules {
    95  		if r.ID != rule.ID {
    96  			rules = append(rules, r)
    97  		}
    98  	}
    99  
   100  	j.rules = rules
   101  	return nil
   102  }
   103  
   104  func (j *jwtAuth) Verify(acc *auth.Account, res *auth.Resource, opts ...auth.VerifyOption) error {
   105  	j.Lock()
   106  	defer j.Unlock()
   107  
   108  	var options auth.VerifyOptions
   109  	for _, o := range opts {
   110  		o(&options)
   111  	}
   112  
   113  	return rules.VerifyAccess(j.rules, acc, res)
   114  }
   115  
   116  func (j *jwtAuth) Rules(opts ...auth.RulesOption) ([]*auth.Rule, error) {
   117  	j.Lock()
   118  	defer j.Unlock()
   119  	return j.rules, nil
   120  }
   121  
   122  func (j *jwtAuth) Inspect(token string) (*auth.Account, error) {
   123  	return j.token.Inspect(token)
   124  }
   125  
   126  func (j *jwtAuth) Token(opts ...auth.TokenOption) (*auth.AuthToken, error) {
   127  	options := auth.NewTokenOptions(opts...)
   128  
   129  	secret := options.RefreshToken
   130  	if len(options.Secret) > 0 {
   131  		secret = options.Secret
   132  	}
   133  
   134  	account, err := j.token.Inspect(secret)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  
   139  	access, err := j.token.Generate(account, token.WithExpiry(options.Expiry))
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  
   144  	refresh, err := j.token.Generate(account, token.WithExpiry(options.Expiry+time.Hour))
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	return &auth.AuthToken{
   150  		Created:      access.Created,
   151  		Expiry:       access.Expiry,
   152  		AccessToken:  access.Token,
   153  		RefreshToken: refresh.Token,
   154  	}, nil
   155  }