forked from micro/go-micro
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
1 parent
449bcb4
commit d621548
Showing
16 changed files
with
1,103 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package auth | ||
|
||
var ( | ||
DefaultAuth Auth = new(noop) | ||
) | ||
|
||
type noop struct { | ||
options Options | ||
} | ||
|
||
// String name of implementation | ||
func (a *noop) String() string { | ||
return "noop" | ||
} | ||
|
||
// Init the svc | ||
func (a *noop) Init(...Option) error { | ||
return nil | ||
} | ||
|
||
// Generate a new auth Account | ||
func (a *noop) Generate(id string, ops ...GenerateOption) (*Account, error) { | ||
return nil, nil | ||
} | ||
|
||
// Revoke an authorization Account | ||
func (a *noop) Revoke(token string) error { | ||
return nil | ||
} | ||
|
||
// Validate a account token | ||
func (a *noop) Validate(token string) (*Account, error) { | ||
return nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package auth | ||
|
||
import ( | ||
b64 "encoding/base64" | ||
) | ||
|
||
type Options struct { | ||
PublicKey []byte | ||
PrivateKey []byte | ||
} | ||
|
||
type Option func(o *Options) | ||
|
||
// PublicKey is the JWT public key | ||
func PublicKey(key string) Option { | ||
return func(o *Options) { | ||
o.PublicKey, _ = b64.StdEncoding.DecodeString(key) | ||
} | ||
} | ||
|
||
// PrivateKey is the JWT private key | ||
func PrivateKey(key string) Option { | ||
return func(o *Options) { | ||
o.PrivateKey, _ = b64.StdEncoding.DecodeString(key) | ||
} | ||
} | ||
|
||
type GenerateOptions struct { | ||
Metadata map[string]string | ||
Roles []*Role | ||
} | ||
|
||
type GenerateOption func(o *GenerateOptions) | ||
|
||
// Metadata for the generated account | ||
func Metadata(md map[string]string) func(o *GenerateOptions) { | ||
return func(o *GenerateOptions) { | ||
o.Metadata = md | ||
} | ||
} | ||
|
||
// Roles for the generated account | ||
func Roles(rs []*Role) func(o *GenerateOptions) { | ||
return func(o *GenerateOptions) { | ||
o.Roles = rs | ||
} | ||
} | ||
|
||
// NewGenerateOptions from a slice of options | ||
func NewGenerateOptions(opts ...GenerateOption) GenerateOptions { | ||
var options GenerateOptions | ||
for _, o := range opts { | ||
o(&options) | ||
} | ||
|
||
return options | ||
} |
Oops, something went wrong.