add MICRO_AUTH_TOKEN, parse token in wrapper, preload config and othe… (#1261)

* add MICRO_AUTH_TOKEN, parse token in wrapper, preload config and other things

* fix wrapper panic
This commit is contained in:
Asim Aslam 2020-02-25 22:15:44 +00:00 committed by GitHub
parent 603d37b135
commit 6aaaf54275
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 243 additions and 177 deletions

View File

@ -15,8 +15,8 @@ type Auth interface {
Generate(id string, opts ...GenerateOption) (*Account, error)
// Revoke an authorization Account
Revoke(token string) error
// Validate an account token
Validate(token string) (*Account, error)
// Verify an account token
Verify(token string) (*Account, error)
// String returns the implementation
String() string
}
@ -31,7 +31,10 @@ type Resource struct {
// Role an account has
type Role struct {
Name string
// Name of the role
Name string
// The resource it has access
// TODO: potentially remove
Resource *Resource
}

View File

@ -6,31 +6,42 @@ var (
// NewAuth returns a new default registry which is noop
func NewAuth(opts ...Option) Auth {
return noop{}
var options Options
for _, o := range opts {
o(&options)
}
return &noop{
opts: options,
}
}
type noop struct{}
type noop struct {
opts Options
}
func (noop) Init(opts ...Option) error {
func (n *noop) Init(opts ...Option) error {
for _, o := range opts {
o(&n.opts)
}
return nil
}
func (noop) Options() Options {
return Options{}
func (n *noop) Options() Options {
return n.opts
}
func (noop) Generate(id string, opts ...GenerateOption) (*Account, error) {
func (n *noop) Generate(id string, opts ...GenerateOption) (*Account, error) {
return nil, nil
}
func (noop) Revoke(token string) error {
func (n *noop) Revoke(token string) error {
return nil
}
func (noop) Validate(token string) (*Account, error) {
func (n *noop) Verify(token string) (*Account, error) {
return nil, nil
}
func (noop) String() string {
func (n *noop) String() string {
return "noop"
}

View File

@ -1,6 +1,7 @@
package jwt
import (
"encoding/base64"
"errors"
"time"
@ -8,17 +9,19 @@ import (
"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")
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
var ErrEncodingToken = errors.New("An error occured while encoding the JWT")
// 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
var ErrInvalidToken = errors.New("An invalid token was provided")
// 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
var ErrMissingToken = errors.New("A valid JWT is required")
// 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 {
@ -59,7 +62,13 @@ type AuthClaims struct {
// Generate a new JWT
func (s *svc) Generate(id string, ops ...auth.GenerateOption) (*auth.Account, error) {
key, err := jwt.ParseRSAPrivateKeyFromPEM(s.options.PrivateKey)
// 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
}
@ -90,14 +99,20 @@ func (s *svc) Revoke(token string) error {
return nil
}
// Validate a JWT
func (s *svc) Validate(token string) (*auth.Account, error) {
// 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(s.options.PublicKey)
return jwt.ParseRSAPublicKeyFromPEM(pub)
})
if err != nil {
return nil, err

View File

@ -1,41 +1,51 @@
package auth
import (
b64 "encoding/base64"
)
type Options struct {
PublicKey []byte
PrivateKey []byte
Excludes []string
// Token is an auth token
Token string
// Public key base64 encoded
PublicKey string
// Private key base64 encoded
PrivateKey string
// Endpoints to exclude
Exclude []string
}
type Option func(o *Options)
// Excludes endpoints from auth
func Excludes(excludes ...string) Option {
// Exclude ecludes a set of endpoints from authorization
func Exclude(e ...string) Option {
return func(o *Options) {
o.Excludes = excludes
o.Exclude = e
}
}
// PublicKey is the JWT public key
func PublicKey(key string) Option {
return func(o *Options) {
o.PublicKey, _ = b64.StdEncoding.DecodeString(key)
o.PublicKey = key
}
}
// PrivateKey is the JWT private key
func PrivateKey(key string) Option {
return func(o *Options) {
o.PrivateKey, _ = b64.StdEncoding.DecodeString(key)
o.PrivateKey = key
}
}
// Token sets an auth token
func Token(t string) Option {
return func(o *Options) {
o.Token = t
}
}
type GenerateOptions struct {
// Metadata associated with the account
Metadata map[string]string
Roles []*Role
// Roles/scopes associated with the account
Roles []*Role
}
type GenerateOption func(o *GenerateOptions)

View File

@ -1,5 +1,5 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: auth/service/proto/auth.proto
// source: micro/go-micro/auth/service/proto/auth.proto
package go_micro_auth
@ -36,7 +36,7 @@ func (m *Account) Reset() { *m = Account{} }
func (m *Account) String() string { return proto.CompactTextString(m) }
func (*Account) ProtoMessage() {}
func (*Account) Descriptor() ([]byte, []int) {
return fileDescriptor_21300bfacc51fc2a, []int{0}
return fileDescriptor_de609d4872dacc78, []int{0}
}
func (m *Account) XXX_Unmarshal(b []byte) error {
@ -111,7 +111,7 @@ func (m *Role) Reset() { *m = Role{} }
func (m *Role) String() string { return proto.CompactTextString(m) }
func (*Role) ProtoMessage() {}
func (*Role) Descriptor() ([]byte, []int) {
return fileDescriptor_21300bfacc51fc2a, []int{1}
return fileDescriptor_de609d4872dacc78, []int{1}
}
func (m *Role) XXX_Unmarshal(b []byte) error {
@ -158,7 +158,7 @@ func (m *Resource) Reset() { *m = Resource{} }
func (m *Resource) String() string { return proto.CompactTextString(m) }
func (*Resource) ProtoMessage() {}
func (*Resource) Descriptor() ([]byte, []int) {
return fileDescriptor_21300bfacc51fc2a, []int{2}
return fileDescriptor_de609d4872dacc78, []int{2}
}
func (m *Resource) XXX_Unmarshal(b []byte) error {
@ -204,7 +204,7 @@ func (m *GenerateRequest) Reset() { *m = GenerateRequest{} }
func (m *GenerateRequest) String() string { return proto.CompactTextString(m) }
func (*GenerateRequest) ProtoMessage() {}
func (*GenerateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_21300bfacc51fc2a, []int{3}
return fileDescriptor_de609d4872dacc78, []int{3}
}
func (m *GenerateRequest) XXX_Unmarshal(b []byte) error {
@ -243,7 +243,7 @@ func (m *GenerateResponse) Reset() { *m = GenerateResponse{} }
func (m *GenerateResponse) String() string { return proto.CompactTextString(m) }
func (*GenerateResponse) ProtoMessage() {}
func (*GenerateResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_21300bfacc51fc2a, []int{4}
return fileDescriptor_de609d4872dacc78, []int{4}
}
func (m *GenerateResponse) XXX_Unmarshal(b []byte) error {
@ -271,78 +271,78 @@ func (m *GenerateResponse) GetAccount() *Account {
return nil
}
type ValidateRequest struct {
type VerifyRequest struct {
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ValidateRequest) Reset() { *m = ValidateRequest{} }
func (m *ValidateRequest) String() string { return proto.CompactTextString(m) }
func (*ValidateRequest) ProtoMessage() {}
func (*ValidateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_21300bfacc51fc2a, []int{5}
func (m *VerifyRequest) Reset() { *m = VerifyRequest{} }
func (m *VerifyRequest) String() string { return proto.CompactTextString(m) }
func (*VerifyRequest) ProtoMessage() {}
func (*VerifyRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_de609d4872dacc78, []int{5}
}
func (m *ValidateRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ValidateRequest.Unmarshal(m, b)
func (m *VerifyRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_VerifyRequest.Unmarshal(m, b)
}
func (m *ValidateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ValidateRequest.Marshal(b, m, deterministic)
func (m *VerifyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_VerifyRequest.Marshal(b, m, deterministic)
}
func (m *ValidateRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ValidateRequest.Merge(m, src)
func (m *VerifyRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_VerifyRequest.Merge(m, src)
}
func (m *ValidateRequest) XXX_Size() int {
return xxx_messageInfo_ValidateRequest.Size(m)
func (m *VerifyRequest) XXX_Size() int {
return xxx_messageInfo_VerifyRequest.Size(m)
}
func (m *ValidateRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ValidateRequest.DiscardUnknown(m)
func (m *VerifyRequest) XXX_DiscardUnknown() {
xxx_messageInfo_VerifyRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ValidateRequest proto.InternalMessageInfo
var xxx_messageInfo_VerifyRequest proto.InternalMessageInfo
func (m *ValidateRequest) GetToken() string {
func (m *VerifyRequest) GetToken() string {
if m != nil {
return m.Token
}
return ""
}
type ValidateResponse struct {
type VerifyResponse struct {
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ValidateResponse) Reset() { *m = ValidateResponse{} }
func (m *ValidateResponse) String() string { return proto.CompactTextString(m) }
func (*ValidateResponse) ProtoMessage() {}
func (*ValidateResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_21300bfacc51fc2a, []int{6}
func (m *VerifyResponse) Reset() { *m = VerifyResponse{} }
func (m *VerifyResponse) String() string { return proto.CompactTextString(m) }
func (*VerifyResponse) ProtoMessage() {}
func (*VerifyResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_de609d4872dacc78, []int{6}
}
func (m *ValidateResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ValidateResponse.Unmarshal(m, b)
func (m *VerifyResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_VerifyResponse.Unmarshal(m, b)
}
func (m *ValidateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ValidateResponse.Marshal(b, m, deterministic)
func (m *VerifyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_VerifyResponse.Marshal(b, m, deterministic)
}
func (m *ValidateResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ValidateResponse.Merge(m, src)
func (m *VerifyResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_VerifyResponse.Merge(m, src)
}
func (m *ValidateResponse) XXX_Size() int {
return xxx_messageInfo_ValidateResponse.Size(m)
func (m *VerifyResponse) XXX_Size() int {
return xxx_messageInfo_VerifyResponse.Size(m)
}
func (m *ValidateResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ValidateResponse.DiscardUnknown(m)
func (m *VerifyResponse) XXX_DiscardUnknown() {
xxx_messageInfo_VerifyResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ValidateResponse proto.InternalMessageInfo
var xxx_messageInfo_VerifyResponse proto.InternalMessageInfo
func (m *ValidateResponse) GetAccount() *Account {
func (m *VerifyResponse) GetAccount() *Account {
if m != nil {
return m.Account
}
@ -360,7 +360,7 @@ func (m *RevokeRequest) Reset() { *m = RevokeRequest{} }
func (m *RevokeRequest) String() string { return proto.CompactTextString(m) }
func (*RevokeRequest) ProtoMessage() {}
func (*RevokeRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_21300bfacc51fc2a, []int{7}
return fileDescriptor_de609d4872dacc78, []int{7}
}
func (m *RevokeRequest) XXX_Unmarshal(b []byte) error {
@ -398,7 +398,7 @@ func (m *RevokeResponse) Reset() { *m = RevokeResponse{} }
func (m *RevokeResponse) String() string { return proto.CompactTextString(m) }
func (*RevokeResponse) ProtoMessage() {}
func (*RevokeResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_21300bfacc51fc2a, []int{8}
return fileDescriptor_de609d4872dacc78, []int{8}
}
func (m *RevokeResponse) XXX_Unmarshal(b []byte) error {
@ -426,41 +426,43 @@ func init() {
proto.RegisterType((*Resource)(nil), "go.micro.auth.Resource")
proto.RegisterType((*GenerateRequest)(nil), "go.micro.auth.GenerateRequest")
proto.RegisterType((*GenerateResponse)(nil), "go.micro.auth.GenerateResponse")
proto.RegisterType((*ValidateRequest)(nil), "go.micro.auth.ValidateRequest")
proto.RegisterType((*ValidateResponse)(nil), "go.micro.auth.ValidateResponse")
proto.RegisterType((*VerifyRequest)(nil), "go.micro.auth.VerifyRequest")
proto.RegisterType((*VerifyResponse)(nil), "go.micro.auth.VerifyResponse")
proto.RegisterType((*RevokeRequest)(nil), "go.micro.auth.RevokeRequest")
proto.RegisterType((*RevokeResponse)(nil), "go.micro.auth.RevokeResponse")
}
func init() { proto.RegisterFile("auth/service/proto/auth.proto", fileDescriptor_21300bfacc51fc2a) }
var fileDescriptor_21300bfacc51fc2a = []byte{
// 429 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0x4d, 0x6f, 0xd3, 0x40,
0x10, 0xad, 0x3f, 0xe2, 0x98, 0x89, 0xd2, 0x46, 0x03, 0x2a, 0x56, 0x44, 0x21, 0xb2, 0x40, 0x84,
0x8b, 0x83, 0xdc, 0x0b, 0x82, 0x0b, 0x15, 0xa0, 0x9e, 0x2a, 0xa4, 0x3d, 0x70, 0x5f, 0xec, 0x11,
0xb5, 0xe2, 0x78, 0xcd, 0x7a, 0x1d, 0xe1, 0xdf, 0xc0, 0x6f, 0xe5, 0x3f, 0x20, 0xaf, 0xbd, 0x69,
0xea, 0xb4, 0xaa, 0xd4, 0xdb, 0x7c, 0xbc, 0x79, 0xf3, 0xde, 0x68, 0x17, 0xce, 0x78, 0xad, 0xae,
0x57, 0x15, 0xc9, 0x6d, 0x96, 0xd0, 0xaa, 0x94, 0x42, 0x89, 0x55, 0x5b, 0x8a, 0x74, 0x88, 0xd3,
0x5f, 0x22, 0xda, 0x64, 0x89, 0x14, 0x51, 0x5b, 0x0c, 0xff, 0xda, 0x30, 0xbe, 0x48, 0x12, 0x51,
0x17, 0x0a, 0x8f, 0xc1, 0xce, 0xd2, 0xc0, 0x5a, 0x58, 0xcb, 0x27, 0xcc, 0xce, 0x52, 0x7c, 0x06,
0x23, 0x25, 0xd6, 0x54, 0x04, 0xb6, 0x2e, 0x75, 0x09, 0x06, 0x30, 0x4e, 0x24, 0x71, 0x45, 0x69,
0xe0, 0x2c, 0xac, 0xa5, 0xc3, 0x4c, 0x8a, 0xa7, 0xe0, 0xd1, 0x9f, 0x32, 0x93, 0x4d, 0xe0, 0xea,
0x46, 0x9f, 0xe1, 0x3b, 0x18, 0x49, 0x91, 0x53, 0x15, 0x8c, 0x16, 0xce, 0x72, 0x12, 0x3f, 0x8d,
0x6e, 0x49, 0x88, 0x98, 0xc8, 0x89, 0x75, 0x08, 0xfc, 0x0c, 0xfe, 0x86, 0x14, 0x4f, 0xb9, 0xe2,
0x81, 0xa7, 0xd1, 0xaf, 0x07, 0xe8, 0x5e, 0x6c, 0x74, 0xd5, 0xc3, 0xbe, 0x15, 0x4a, 0x36, 0x6c,
0x37, 0x35, 0xff, 0x04, 0xd3, 0x5b, 0x2d, 0x9c, 0x81, 0xb3, 0xa6, 0xa6, 0xb7, 0xd5, 0x86, 0xad,
0xaf, 0x2d, 0xcf, 0x6b, 0x32, 0xbe, 0x74, 0xf2, 0xd1, 0xfe, 0x60, 0x85, 0xdf, 0xc1, 0x6d, 0xd5,
0x20, 0x82, 0x5b, 0xf0, 0x0d, 0xf5, 0x43, 0x3a, 0xc6, 0x73, 0xf0, 0x25, 0x55, 0xa2, 0x96, 0x49,
0x37, 0x38, 0x89, 0x9f, 0x0f, 0x8d, 0xf4, 0x6d, 0xb6, 0x03, 0x86, 0x31, 0xf8, 0xa6, 0x7a, 0x27,
0x29, 0x82, 0xab, 0x9a, 0xd2, 0x28, 0xd1, 0x71, 0xf8, 0x05, 0x4e, 0x2e, 0xa9, 0x20, 0xc9, 0x15,
0x31, 0xfa, 0x5d, 0x53, 0xa5, 0xf0, 0x3d, 0x8c, 0x79, 0xe7, 0x5b, 0x4f, 0x4f, 0xe2, 0xd3, 0xbb,
0xaf, 0xc2, 0x0c, 0x2c, 0xfc, 0x0a, 0xb3, 0x1b, 0x92, 0xaa, 0x14, 0x45, 0x45, 0x8f, 0x60, 0x79,
0x0b, 0x27, 0x3f, 0x78, 0x9e, 0xa5, 0x7b, 0x52, 0x76, 0x8f, 0xc2, 0xda, 0x7b, 0x14, 0xed, 0xba,
0x1b, 0xe0, 0xa3, 0xd7, 0xbd, 0x81, 0x29, 0xa3, 0xad, 0x58, 0x3f, 0xb0, 0x6c, 0x06, 0xc7, 0x06,
0xd6, 0xad, 0x8a, 0xff, 0x59, 0xe0, 0x5e, 0xd4, 0xea, 0x1a, 0xaf, 0xc0, 0x37, 0xb6, 0xf1, 0xe5,
0x60, 0xdd, 0xe0, 0xa8, 0xf3, 0x57, 0xf7, 0xf6, 0x3b, 0xd6, 0xf0, 0xa8, 0xa5, 0x33, 0xb6, 0x0e,
0xe8, 0x06, 0x87, 0x39, 0xa0, 0x1b, 0xde, 0x23, 0x3c, 0xc2, 0x4b, 0xf0, 0x3a, 0xe1, 0xf8, 0xe2,
0xe0, 0xe9, 0xec, 0xd9, 0x9e, 0x9f, 0xdd, 0xd3, 0x35, 0x44, 0x3f, 0x3d, 0xfd, 0x97, 0xcf, 0xff,
0x07, 0x00, 0x00, 0xff, 0xff, 0x79, 0x35, 0xb2, 0x7e, 0xec, 0x03, 0x00, 0x00,
func init() {
proto.RegisterFile("micro/go-micro/auth/service/proto/auth.proto", fileDescriptor_de609d4872dacc78)
}
var fileDescriptor_de609d4872dacc78 = []byte{
// 432 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x4b, 0x6f, 0xd3, 0x40,
0x10, 0xae, 0x1d, 0xe7, 0xc1, 0x44, 0x09, 0xd1, 0x80, 0x8a, 0x15, 0xf1, 0x88, 0x56, 0x20, 0x05,
0x09, 0x1c, 0xe4, 0x5e, 0x10, 0x5c, 0x28, 0x0f, 0xf5, 0x54, 0x21, 0xed, 0x81, 0xfb, 0xe2, 0x0c,
0xad, 0x95, 0xc4, 0x6b, 0xd6, 0xeb, 0x08, 0xff, 0x06, 0x7e, 0x28, 0x7f, 0x03, 0x79, 0xd7, 0x1b,
0x6a, 0xb7, 0xe5, 0x00, 0xb7, 0x79, 0x7c, 0xf3, 0xcd, 0xf7, 0x8d, 0x76, 0xe1, 0xc5, 0x2e, 0x4d,
0x94, 0x5c, 0x5d, 0xc8, 0x97, 0x36, 0x10, 0xa5, 0xbe, 0x5c, 0x15, 0xa4, 0xf6, 0x69, 0x42, 0xab,
0x5c, 0x49, 0x6d, 0x4b, 0x91, 0x09, 0x71, 0x72, 0x21, 0x23, 0x83, 0x8b, 0xea, 0x22, 0xfb, 0xe9,
0xc3, 0xf0, 0x34, 0x49, 0x64, 0x99, 0x69, 0x9c, 0x82, 0x9f, 0xae, 0x43, 0x6f, 0xe1, 0x2d, 0xef,
0x70, 0x3f, 0x5d, 0xe3, 0x7d, 0xe8, 0x6b, 0xb9, 0xa1, 0x2c, 0xf4, 0x4d, 0xc9, 0x26, 0x18, 0xc2,
0x30, 0x51, 0x24, 0x34, 0xad, 0xc3, 0xde, 0xc2, 0x5b, 0xf6, 0xb8, 0x4b, 0xf1, 0x18, 0x06, 0xf4,
0x23, 0x4f, 0x55, 0x15, 0x06, 0xa6, 0xd1, 0x64, 0xf8, 0x1c, 0xfa, 0x4a, 0x6e, 0xa9, 0x08, 0xfb,
0x8b, 0xde, 0x72, 0x1c, 0xdf, 0x8b, 0x5a, 0x12, 0x22, 0x2e, 0xb7, 0xc4, 0x2d, 0x02, 0xdf, 0xc1,
0x68, 0x47, 0x5a, 0xac, 0x85, 0x16, 0xe1, 0xc0, 0xa0, 0x9f, 0x76, 0xd0, 0x8d, 0xd8, 0xe8, 0xbc,
0x81, 0x7d, 0xca, 0xb4, 0xaa, 0xf8, 0x61, 0x6a, 0xfe, 0x16, 0x26, 0xad, 0x16, 0xce, 0xa0, 0xb7,
0xa1, 0xaa, 0xb1, 0x55, 0x87, 0xb5, 0xaf, 0xbd, 0xd8, 0x96, 0xe4, 0x7c, 0x99, 0xe4, 0x8d, 0xff,
0xda, 0x63, 0x9f, 0x21, 0xa8, 0xd5, 0x20, 0x42, 0x90, 0x89, 0x1d, 0x35, 0x43, 0x26, 0xc6, 0x13,
0x18, 0x29, 0x2a, 0x64, 0xa9, 0x12, 0x3b, 0x38, 0x8e, 0x1f, 0x74, 0x8d, 0x34, 0x6d, 0x7e, 0x00,
0xb2, 0x18, 0x46, 0xae, 0x7a, 0x23, 0x29, 0x42, 0xa0, 0xab, 0xdc, 0x29, 0x31, 0x31, 0xfb, 0x00,
0x77, 0xcf, 0x28, 0x23, 0x25, 0x34, 0x71, 0xfa, 0x5e, 0x52, 0xa1, 0xf1, 0x15, 0x0c, 0x85, 0xf5,
0x6d, 0xa6, 0xc7, 0xf1, 0xf1, 0xcd, 0x57, 0xe1, 0x0e, 0xc6, 0x3e, 0xc2, 0xec, 0x0f, 0x49, 0x91,
0xcb, 0xac, 0xa0, 0x7f, 0x60, 0x79, 0x06, 0x93, 0x2f, 0xa4, 0xd2, 0x6f, 0x95, 0x13, 0x72, 0x78,
0x12, 0xde, 0x95, 0x27, 0xc1, 0xde, 0xc3, 0xd4, 0xc1, 0xfe, 0x67, 0x15, 0xa7, 0xbd, 0xdc, 0xd0,
0xdf, 0x57, 0xcd, 0x60, 0xea, 0x60, 0x76, 0x55, 0xfc, 0xcb, 0x83, 0xe0, 0xb4, 0xd4, 0x97, 0x78,
0x0e, 0x23, 0x67, 0x19, 0x1f, 0x77, 0xd6, 0x75, 0x0e, 0x3a, 0x7f, 0x72, 0x6b, 0xdf, 0xb2, 0xb2,
0x23, 0x3c, 0x83, 0x81, 0x35, 0x85, 0x0f, 0x3b, 0xe0, 0xd6, 0x49, 0xe6, 0x8f, 0x6e, 0xe9, 0x5e,
0x25, 0xb2, 0x92, 0xaf, 0x11, 0xb5, 0x0c, 0x5f, 0x23, 0x6a, 0xfb, 0x64, 0x47, 0x5f, 0x07, 0xe6,
0x07, 0x9f, 0xfc, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x34, 0xce, 0x17, 0xf1, 0x03, 0x00, 0x00,
}

View File

@ -1,16 +1,16 @@
// Code generated by protoc-gen-micro. DO NOT EDIT.
// source: auth/service/proto/auth.proto
// source: micro/go-micro/auth/service/proto/auth.proto
package go_micro_auth
import (
fmt "fmt"
math "math"
context "context"
proto "github.com/golang/protobuf/proto"
math "math"
)
import (
context "context"
client "github.com/micro/go-micro/v2/client"
server "github.com/micro/go-micro/v2/server"
)
@ -35,7 +35,7 @@ var _ server.Option
type AuthService interface {
Generate(ctx context.Context, in *GenerateRequest, opts ...client.CallOption) (*GenerateResponse, error)
Validate(ctx context.Context, in *ValidateRequest, opts ...client.CallOption) (*ValidateResponse, error)
Verify(ctx context.Context, in *VerifyRequest, opts ...client.CallOption) (*VerifyResponse, error)
Revoke(ctx context.Context, in *RevokeRequest, opts ...client.CallOption) (*RevokeResponse, error)
}
@ -45,12 +45,6 @@ type authService struct {
}
func NewAuthService(name string, c client.Client) AuthService {
if c == nil {
c = client.NewClient()
}
if len(name) == 0 {
name = "go.micro.auth"
}
return &authService{
c: c,
name: name,
@ -67,9 +61,9 @@ func (c *authService) Generate(ctx context.Context, in *GenerateRequest, opts ..
return out, nil
}
func (c *authService) Validate(ctx context.Context, in *ValidateRequest, opts ...client.CallOption) (*ValidateResponse, error) {
req := c.c.NewRequest(c.name, "Auth.Validate", in)
out := new(ValidateResponse)
func (c *authService) Verify(ctx context.Context, in *VerifyRequest, opts ...client.CallOption) (*VerifyResponse, error) {
req := c.c.NewRequest(c.name, "Auth.Verify", in)
out := new(VerifyResponse)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
@ -91,14 +85,14 @@ func (c *authService) Revoke(ctx context.Context, in *RevokeRequest, opts ...cli
type AuthHandler interface {
Generate(context.Context, *GenerateRequest, *GenerateResponse) error
Validate(context.Context, *ValidateRequest, *ValidateResponse) error
Verify(context.Context, *VerifyRequest, *VerifyResponse) error
Revoke(context.Context, *RevokeRequest, *RevokeResponse) error
}
func RegisterAuthHandler(s server.Server, hdlr AuthHandler, opts ...server.HandlerOption) error {
type auth interface {
Generate(ctx context.Context, in *GenerateRequest, out *GenerateResponse) error
Validate(ctx context.Context, in *ValidateRequest, out *ValidateResponse) error
Verify(ctx context.Context, in *VerifyRequest, out *VerifyResponse) error
Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error
}
type Auth struct {
@ -116,8 +110,8 @@ func (h *authHandler) Generate(ctx context.Context, in *GenerateRequest, out *Ge
return h.AuthHandler.Generate(ctx, in, out)
}
func (h *authHandler) Validate(ctx context.Context, in *ValidateRequest, out *ValidateResponse) error {
return h.AuthHandler.Validate(ctx, in, out)
func (h *authHandler) Verify(ctx context.Context, in *VerifyRequest, out *VerifyResponse) error {
return h.AuthHandler.Verify(ctx, in, out)
}
func (h *authHandler) Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error {

View File

@ -4,47 +4,47 @@ package go.micro.auth;
service Auth {
rpc Generate(GenerateRequest) returns (GenerateResponse) {};
rpc Validate(ValidateRequest) returns (ValidateResponse) {};
rpc Verify(VerifyRequest) returns (VerifyResponse) {};
rpc Revoke(RevokeRequest) returns (RevokeResponse) {};
}
message Account{
string id = 1;
string token = 2;
int64 created = 3;
int64 expiry = 4;
repeated Role roles = 5;
string id = 1;
string token = 2;
int64 created = 3;
int64 expiry = 4;
repeated Role roles = 5;
map<string, string> metadata = 6;
}
message Role {
string name = 1;
Resource resource = 2;
string name = 1;
Resource resource = 2;
}
message Resource{
string name = 1;
string type = 2;
string name = 1;
string type = 2;
}
message GenerateRequest {
Account account = 1;
Account account = 1;
}
message GenerateResponse {
Account account = 1;
Account account = 1;
}
message ValidateRequest {
string token = 1;
message VerifyRequest {
string token = 1;
}
message ValidateResponse {
Account account = 1;
message VerifyResponse {
Account account = 1;
}
message RevokeRequest {
string token = 1;
string token = 1;
}
message RevokeResponse {}

View File

@ -72,9 +72,9 @@ func (s *svc) Revoke(token string) error {
return err
}
// Validate an account token
func (s *svc) Validate(token string) (*auth.Account, error) {
resp, err := s.auth.Validate(context.Background(), &pb.ValidateRequest{Token: token})
// Verify an account token
func (s *svc) Verify(token string) (*auth.Account, error) {
resp, err := s.auth.Verify(context.Background(), &pb.VerifyRequest{Token: token})
if err != nil {
return nil, err
}

View File

@ -7,14 +7,19 @@ import (
"github.com/google/uuid"
"github.com/micro/go-micro/v2/auth"
"github.com/micro/go-micro/v2/errors"
"github.com/micro/go-micro/v2/store"
)
type Auth struct {
store store.Store
opts auth.Options
}
// NewAuth returns an instance of store auth
func NewAuth(opts ...auth.Option) auth.Auth {
options := auth.Options{}
var options auth.Options
for _, o := range opts {
o(&options)
}
@ -25,11 +30,6 @@ func NewAuth(opts ...auth.Option) auth.Auth {
}
}
type Auth struct {
store store.Store
opts auth.Options
}
// Init the auth package
func (a *Auth) Init(opts ...auth.Option) error {
for _, o := range opts {
@ -64,6 +64,7 @@ func (a *Auth) Generate(id string, opts ...auth.GenerateOption) (*auth.Account,
}
// encode the data to bytes
// TODO: replace with json
buf := &bytes.Buffer{}
e := gob.NewEncoder(buf)
if err := e.Encode(sa); err != nil {
@ -102,8 +103,8 @@ func (a *Auth) Revoke(token string) error {
return nil
}
// Validate an account token
func (a *Auth) Validate(token string) (*auth.Account, error) {
// Verify an account token
func (a *Auth) Verify(token string) (*auth.Account, error) {
// lookup the record by token
records, err := a.store.Read(token, store.ReadSuffix())
if err == store.ErrNotFound || len(records) == 0 {
@ -113,6 +114,7 @@ func (a *Auth) Validate(token string) (*auth.Account, error) {
}
// decode the result
// TODO: replace with json
b := bytes.NewBuffer(records[0].Value)
decoder := gob.NewDecoder(b)
var sa auth.Account

View File

@ -18,7 +18,6 @@ import (
"github.com/micro/go-micro/v2/errors"
"github.com/micro/go-micro/v2/metadata"
"github.com/micro/go-micro/v2/registry"
"github.com/micro/go-micro/v2/util/config"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@ -129,10 +128,6 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R
header["timeout"] = fmt.Sprintf("%d", opts.RequestTimeout)
// set the content type for the request
header["x-content-type"] = req.ContentType()
// set the authorization token if one is saved locally
if token, err := config.Get("token"); err == nil && len(token) > 0 {
header["authorization"] = fmt.Sprintf("Bearer %v", token)
}
md := gmetadata.New(header)
ctx = gmetadata.NewOutgoingContext(ctx, md)

View File

@ -249,6 +249,11 @@ var (
EnvVars: []string{"MICRO_AUTH"},
Usage: "Auth for role based access control, e.g. service",
},
&cli.StringFlag{
Name: "auth_token",
EnvVars: []string{"MICRO_AUTH_TOKEN"},
Usage: "Auth token used for client authentication",
},
&cli.StringFlag{
Name: "auth_public_key",
EnvVars: []string{"MICRO_AUTH_PUBLIC_KEY"},
@ -606,6 +611,10 @@ func (c *cmd) Before(ctx *cli.Context) error {
}
}
if len(ctx.String("auth_token")) > 0 {
authOpts = append(authOpts, auth.Token(ctx.String("auth_token")))
}
if len(ctx.String("auth_public_key")) > 0 {
authOpts = append(authOpts, auth.PublicKey(ctx.String("auth_public_key")))
}
@ -615,7 +624,7 @@ func (c *cmd) Before(ctx *cli.Context) error {
}
if len(ctx.StringSlice("auth_exclude")) > 0 {
authOpts = append(authOpts, auth.Excludes(ctx.StringSlice("auth_exclude")...))
authOpts = append(authOpts, auth.Exclude(ctx.StringSlice("auth_exclude")...))
}
if len(authOpts) > 0 {

View File

@ -17,6 +17,7 @@ import (
log "github.com/micro/go-micro/v2/logger"
"github.com/micro/go-micro/v2/plugin"
"github.com/micro/go-micro/v2/server"
"github.com/micro/go-micro/v2/util/config"
"github.com/micro/go-micro/v2/util/wrapper"
)
@ -37,7 +38,7 @@ func newService(opts ...Option) Service {
authFn := func() auth.Auth { return service.opts.Auth }
// wrap client to inject From-Service header on any calls
options.Client = wrapper.FromService(serviceName, options.Client)
options.Client = wrapper.FromService(serviceName, options.Client, authFn)
options.Client = wrapper.TraceCall(serviceName, trace.DefaultTracer, options.Client)
// wrap the server to provide handler stats
@ -102,6 +103,14 @@ func (s *service) Init(opts ...Option) {
); err != nil {
log.Fatal(err)
}
// TODO: replace Cmd.Init with config.Load
// Right now we're just going to load a token
// May need to re-read value on change
// TODO: should be scoped to micro/auth/token
if tk, _ := config.Get("token"); len(tk) > 0 {
s.opts.Auth.Init(auth.Token(tk))
}
})
}

View File

@ -15,6 +15,10 @@ import (
type clientWrapper struct {
client.Client
// Auth interface
auth func() auth.Auth
// headers to inject
headers metadata.Metadata
}
@ -27,7 +31,7 @@ type traceWrapper struct {
var (
HeaderPrefix = "Micro-"
BearerSchema = "Bearer "
BearerScheme = "Bearer "
)
func (c *clientWrapper) setHeaders(ctx context.Context) context.Context {
@ -35,6 +39,15 @@ func (c *clientWrapper) setHeaders(ctx context.Context) context.Context {
mda, _ := metadata.FromContext(ctx)
md := metadata.Copy(mda)
// get auth token
if a := c.auth(); a != nil {
tk := a.Options().Token
// if the token if exists and auth header isn't set then set it
if len(tk) > 0 && len(md["Authorization"]) == 0 {
md["Authorization"] = BearerScheme + tk
}
}
// set headers
for k, v := range c.headers {
if _, ok := md[k]; !ok {
@ -75,10 +88,11 @@ func (c *traceWrapper) Call(ctx context.Context, req client.Request, rsp interfa
return err
}
// FromService wraps a client to inject From-Service header into metadata
func FromService(name string, c client.Client) client.Client {
// FromService wraps a client to inject service and auth metadata
func FromService(name string, c client.Client, fn func() auth.Auth) client.Client {
return &clientWrapper{
c,
fn,
metadata.Metadata{
HeaderPrefix + "From-Service": name,
},
@ -151,7 +165,7 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper {
}
// Exclude any user excluded endpoints
for _, e := range a.Options().Excludes {
for _, e := range a.Options().Exclude {
if e == req.Endpoint() {
return h(ctx, req, rsp)
}
@ -162,15 +176,15 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper {
var token string
if header, ok := metadata.Get(ctx, "Authorization"); ok {
// Ensure the correct scheme is being used
if !strings.HasPrefix(header, BearerSchema) {
if !strings.HasPrefix(header, BearerScheme) {
return errors.Unauthorized("go.micro.auth", "invalid authorization header. expected Bearer schema")
}
token = header[len(BearerSchema):]
token = header[len(BearerScheme):]
}
// Validate the token
if _, err := a.Validate(token); err != nil {
// Verify the token
if _, err := a.Verify(token); err != nil {
return errors.Unauthorized("go.micro.auth", err.Error())
}

View File

@ -4,6 +4,7 @@ import (
"context"
"testing"
"github.com/micro/go-micro/v2/auth"
"github.com/micro/go-micro/v2/metadata"
)
@ -33,6 +34,7 @@ func TestWrapper(t *testing.T) {
for _, d := range testData {
c := &clientWrapper{
auth: func() auth.Auth { return nil },
headers: d.headers,
}