Implement the Auth interface, with JWT and service implementations. * Update Auth Interface * Define Auth Service Implementation * Support Service Auth * Add Auth Service Proto * Remove erronious files * Implement Auth Service Package * Update Auth Interface * Update Auth Interface. Add Validate, remove Add/Remove roles * Make Revoke interface more explicit * Refactor serializing and deserializing service accounts * Fix srv name & update interface to be more explicit * Require jwt public key for auth * Rename Variables (Resource.ID => Resource.Name & ServiceAccount => Account) * Implement JWT Auth Package * Remove parent, add ID * Update auth imports to v2. Add String() to auth interface
		
			
				
	
	
		
			107 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package jwt
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/dgrijalva/jwt-go"
 | |
| 	"github.com/micro/go-micro/v2/auth"
 | |
| )
 | |
| 
 | |
| // ErrInvalidPrivateKey is returned when the service provided an invalid private key
 | |
| var ErrInvalidPrivateKey = errors.New("An invalid private key was provided")
 | |
| 
 | |
| // ErrEncodingToken is returned when the service encounters an error during encoding
 | |
| var ErrEncodingToken = errors.New("An error occured while encoding the JWT")
 | |
| 
 | |
| // ErrInvalidToken is returned when the token provided is not valid
 | |
| var ErrInvalidToken = errors.New("An invalid token was provided")
 | |
| 
 | |
| // NewAuth returns a new instance of the Auth service
 | |
| func NewAuth(opts ...auth.Option) auth.Auth {
 | |
| 	svc := new(svc)
 | |
| 	svc.Init(opts...)
 | |
| 	return svc
 | |
| }
 | |
| 
 | |
| // svc is the JWT implementation of the Auth interface
 | |
| type svc struct {
 | |
| 	options auth.Options
 | |
| }
 | |
| 
 | |
| func (s *svc) String() string {
 | |
| 	return "jwt"
 | |
| }
 | |
| 
 | |
| func (s *svc) Init(opts ...auth.Option) error {
 | |
| 	for _, o := range opts {
 | |
| 		o(&s.options)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // AuthClaims to be encoded in the JWT
 | |
| type AuthClaims struct {
 | |
| 	Id       string            `json:"id"`
 | |
| 	Roles    []*auth.Role      `json:"roles"`
 | |
| 	Metadata map[string]string `json:"metadata"`
 | |
| 
 | |
| 	jwt.StandardClaims
 | |
| }
 | |
| 
 | |
| // Generate a new JWT
 | |
| func (s *svc) Generate(id string, ops ...auth.GenerateOption) (*auth.Account, error) {
 | |
| 	key, err := jwt.ParseRSAPrivateKeyFromPEM(s.options.PrivateKey)
 | |
| 	if err != nil {
 | |
| 		return nil, ErrEncodingToken
 | |
| 	}
 | |
| 
 | |
| 	options := auth.NewGenerateOptions(ops...)
 | |
| 	account := jwt.NewWithClaims(jwt.SigningMethodRS256, AuthClaims{
 | |
| 		id, options.Roles, options.Metadata, jwt.StandardClaims{
 | |
| 			Subject:   "TODO",
 | |
| 			ExpiresAt: time.Now().Add(time.Hour * 24).Unix(),
 | |
| 		},
 | |
| 	})
 | |
| 
 | |
| 	token, err := account.SignedString(key)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return &auth.Account{
 | |
| 		Id:       id,
 | |
| 		Token:    token,
 | |
| 		Roles:    options.Roles,
 | |
| 		Metadata: options.Metadata,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // Revoke an authorization account
 | |
| func (s *svc) Revoke(token string) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Validate a JWT
 | |
| func (s *svc) Validate(token string) (*auth.Account, error) {
 | |
| 	res, err := jwt.ParseWithClaims(token, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) {
 | |
| 		return jwt.ParseRSAPublicKeyFromPEM(s.options.PublicKey)
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	if !res.Valid {
 | |
| 		return nil, ErrInvalidToken
 | |
| 	}
 | |
| 
 | |
| 	claims := res.Claims.(*AuthClaims)
 | |
| 
 | |
| 	return &auth.Account{
 | |
| 		Id:       claims.Id,
 | |
| 		Metadata: claims.Metadata,
 | |
| 		Roles:    claims.Roles,
 | |
| 	}, nil
 | |
| }
 |