Updated auth interface (#1384)
* Updated auth interface * Add Rule * Remove Rule * Return token from Renew * Renew => Refresh * Implement Tokens & Default Auth Implementation * Change default auth to noop * Change default auth to noop * Move token.Token to auth.Token * Remove Token from Account * Auth service implementation * Decode JWT locally * Cookie for secret * Move string to bottom of interface definition * Depricate auth_exclude * Update auth wrappers * Update go.sum Co-authored-by: Ben Toogood <ben@micro.mu>
This commit is contained in:
133
auth/jwt/jwt.go
133
auth/jwt/jwt.go
@@ -1,133 +0,0 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidPrivateKey is returned when the service provided an invalid private key
|
||||
ErrInvalidPrivateKey = errors.New("An invalid private key was provided")
|
||||
|
||||
// ErrEncodingToken is returned when the service encounters an error during encoding
|
||||
ErrEncodingToken = errors.New("An error occured while encoding the JWT")
|
||||
|
||||
// ErrInvalidToken is returned when the token provided is not valid
|
||||
ErrInvalidToken = errors.New("An invalid token was provided")
|
||||
|
||||
// ErrMissingToken is returned when no token is provided
|
||||
ErrMissingToken = errors.New("A valid JWT is required")
|
||||
)
|
||||
|
||||
// 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) Options() auth.Options {
|
||||
return s.options
|
||||
}
|
||||
|
||||
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 {
|
||||
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) {
|
||||
// decode the private key
|
||||
priv, err := base64.StdEncoding.DecodeString(s.options.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := jwt.ParseRSAPrivateKeyFromPEM(priv)
|
||||
if err != nil {
|
||||
return nil, ErrEncodingToken
|
||||
}
|
||||
|
||||
options := auth.NewGenerateOptions(ops...)
|
||||
account := jwt.NewWithClaims(jwt.SigningMethodRS256, AuthClaims{
|
||||
options.Roles, options.Metadata, jwt.StandardClaims{
|
||||
Subject: id,
|
||||
ExpiresAt: options.Expiry.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
|
||||
}
|
||||
|
||||
// Verify a JWT
|
||||
func (s *svc) Verify(token string) (*auth.Account, error) {
|
||||
if token == "" {
|
||||
return nil, ErrMissingToken
|
||||
}
|
||||
|
||||
// decode the public key
|
||||
pub, err := base64.StdEncoding.DecodeString(s.options.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := jwt.ParseWithClaims(token, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwt.ParseRSAPublicKeyFromPEM(pub)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !res.Valid {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
claims, ok := res.Claims.(*AuthClaims)
|
||||
if !ok {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
return &auth.Account{
|
||||
Id: claims.Subject,
|
||||
Metadata: claims.Metadata,
|
||||
Roles: claims.Roles,
|
||||
}, nil
|
||||
}
|
Reference in New Issue
Block a user