mirror of
				https://github.com/go-micro/go-micro.git
				synced 2025-10-30 23:27:41 +02:00 
			
		
		
		
	Auth (#1147)
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
This commit is contained in:
		
							
								
								
									
										48
									
								
								auth/auth.go
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								auth/auth.go
									
									
									
									
									
								
							| @@ -7,34 +7,44 @@ import ( | ||||
|  | ||||
| // Auth providers authentication and authorization | ||||
| type Auth interface { | ||||
| 	// Generate a new auth token | ||||
| 	Generate(string) (*Token, error) | ||||
| 	// Revoke an authorization token | ||||
| 	Revoke(*Token) error | ||||
| 	// Grant access to a resource | ||||
| 	Grant(*Token, *Service) error | ||||
| 	// Verify a token can access a resource | ||||
| 	Verify(*Token, *Service) error | ||||
| 	// String to identify the package | ||||
| 	String() string | ||||
| 	// Init the auth package | ||||
| 	Init(opts ...Option) error | ||||
| 	// Generate a new auth Account | ||||
| 	Generate(id string, opts ...GenerateOption) (*Account, error) | ||||
| 	// Revoke an authorization Account | ||||
| 	Revoke(token string) error | ||||
| 	// Validate an account token | ||||
| 	Validate(token string) (*Account, error) | ||||
| } | ||||
|  | ||||
| // Service is some thing to provide access to | ||||
| type Service struct { | ||||
| // Resource is an entity such as a user or | ||||
| type Resource struct { | ||||
| 	// Name of the resource | ||||
| 	Name string | ||||
| 	// Endpoint is the specific endpoint | ||||
| 	Endpoint string | ||||
| 	// Type of resource, e.g. | ||||
| 	Type string | ||||
| } | ||||
|  | ||||
| // Token providers by an auth provider | ||||
| type Token struct { | ||||
| 	// Unique token id | ||||
| // Role an account has | ||||
| type Role struct { | ||||
| 	Name     string | ||||
| 	Resource *Resource | ||||
| } | ||||
|  | ||||
| // Account provided by an auth provider | ||||
| type Account struct { | ||||
| 	// ID of the account (UUID or email) | ||||
| 	Id string `json: "id"` | ||||
| 	// Time of token creation | ||||
| 	// Token used to authenticate | ||||
| 	Token string `json: "token"` | ||||
| 	// Time of Account creation | ||||
| 	Created time.Time `json:"created"` | ||||
| 	// Time of token expiry | ||||
| 	// Time of Account expiry | ||||
| 	Expiry time.Time `json:"expiry"` | ||||
| 	// Roles associated with the token | ||||
| 	Roles []string `json:"roles"` | ||||
| 	// Roles associated with the Account | ||||
| 	Roles []*Role `json:"roles"` | ||||
| 	// Any other associated metadata | ||||
| 	Metadata map[string]string `json:"metadata"` | ||||
| } | ||||
|   | ||||
							
								
								
									
										34
									
								
								auth/default.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								auth/default.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										106
									
								
								auth/jwt/jwt.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								auth/jwt/jwt.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										57
									
								
								auth/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								auth/options.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
							
								
								
									
										466
									
								
								auth/service/proto/auth.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								auth/service/proto/auth.pb.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,466 @@ | ||||
| // Code generated by protoc-gen-go. DO NOT EDIT. | ||||
| // source: auth/service/proto/auth.proto | ||||
|  | ||||
| package go_micro_auth | ||||
|  | ||||
| import ( | ||||
| 	fmt "fmt" | ||||
| 	proto "github.com/golang/protobuf/proto" | ||||
| 	math "math" | ||||
| ) | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ = proto.Marshal | ||||
| var _ = fmt.Errorf | ||||
| var _ = math.Inf | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the proto package it is being compiled against. | ||||
| // A compilation error at this line likely means your copy of the | ||||
| // proto package needs to be updated. | ||||
| const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||
|  | ||||
| type Account struct { | ||||
| 	Id                   string            `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` | ||||
| 	Token                string            `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"` | ||||
| 	Created              int64             `protobuf:"varint,3,opt,name=created,proto3" json:"created,omitempty"` | ||||
| 	Expiry               int64             `protobuf:"varint,4,opt,name=expiry,proto3" json:"expiry,omitempty"` | ||||
| 	Roles                []*Role           `protobuf:"bytes,5,rep,name=roles,proto3" json:"roles,omitempty"` | ||||
| 	Metadata             map[string]string `protobuf:"bytes,6,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}          `json:"-"` | ||||
| 	XXX_unrecognized     []byte            `json:"-"` | ||||
| 	XXX_sizecache        int32             `json:"-"` | ||||
| } | ||||
|  | ||||
| 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} | ||||
| } | ||||
|  | ||||
| func (m *Account) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_Account.Unmarshal(m, b) | ||||
| } | ||||
| func (m *Account) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_Account.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *Account) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_Account.Merge(m, src) | ||||
| } | ||||
| func (m *Account) XXX_Size() int { | ||||
| 	return xxx_messageInfo_Account.Size(m) | ||||
| } | ||||
| func (m *Account) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_Account.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_Account proto.InternalMessageInfo | ||||
|  | ||||
| func (m *Account) GetId() string { | ||||
| 	if m != nil { | ||||
| 		return m.Id | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (m *Account) GetToken() string { | ||||
| 	if m != nil { | ||||
| 		return m.Token | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (m *Account) GetCreated() int64 { | ||||
| 	if m != nil { | ||||
| 		return m.Created | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *Account) GetExpiry() int64 { | ||||
| 	if m != nil { | ||||
| 		return m.Expiry | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *Account) GetRoles() []*Role { | ||||
| 	if m != nil { | ||||
| 		return m.Roles | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *Account) GetMetadata() map[string]string { | ||||
| 	if m != nil { | ||||
| 		return m.Metadata | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type Role struct { | ||||
| 	Name                 string    `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` | ||||
| 	Resource             *Resource `protobuf:"bytes,2,opt,name=resource,proto3" json:"resource,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}  `json:"-"` | ||||
| 	XXX_unrecognized     []byte    `json:"-"` | ||||
| 	XXX_sizecache        int32     `json:"-"` | ||||
| } | ||||
|  | ||||
| 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} | ||||
| } | ||||
|  | ||||
| func (m *Role) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_Role.Unmarshal(m, b) | ||||
| } | ||||
| func (m *Role) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_Role.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *Role) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_Role.Merge(m, src) | ||||
| } | ||||
| func (m *Role) XXX_Size() int { | ||||
| 	return xxx_messageInfo_Role.Size(m) | ||||
| } | ||||
| func (m *Role) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_Role.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_Role proto.InternalMessageInfo | ||||
|  | ||||
| func (m *Role) GetName() string { | ||||
| 	if m != nil { | ||||
| 		return m.Name | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (m *Role) GetResource() *Resource { | ||||
| 	if m != nil { | ||||
| 		return m.Resource | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type Resource struct { | ||||
| 	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` | ||||
| 	Type                 string   `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| 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} | ||||
| } | ||||
|  | ||||
| func (m *Resource) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_Resource.Unmarshal(m, b) | ||||
| } | ||||
| func (m *Resource) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_Resource.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *Resource) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_Resource.Merge(m, src) | ||||
| } | ||||
| func (m *Resource) XXX_Size() int { | ||||
| 	return xxx_messageInfo_Resource.Size(m) | ||||
| } | ||||
| func (m *Resource) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_Resource.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_Resource proto.InternalMessageInfo | ||||
|  | ||||
| func (m *Resource) GetName() string { | ||||
| 	if m != nil { | ||||
| 		return m.Name | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (m *Resource) GetType() string { | ||||
| 	if m != nil { | ||||
| 		return m.Type | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type GenerateRequest 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 *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} | ||||
| } | ||||
|  | ||||
| func (m *GenerateRequest) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_GenerateRequest.Unmarshal(m, b) | ||||
| } | ||||
| func (m *GenerateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_GenerateRequest.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *GenerateRequest) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_GenerateRequest.Merge(m, src) | ||||
| } | ||||
| func (m *GenerateRequest) XXX_Size() int { | ||||
| 	return xxx_messageInfo_GenerateRequest.Size(m) | ||||
| } | ||||
| func (m *GenerateRequest) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_GenerateRequest.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_GenerateRequest proto.InternalMessageInfo | ||||
|  | ||||
| func (m *GenerateRequest) GetAccount() *Account { | ||||
| 	if m != nil { | ||||
| 		return m.Account | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type GenerateResponse 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 *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} | ||||
| } | ||||
|  | ||||
| func (m *GenerateResponse) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_GenerateResponse.Unmarshal(m, b) | ||||
| } | ||||
| func (m *GenerateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_GenerateResponse.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *GenerateResponse) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_GenerateResponse.Merge(m, src) | ||||
| } | ||||
| func (m *GenerateResponse) XXX_Size() int { | ||||
| 	return xxx_messageInfo_GenerateResponse.Size(m) | ||||
| } | ||||
| func (m *GenerateResponse) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_GenerateResponse.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_GenerateResponse proto.InternalMessageInfo | ||||
|  | ||||
| func (m *GenerateResponse) GetAccount() *Account { | ||||
| 	if m != nil { | ||||
| 		return m.Account | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type ValidateRequest 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 *ValidateRequest) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_ValidateRequest.Unmarshal(m, b) | ||||
| } | ||||
| func (m *ValidateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_ValidateRequest.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *ValidateRequest) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_ValidateRequest.Merge(m, src) | ||||
| } | ||||
| func (m *ValidateRequest) XXX_Size() int { | ||||
| 	return xxx_messageInfo_ValidateRequest.Size(m) | ||||
| } | ||||
| func (m *ValidateRequest) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_ValidateRequest.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_ValidateRequest proto.InternalMessageInfo | ||||
|  | ||||
| func (m *ValidateRequest) GetToken() string { | ||||
| 	if m != nil { | ||||
| 		return m.Token | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type ValidateResponse 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 *ValidateResponse) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_ValidateResponse.Unmarshal(m, b) | ||||
| } | ||||
| func (m *ValidateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_ValidateResponse.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *ValidateResponse) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_ValidateResponse.Merge(m, src) | ||||
| } | ||||
| func (m *ValidateResponse) XXX_Size() int { | ||||
| 	return xxx_messageInfo_ValidateResponse.Size(m) | ||||
| } | ||||
| func (m *ValidateResponse) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_ValidateResponse.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_ValidateResponse proto.InternalMessageInfo | ||||
|  | ||||
| func (m *ValidateResponse) GetAccount() *Account { | ||||
| 	if m != nil { | ||||
| 		return m.Account | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type RevokeRequest 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 *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} | ||||
| } | ||||
|  | ||||
| func (m *RevokeRequest) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_RevokeRequest.Unmarshal(m, b) | ||||
| } | ||||
| func (m *RevokeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_RevokeRequest.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *RevokeRequest) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_RevokeRequest.Merge(m, src) | ||||
| } | ||||
| func (m *RevokeRequest) XXX_Size() int { | ||||
| 	return xxx_messageInfo_RevokeRequest.Size(m) | ||||
| } | ||||
| func (m *RevokeRequest) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_RevokeRequest.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_RevokeRequest proto.InternalMessageInfo | ||||
|  | ||||
| func (m *RevokeRequest) GetToken() string { | ||||
| 	if m != nil { | ||||
| 		return m.Token | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type RevokeResponse struct { | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| 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} | ||||
| } | ||||
|  | ||||
| func (m *RevokeResponse) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_RevokeResponse.Unmarshal(m, b) | ||||
| } | ||||
| func (m *RevokeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_RevokeResponse.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *RevokeResponse) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_RevokeResponse.Merge(m, src) | ||||
| } | ||||
| func (m *RevokeResponse) XXX_Size() int { | ||||
| 	return xxx_messageInfo_RevokeResponse.Size(m) | ||||
| } | ||||
| func (m *RevokeResponse) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_RevokeResponse.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_RevokeResponse proto.InternalMessageInfo | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterType((*Account)(nil), "go.micro.auth.Account") | ||||
| 	proto.RegisterMapType((map[string]string)(nil), "go.micro.auth.Account.MetadataEntry") | ||||
| 	proto.RegisterType((*Role)(nil), "go.micro.auth.Role") | ||||
| 	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((*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, | ||||
| } | ||||
							
								
								
									
										125
									
								
								auth/service/proto/auth.pb.micro.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								auth/service/proto/auth.pb.micro.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| // Code generated by protoc-gen-micro. DO NOT EDIT. | ||||
| // source: auth/service/proto/auth.proto | ||||
|  | ||||
| package go_micro_auth | ||||
|  | ||||
| import ( | ||||
| 	fmt "fmt" | ||||
| 	proto "github.com/golang/protobuf/proto" | ||||
| 	math "math" | ||||
| ) | ||||
|  | ||||
| import ( | ||||
| 	context "context" | ||||
| 	client "github.com/micro/go-micro/client" | ||||
| 	server "github.com/micro/go-micro/server" | ||||
| ) | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ = proto.Marshal | ||||
| var _ = fmt.Errorf | ||||
| var _ = math.Inf | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the proto package it is being compiled against. | ||||
| // A compilation error at this line likely means your copy of the | ||||
| // proto package needs to be updated. | ||||
| const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ context.Context | ||||
| var _ client.Option | ||||
| var _ server.Option | ||||
|  | ||||
| // Client API for Auth service | ||||
|  | ||||
| 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) | ||||
| 	Revoke(ctx context.Context, in *RevokeRequest, opts ...client.CallOption) (*RevokeResponse, error) | ||||
| } | ||||
|  | ||||
| type authService struct { | ||||
| 	c    client.Client | ||||
| 	name string | ||||
| } | ||||
|  | ||||
| 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, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *authService) Generate(ctx context.Context, in *GenerateRequest, opts ...client.CallOption) (*GenerateResponse, error) { | ||||
| 	req := c.c.NewRequest(c.name, "Auth.Generate", in) | ||||
| 	out := new(GenerateResponse) | ||||
| 	err := c.c.Call(ctx, req, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	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) | ||||
| 	err := c.c.Call(ctx, req, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *authService) Revoke(ctx context.Context, in *RevokeRequest, opts ...client.CallOption) (*RevokeResponse, error) { | ||||
| 	req := c.c.NewRequest(c.name, "Auth.Revoke", in) | ||||
| 	out := new(RevokeResponse) | ||||
| 	err := c.c.Call(ctx, req, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // Server API for Auth service | ||||
|  | ||||
| type AuthHandler interface { | ||||
| 	Generate(context.Context, *GenerateRequest, *GenerateResponse) error | ||||
| 	Validate(context.Context, *ValidateRequest, *ValidateResponse) 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 | ||||
| 		Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error | ||||
| 	} | ||||
| 	type Auth struct { | ||||
| 		auth | ||||
| 	} | ||||
| 	h := &authHandler{hdlr} | ||||
| 	return s.Handle(s.NewHandler(&Auth{h}, opts...)) | ||||
| } | ||||
|  | ||||
| type authHandler struct { | ||||
| 	AuthHandler | ||||
| } | ||||
|  | ||||
| func (h *authHandler) Generate(ctx context.Context, in *GenerateRequest, out *GenerateResponse) error { | ||||
| 	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) Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error { | ||||
| 	return h.AuthHandler.Revoke(ctx, in, out) | ||||
| } | ||||
							
								
								
									
										50
									
								
								auth/service/proto/auth.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								auth/service/proto/auth.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| syntax = "proto3"; | ||||
|  | ||||
| package go.micro.auth; | ||||
|  | ||||
| service Auth { | ||||
|     rpc Generate(GenerateRequest) returns (GenerateResponse) {}; | ||||
|     rpc Validate(ValidateRequest) returns (ValidateResponse) {}; | ||||
|     rpc Revoke(RevokeRequest)  returns (RevokeResponse) {}; | ||||
| } | ||||
|  | ||||
| message Account{ | ||||
|     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; | ||||
| } | ||||
|  | ||||
| message Resource{ | ||||
|     string name = 1; | ||||
|     string type = 2; | ||||
| } | ||||
|  | ||||
| message GenerateRequest { | ||||
|     Account account = 1; | ||||
| } | ||||
|  | ||||
| message GenerateResponse { | ||||
|     Account account = 1; | ||||
| } | ||||
|  | ||||
| message ValidateRequest { | ||||
|     string token = 1; | ||||
| } | ||||
|  | ||||
| message ValidateResponse { | ||||
|     Account account = 1; | ||||
| } | ||||
|  | ||||
| message RevokeRequest { | ||||
|     string token = 1; | ||||
| } | ||||
|  | ||||
| message RevokeResponse {} | ||||
							
								
								
									
										128
									
								
								auth/service/service.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								auth/service/service.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| package service | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	"github.com/micro/go-micro/v2/auth" | ||||
| 	pb "github.com/micro/go-micro/v2/auth/service/proto" | ||||
| ) | ||||
|  | ||||
| // 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 service implementation of the Auth interface | ||||
| type svc struct { | ||||
| 	options auth.Options | ||||
| 	auth    pb.AuthService | ||||
| } | ||||
|  | ||||
| func (s *svc) String() string { | ||||
| 	return "service" | ||||
| } | ||||
|  | ||||
| func (s *svc) Init(opts ...auth.Option) error { | ||||
| 	for _, o := range opts { | ||||
| 		o(&s.options) | ||||
| 	} | ||||
|  | ||||
| 	dc := client.DefaultClient | ||||
| 	s.auth = pb.NewAuthService("go.micro.auth", dc) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Generate a new auth account | ||||
| func (s *svc) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) { | ||||
| 	// construct the request | ||||
| 	options := auth.NewGenerateOptions(opts...) | ||||
| 	sa := &auth.Account{ | ||||
| 		Id:       id, | ||||
| 		Roles:    options.Roles, | ||||
| 		Metadata: options.Metadata, | ||||
| 	} | ||||
| 	req := &pb.GenerateRequest{Account: serializeAccount(sa)} | ||||
|  | ||||
| 	// execute the request | ||||
| 	resp, err := s.auth.Generate(context.Background(), req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// format the response | ||||
| 	return deserializeAccount(resp.Account), nil | ||||
| } | ||||
|  | ||||
| // Revoke an authorization account | ||||
| func (s *svc) Revoke(token string) error { | ||||
| 	// contruct the request | ||||
| 	req := &pb.RevokeRequest{Token: token} | ||||
|  | ||||
| 	// execute the request | ||||
| 	_, err := s.auth.Revoke(context.Background(), req) | ||||
| 	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}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return deserializeAccount(resp.Account), nil | ||||
| } | ||||
|  | ||||
| func serializeAccount(sa *auth.Account) *pb.Account { | ||||
| 	roles := make([]*pb.Role, len(sa.Roles)) | ||||
| 	for i, r := range sa.Roles { | ||||
| 		roles[i] = &pb.Role{ | ||||
| 			Name: r.Name, | ||||
| 		} | ||||
|  | ||||
| 		if r.Resource != nil { | ||||
| 			roles[i].Resource = &pb.Resource{ | ||||
| 				Name: r.Resource.Name, | ||||
| 				Type: r.Resource.Type, | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &pb.Account{ | ||||
| 		Id:       sa.Id, | ||||
| 		Roles:    roles, | ||||
| 		Metadata: sa.Metadata, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func deserializeAccount(a *pb.Account) *auth.Account { | ||||
| 	// format the response | ||||
| 	sa := &auth.Account{ | ||||
| 		Id:       a.Id, | ||||
| 		Token:    a.Token, | ||||
| 		Created:  time.Unix(a.Created, 0), | ||||
| 		Expiry:   time.Unix(a.Expiry, 0), | ||||
| 		Metadata: a.Metadata, | ||||
| 	} | ||||
|  | ||||
| 	sa.Roles = make([]*auth.Role, len(a.Roles)) | ||||
| 	for i, r := range a.Roles { | ||||
| 		sa.Roles[i] = &auth.Role{ | ||||
| 			Name: r.Name, | ||||
| 		} | ||||
|  | ||||
| 		if r.Resource != nil { | ||||
| 			sa.Roles[i].Resource = &auth.Resource{ | ||||
| 				Name: r.Resource.Name, | ||||
| 				Type: r.Resource.Type, | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return sa | ||||
| } | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/micro/go-micro/v2/auth" | ||||
| 	"github.com/micro/go-micro/v2/broker" | ||||
| 	"github.com/micro/go-micro/v2/client" | ||||
| 	"github.com/micro/go-micro/v2/client/selector" | ||||
| @@ -55,6 +56,10 @@ import ( | ||||
| 	// tracers | ||||
| 	// jTracer "github.com/micro/go-micro/v2/debug/trace/jaeger" | ||||
| 	memTracer "github.com/micro/go-micro/v2/debug/trace/memory" | ||||
|  | ||||
| 	// auth | ||||
| 	jwtAuth "github.com/micro/go-micro/v2/auth/jwt" | ||||
| 	sAuth "github.com/micro/go-micro/v2/auth/service" | ||||
| ) | ||||
|  | ||||
| type Cmd interface { | ||||
| @@ -223,6 +228,21 @@ var ( | ||||
| 			EnvVars: []string{"MICRO_TRACER_ADDRESS"}, | ||||
| 			Usage:   "Comma-separated list of tracer addresses", | ||||
| 		}, | ||||
| 		&cli.StringFlag{ | ||||
| 			Name:    "auth", | ||||
| 			EnvVars: []string{"MICRO_AUTH"}, | ||||
| 			Usage:   "Auth for role based access control, e.g. service", | ||||
| 		}, | ||||
| 		&cli.StringFlag{ | ||||
| 			Name:    "auth_public_key", | ||||
| 			EnvVars: []string{"MICRO_AUTH_PUBLIC_KEY"}, | ||||
| 			Usage:   "Public key for JWT auth (base64 encoded PEM)", | ||||
| 		}, | ||||
| 		&cli.StringFlag{ | ||||
| 			Name:    "auth_private_key", | ||||
| 			EnvVars: []string{"MICRO_AUTH_PRIVATE_KEY"}, | ||||
| 			Usage:   "Private key for JWT auth (base64 encoded PEM)", | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	DefaultBrokers = map[string]func(...broker.Option) broker.Broker{ | ||||
| @@ -274,6 +294,11 @@ var ( | ||||
| 		// "jaeger": jTracer.NewTracer, | ||||
| 	} | ||||
|  | ||||
| 	DefaultAuths = map[string]func(...auth.Option) auth.Auth{ | ||||
| 		"service": sAuth.NewAuth, | ||||
| 		"jwt":     jwtAuth.NewAuth, | ||||
| 	} | ||||
|  | ||||
| 	// used for default selection as the fall back | ||||
| 	defaultClient    = "grpc" | ||||
| 	defaultServer    = "grpc" | ||||
| @@ -300,6 +325,7 @@ func newCmd(opts ...Option) Cmd { | ||||
| 		Runtime:   &runtime.DefaultRuntime, | ||||
| 		Store:     &store.DefaultStore, | ||||
| 		Tracer:    &trace.DefaultTracer, | ||||
| 		Auth:      &auth.DefaultAuth, | ||||
|  | ||||
| 		Brokers:    DefaultBrokers, | ||||
| 		Clients:    DefaultClients, | ||||
| @@ -310,6 +336,7 @@ func newCmd(opts ...Option) Cmd { | ||||
| 		Runtimes:   DefaultRuntimes, | ||||
| 		Stores:     DefaultStores, | ||||
| 		Tracers:    DefaultTracers, | ||||
| 		Auths:      DefaultAuths, | ||||
| 	} | ||||
|  | ||||
| 	for _, o := range opts { | ||||
| @@ -382,6 +409,16 @@ func (c *cmd) Before(ctx *cli.Context) error { | ||||
| 		*c.opts.Tracer = r() | ||||
| 	} | ||||
|  | ||||
| 	// Set the auth | ||||
| 	if name := ctx.String("auth"); len(name) > 0 { | ||||
| 		r, ok := c.opts.Auths[name] | ||||
| 		if !ok { | ||||
| 			return fmt.Errorf("Unsupported auth: %s", name) | ||||
| 		} | ||||
|  | ||||
| 		*c.opts.Auth = r() | ||||
| 	} | ||||
|  | ||||
| 	// Set the client | ||||
| 	if name := ctx.String("client"); len(name) > 0 { | ||||
| 		// only change if we have the client and type differs | ||||
| @@ -531,6 +568,18 @@ func (c *cmd) Before(ctx *cli.Context) error { | ||||
| 		serverOpts = append(serverOpts, server.RegisterInterval(val*time.Second)) | ||||
| 	} | ||||
|  | ||||
| 	if len(ctx.String("auth_public_key")) > 0 { | ||||
| 		if err := (*c.opts.Auth).Init(auth.PublicKey(ctx.String("auth_public_key"))); err != nil { | ||||
| 			log.Fatalf("Error configuring auth: %v", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(ctx.String("auth_private_key")) > 0 { | ||||
| 		if err := (*c.opts.Auth).Init(auth.PrivateKey(ctx.String("auth_private_key"))); err != nil { | ||||
| 			log.Fatalf("Error configuring auth: %v", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// client opts | ||||
| 	if r := ctx.Int("client_retries"); r >= 0 { | ||||
| 		clientOpts = append(clientOpts, client.Retries(r)) | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package cmd | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/micro/go-micro/v2/auth" | ||||
| 	"github.com/micro/go-micro/v2/broker" | ||||
| 	"github.com/micro/go-micro/v2/client" | ||||
| 	"github.com/micro/go-micro/v2/client/selector" | ||||
| @@ -30,6 +31,7 @@ type Options struct { | ||||
| 	Runtime   *runtime.Runtime | ||||
| 	Store     *store.Store | ||||
| 	Tracer    *trace.Tracer | ||||
| 	Auth      *auth.Auth | ||||
|  | ||||
| 	Brokers    map[string]func(...broker.Option) broker.Broker | ||||
| 	Clients    map[string]func(...client.Option) client.Client | ||||
| @@ -40,6 +42,7 @@ type Options struct { | ||||
| 	Runtimes   map[string]func(...runtime.Option) runtime.Runtime | ||||
| 	Stores     map[string]func(...store.Option) store.Store | ||||
| 	Tracers    map[string]func(...trace.Option) trace.Tracer | ||||
| 	Auths      map[string]func(...auth.Option) auth.Auth | ||||
|  | ||||
| 	// Other options for implementations of the interface | ||||
| 	// can be stored in a context | ||||
| @@ -109,6 +112,12 @@ func Tracer(t *trace.Tracer) Option { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func Auth(a *auth.Auth) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Auth = a | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // New broker func | ||||
| func NewBroker(name string, b func(...broker.Option) broker.Broker) Option { | ||||
| 	return func(o *Options) { | ||||
| @@ -164,3 +173,10 @@ func NewTracer(name string, t func(...trace.Option) trace.Tracer) Option { | ||||
| 		o.Tracers[name] = t | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // New auth func | ||||
| func NewAuth(name string, t func(...auth.Option) auth.Auth) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Auths[name] = t | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @@ -8,6 +8,7 @@ require ( | ||||
| 	github.com/bitly/go-simplejson v0.5.0 | ||||
| 	github.com/bwmarrin/discordgo v0.20.2 | ||||
| 	github.com/coreos/etcd v3.3.18+incompatible | ||||
| 	github.com/dgrijalva/jwt-go v3.2.0+incompatible | ||||
| 	github.com/forestgiant/sliceutil v0.0.0-20160425183142-94783f95db6c | ||||
| 	github.com/fsnotify/fsnotify v1.4.7 | ||||
| 	github.com/fsouza/go-dockerclient v1.6.0 | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/micro/cli/v2" | ||||
| 	"github.com/micro/go-micro/v2/auth" | ||||
| 	"github.com/micro/go-micro/v2/broker" | ||||
| 	"github.com/micro/go-micro/v2/client" | ||||
| 	"github.com/micro/go-micro/v2/client/selector" | ||||
| @@ -120,6 +121,13 @@ func Tracer(t trace.Tracer) Option { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Auth sets the auth for the service | ||||
| func Auth(a auth.Auth) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Server.Init(server.Auth(a)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Selector sets the selector for the service client | ||||
| func Selector(s selector.Selector) Option { | ||||
| 	return func(o *Options) { | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/micro/go-micro/v2/auth" | ||||
| 	"github.com/micro/go-micro/v2/broker" | ||||
| 	"github.com/micro/go-micro/v2/codec" | ||||
| 	"github.com/micro/go-micro/v2/debug/trace" | ||||
| @@ -17,6 +18,7 @@ type Options struct { | ||||
| 	Broker       broker.Broker | ||||
| 	Registry     registry.Registry | ||||
| 	Tracer       trace.Tracer | ||||
| 	Auth         auth.Auth | ||||
| 	Transport    transport.Transport | ||||
| 	Metadata     map[string]string | ||||
| 	Name         string | ||||
| @@ -161,6 +163,13 @@ func Tracer(t trace.Tracer) Option { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Auth mechanism for role based access control | ||||
| func Auth(a auth.Auth) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Auth = a | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Transport mechanism for communication e.g http, rabbitmq, etc | ||||
| func Transport(t transport.Transport) Option { | ||||
| 	return func(o *Options) { | ||||
|   | ||||
| @@ -68,19 +68,26 @@ func (m *memoryStore) Read(key string, opts ...store.ReadOption) ([]*store.Recor | ||||
|  | ||||
| 	var vals []*memoryRecord | ||||
|  | ||||
| 	if !options.Prefix { | ||||
| 		v, ok := m.values[key] | ||||
| 		if !ok { | ||||
| 			return nil, store.ErrNotFound | ||||
| 		} | ||||
| 		vals = []*memoryRecord{v} | ||||
| 	} else { | ||||
| 	if options.Prefix { | ||||
| 		for _, v := range m.values { | ||||
| 			if !strings.HasPrefix(v.r.Key, key) { | ||||
| 				continue | ||||
| 			} | ||||
| 			vals = append(vals, v) | ||||
| 		} | ||||
| 	} else if options.Suffix { | ||||
| 		for _, v := range m.values { | ||||
| 			if !strings.HasSuffix(v.r.Key, key) { | ||||
| 				continue | ||||
| 			} | ||||
| 			vals = append(vals, v) | ||||
| 		} | ||||
| 	} else { | ||||
| 		v, ok := m.values[key] | ||||
| 		if !ok { | ||||
| 			return nil, store.ErrNotFound | ||||
| 		} | ||||
| 		vals = []*memoryRecord{v} | ||||
| 	} | ||||
|  | ||||
| 	//nolint:prealloc | ||||
|   | ||||
| @@ -11,6 +11,8 @@ type Options struct { | ||||
| 	Namespace string | ||||
| 	// Prefix of the keys used | ||||
| 	Prefix string | ||||
| 	// Suffix of the keys used | ||||
| 	Suffix string | ||||
| 	// Alternative options | ||||
| 	Context context.Context | ||||
| } | ||||
| @@ -45,3 +47,10 @@ func ReadPrefix() ReadOption { | ||||
| 		o.Prefix = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ReadSuffix uses the key as a suffix | ||||
| func ReadSuffix() ReadOption { | ||||
| 	return func(o *ReadOptions) { | ||||
| 		o.Suffix = true | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -39,6 +39,8 @@ type Record struct { | ||||
| type ReadOptions struct { | ||||
| 	// Read key as a prefix | ||||
| 	Prefix bool | ||||
| 	// Read key as a suffix | ||||
| 	Suffix bool | ||||
| } | ||||
|  | ||||
| type ReadOption func(o *ReadOptions) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user