d621548120
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
|
|
}
|