Merge pull request #1459 from micro/auth-interface-update

Auth Interface Iteration
This commit is contained in:
ben-toogood 2020-04-01 17:56:38 +01:00 committed by GitHub
commit cd3d704aa5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 315 additions and 291 deletions

View File

@ -5,7 +5,6 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"time"
"github.com/micro/go-micro/v2/metadata"
@ -42,8 +41,8 @@ type Auth interface {
Verify(acc *Account, res *Resource) error
// Inspect a token
Inspect(token string) (*Account, error)
// Token generated using an account ID and secret
Token(id, secret string, opts ...TokenOption) (*Token, error)
// Token generated using refresh token
Token(opts ...TokenOption) (*Token, error)
// String returns the name of the implementation
String() string
}
@ -60,36 +59,32 @@ type Resource struct {
// Account provided by an auth provider
type Account struct {
// ID of the account (UUIDV4, email or username)
// ID of the account e.g. email
ID string `json:"id"`
// Secret used to renew the account
Secret string `json:"secret"`
// Type of the account, e.g. service
Type string `json:"type"`
// Provider who issued the account
Provider string `json:"provider"`
// Roles associated with the Account
Roles []string `json:"roles"`
// Any other associated metadata
Metadata map[string]string `json:"metadata"`
// Namespace the account belongs to, default blank
Namespace string `json:"namespace"`
// Secret for the account, e.g. the password
Secret string `json:"secret"`
}
// Token can be short or long lived
type Token struct {
// The token itself
Token string `json:"token"`
// Type of token, e.g. JWT
Type string `json:"type"`
// The token to be used for accessing resources
AccessToken string `json:"access_token"`
// RefreshToken to be used to generate a new token
RefreshToken string `json:"refresh_token"`
// Time of token creation
Created time.Time `json:"created"`
// Time of token expiry
Expiry time.Time `json:"expiry"`
// Subject of the token, e.g. the account ID
Subject string `json:"subject"`
// Roles granted to the token
Roles []string `json:"roles"`
// Metadata embedded in the token
Metadata map[string]string `json:"metadata"`
// Namespace the token belongs to
Namespace string `json:"namespace"`
}
const (
@ -132,8 +127,3 @@ func ContextWithAccount(ctx context.Context, account *Account) (context.Context,
// generate a new context with the MetadataKey set
return metadata.Set(ctx, MetadataKey, string(bytes)), nil
}
// ContextWithToken sets the auth token in the context
func ContextWithToken(ctx context.Context, token string) context.Context {
return metadata.Set(ctx, "Authorization", fmt.Sprintf("%v%v", BearerScheme, token))
}

View File

@ -40,8 +40,8 @@ func (n *noop) Generate(id string, opts ...GenerateOption) (*Account, error) {
return &Account{
ID: id,
Roles: options.Roles,
Secret: options.Secret,
Metadata: options.Metadata,
Secret: uuid.New().String(),
}, nil
}
@ -68,6 +68,6 @@ func (n *noop) Inspect(token string) (*Account, error) {
}
// Token generation using an account id and secret
func (n *noop) Token(id, secret string, opts ...TokenOption) (*Token, error) {
func (n *noop) Token(opts ...TokenOption) (*Token, error) {
return &Token{}, nil
}

View File

@ -10,13 +10,13 @@ import (
type Options struct {
// ID is the services auth ID
ID string
// Secret is used to generate new tokens
// Secret is used to authenticate the service
Secret string
// Token is the services token used to authenticate itself
Token *Token
// Public key base64 encoded
// PublicKey for decoding JWTs
PublicKey string
// Private key base64 encoded
// PrivateKey for encoding JWTs
PrivateKey string
// Provider is an auth provider
Provider provider.Provider
@ -78,10 +78,30 @@ type GenerateOptions struct {
Roles []string
// Namespace the account belongs too
Namespace string
// Provider of the account, e.g. oauth
Provider string
// Type of the account, e.g. user
Type string
// Secret used to authenticate the account
Secret string
}
type GenerateOption func(o *GenerateOptions)
// WithSecret for the generated account
func WithSecret(s string) GenerateOption {
return func(o *GenerateOptions) {
o.Secret = s
}
}
// WithType for the generated account
func WithType(t string) GenerateOption {
return func(o *GenerateOptions) {
o.Type = t
}
}
// WithMetadata for the generated account
func WithMetadata(md map[string]string) GenerateOption {
return func(o *GenerateOptions) {
@ -103,6 +123,13 @@ func WithNamespace(n string) GenerateOption {
}
}
// WithProvider for the generated account
func WithProvider(p string) GenerateOption {
return func(o *GenerateOptions) {
o.Provider = p
}
}
// NewGenerateOptions from a slice of options
func NewGenerateOptions(opts ...GenerateOption) GenerateOptions {
var options GenerateOptions
@ -113,16 +140,35 @@ func NewGenerateOptions(opts ...GenerateOption) GenerateOptions {
}
type TokenOptions struct {
// TokenExpiry is the time the token should live for
TokenExpiry time.Duration
// ID for the account
ID string
// Secret for the account
Secret string
// RefreshToken is used to refesh a token
RefreshToken string
// Expiry is the time the token should live for
Expiry time.Duration
}
type TokenOption func(o *TokenOptions)
// WithTokenExpiry for the token
func WithTokenExpiry(ex time.Duration) TokenOption {
// WithExpiry for the token
func WithExpiry(ex time.Duration) TokenOption {
return func(o *TokenOptions) {
o.TokenExpiry = ex
o.Expiry = ex
}
}
func WithCredentials(id, secret string) TokenOption {
return func(o *TokenOptions) {
o.ID = id
o.Secret = secret
}
}
func WithToken(rt string) TokenOption {
return func(o *TokenOptions) {
o.RefreshToken = rt
}
}
@ -134,8 +180,8 @@ func NewTokenOptions(opts ...TokenOption) TokenOptions {
}
// set defualt expiry of token
if options.TokenExpiry == 0 {
options.TokenExpiry = time.Minute
if options.Expiry == 0 {
options.Expiry = time.Minute
}
return options

View File

@ -25,7 +25,7 @@ func (b *basic) Options() provider.Options {
return b.opts
}
func (b *basic) Endpoint() string {
func (b *basic) Endpoint(...provider.EndpointOption) string {
return ""
}

View File

@ -3,7 +3,6 @@ package oauth
import (
"fmt"
"net/url"
"strings"
"github.com/micro/go-micro/v2/auth/provider"
)
@ -29,17 +28,25 @@ func (o *oauth) Options() provider.Options {
return o.opts
}
func (o *oauth) Endpoint() string {
func (o *oauth) Endpoint(opts ...provider.EndpointOption) string {
var options provider.EndpointOptions
for _, o := range opts {
o(&options)
}
params := make(url.Values)
params.Add("response_type", "code")
if len(options.State) > 0 {
params.Add("state", options.State)
}
if clientID := o.opts.ClientID; len(clientID) > 0 {
params.Add("client_id", clientID)
}
if scope := o.opts.Scope; len(scope) > 0 {
// spaces are url encoded since this cannot be passed in env vars
params.Add("scope", strings.ReplaceAll(scope, "%20", " "))
params.Add("scope", scope)
}
if redir := o.Redirect(); len(redir) > 0 {

View File

@ -12,7 +12,7 @@ type Provider interface {
// Options returns the options of a provider
Options() Options
// Endpoint for the provider
Endpoint() string
Endpoint(...EndpointOption) string
// Redirect url incase of UI
Redirect() string
}
@ -26,3 +26,15 @@ type Grant struct {
// Scopes associated with grant
Scopes []string
}
type EndpointOptions struct {
State string
}
type EndpointOption func(*EndpointOptions)
func WithState(c string) EndpointOption {
return func(o *EndpointOptions) {
o.State = c
}
}

View File

@ -119,14 +119,10 @@ func (m *ListAccountsResponse) GetAccounts() []*Account {
}
type Token struct {
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
RefreshToken string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_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"`
Subject string `protobuf:"bytes,5,opt,name=subject,proto3" json:"subject,omitempty"`
Roles []string `protobuf:"bytes,6,rep,name=roles,proto3" json:"roles,omitempty"`
Metadata map[string]string `protobuf:"bytes,7,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Namespace string `protobuf:"bytes,8,opt,name=namespace,proto3" json:"namespace,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -157,16 +153,16 @@ func (m *Token) XXX_DiscardUnknown() {
var xxx_messageInfo_Token proto.InternalMessageInfo
func (m *Token) GetToken() string {
func (m *Token) GetAccessToken() string {
if m != nil {
return m.Token
return m.AccessToken
}
return ""
}
func (m *Token) GetType() string {
func (m *Token) GetRefreshToken() string {
if m != nil {
return m.Type
return m.RefreshToken
}
return ""
}
@ -185,40 +181,14 @@ func (m *Token) GetExpiry() int64 {
return 0
}
func (m *Token) GetSubject() string {
if m != nil {
return m.Subject
}
return ""
}
func (m *Token) GetRoles() []string {
if m != nil {
return m.Roles
}
return nil
}
func (m *Token) GetMetadata() map[string]string {
if m != nil {
return m.Metadata
}
return nil
}
func (m *Token) GetNamespace() string {
if m != nil {
return m.Namespace
}
return ""
}
type Account struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Secret string `protobuf:"bytes,2,opt,name=secret,proto3" json:"secret,omitempty"`
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
Roles []string `protobuf:"bytes,3,rep,name=roles,proto3" json:"roles,omitempty"`
Metadata map[string]string `protobuf:"bytes,4,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Namespace string `protobuf:"bytes,5,opt,name=namespace,proto3" json:"namespace,omitempty"`
Provider string `protobuf:"bytes,6,opt,name=provider,proto3" json:"provider,omitempty"`
Secret string `protobuf:"bytes,7,opt,name=secret,proto3" json:"secret,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -256,9 +226,9 @@ func (m *Account) GetId() string {
return ""
}
func (m *Account) GetSecret() string {
func (m *Account) GetType() string {
if m != nil {
return m.Secret
return m.Type
}
return ""
}
@ -284,6 +254,20 @@ func (m *Account) GetNamespace() string {
return ""
}
func (m *Account) GetProvider() string {
if m != nil {
return m.Provider
}
return ""
}
func (m *Account) GetSecret() string {
if m != nil {
return m.Secret
}
return ""
}
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"`
@ -344,6 +328,9 @@ type GenerateRequest struct {
Roles []string `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"`
Metadata map[string]string `protobuf:"bytes,3,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Namespace string `protobuf:"bytes,4,opt,name=namespace,proto3" json:"namespace,omitempty"`
Secret string `protobuf:"bytes,5,opt,name=secret,proto3" json:"secret,omitempty"`
Type string `protobuf:"bytes,6,opt,name=type,proto3" json:"type,omitempty"`
Provider string `protobuf:"bytes,7,opt,name=provider,proto3" json:"provider,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -402,6 +389,27 @@ func (m *GenerateRequest) GetNamespace() string {
return ""
}
func (m *GenerateRequest) GetSecret() string {
if m != nil {
return m.Secret
}
return ""
}
func (m *GenerateRequest) GetType() string {
if m != nil {
return m.Type
}
return ""
}
func (m *GenerateRequest) GetProvider() string {
if m != nil {
return m.Provider
}
return ""
}
type GenerateResponse struct {
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
@ -678,7 +686,8 @@ func (m *InspectResponse) GetAccount() *Account {
type TokenRequest struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Secret string `protobuf:"bytes,2,opt,name=secret,proto3" json:"secret,omitempty"`
TokenExpiry int64 `protobuf:"varint,3,opt,name=token_expiry,json=tokenExpiry,proto3" json:"token_expiry,omitempty"`
RefreshToken string `protobuf:"bytes,3,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
TokenExpiry int64 `protobuf:"varint,4,opt,name=token_expiry,json=tokenExpiry,proto3" json:"token_expiry,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -723,6 +732,13 @@ func (m *TokenRequest) GetSecret() string {
return ""
}
func (m *TokenRequest) GetRefreshToken() string {
if m != nil {
return m.RefreshToken
}
return ""
}
func (m *TokenRequest) GetTokenExpiry() int64 {
if m != nil {
return m.TokenExpiry
@ -1079,7 +1095,6 @@ func init() {
proto.RegisterType((*ListAccountsRequest)(nil), "go.micro.auth.ListAccountsRequest")
proto.RegisterType((*ListAccountsResponse)(nil), "go.micro.auth.ListAccountsResponse")
proto.RegisterType((*Token)(nil), "go.micro.auth.Token")
proto.RegisterMapType((map[string]string)(nil), "go.micro.auth.Token.MetadataEntry")
proto.RegisterType((*Account)(nil), "go.micro.auth.Account")
proto.RegisterMapType((map[string]string)(nil), "go.micro.auth.Account.MetadataEntry")
proto.RegisterType((*Resource)(nil), "go.micro.auth.Resource")
@ -1108,59 +1123,61 @@ func init() {
}
var fileDescriptor_11312eec02fd5712 = []byte{
// 860 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0xdd, 0x8e, 0xdb, 0x44,
0x14, 0x5e, 0xff, 0xc4, 0xf1, 0x9e, 0xfc, 0x6c, 0x34, 0xdd, 0x16, 0x2b, 0xfd, 0x21, 0x18, 0x84,
0x96, 0x8a, 0x3a, 0x28, 0xbd, 0xe0, 0xa7, 0x12, 0x22, 0x6a, 0xa2, 0xd0, 0x42, 0x83, 0xb0, 0x8a,
0x0a, 0x17, 0x08, 0x79, 0x9d, 0xa3, 0x5d, 0xb3, 0x89, 0x1d, 0x3c, 0xe3, 0x15, 0x79, 0x02, 0xee,
0x78, 0x14, 0x9e, 0xa8, 0x97, 0x48, 0xbc, 0x06, 0x9a, 0xf1, 0x8c, 0x37, 0x71, 0x9c, 0x55, 0x84,
0x72, 0xc1, 0xdd, 0x9c, 0x99, 0x33, 0xdf, 0x7c, 0xdf, 0xe7, 0x33, 0xc7, 0x03, 0x9f, 0x5e, 0x44,
0xec, 0x32, 0x3b, 0xf7, 0xc2, 0x64, 0xd1, 0x5f, 0x44, 0x61, 0x9a, 0xf4, 0x2f, 0x92, 0x27, 0xf9,
0x20, 0xc8, 0xd8, 0x65, 0x9f, 0x62, 0x7a, 0x1d, 0x85, 0xd8, 0x5f, 0xa6, 0x09, 0xcb, 0xa7, 0x3c,
0x31, 0x24, 0xad, 0x8b, 0xc4, 0x13, 0x79, 0x1e, 0x9f, 0x74, 0xef, 0xc2, 0x9d, 0x6f, 0x23, 0xca,
0x86, 0x61, 0x98, 0x64, 0x31, 0xa3, 0x3e, 0xfe, 0x96, 0x21, 0x65, 0xee, 0x4b, 0x38, 0xdd, 0x9c,
0xa6, 0xcb, 0x24, 0xa6, 0x48, 0x06, 0x60, 0x07, 0x72, 0xce, 0xd1, 0x7a, 0xc6, 0x59, 0x63, 0x70,
0xcf, 0xdb, 0x00, 0xf4, 0xe4, 0x16, 0xbf, 0xc8, 0x73, 0xff, 0xd2, 0xa1, 0xf6, 0x3a, 0xb9, 0xc2,
0x98, 0x9c, 0x42, 0x8d, 0xf1, 0x81, 0xa3, 0xf5, 0xb4, 0xb3, 0x63, 0x3f, 0x0f, 0x08, 0x01, 0x93,
0xad, 0x96, 0xe8, 0xe8, 0x62, 0x52, 0x8c, 0x89, 0x03, 0xf5, 0x30, 0xc5, 0x80, 0xe1, 0xcc, 0x31,
0x7a, 0xda, 0x99, 0xe1, 0xab, 0x90, 0xdc, 0x03, 0x0b, 0x7f, 0x5f, 0x46, 0xe9, 0xca, 0x31, 0xc5,
0x82, 0x8c, 0xf8, 0x0e, 0x9a, 0x9d, 0xff, 0x8a, 0x21, 0x73, 0x6a, 0x02, 0x48, 0x85, 0xfc, 0xd4,
0x34, 0x99, 0x23, 0x75, 0xac, 0x9e, 0xc1, 0x4f, 0x15, 0x01, 0xf9, 0x12, 0xec, 0x05, 0xb2, 0x60,
0x16, 0xb0, 0xc0, 0xa9, 0x0b, 0x25, 0x6e, 0x49, 0x89, 0xe0, 0xec, 0xbd, 0x92, 0x49, 0xe3, 0x98,
0xa5, 0x2b, 0xbf, 0xd8, 0x43, 0x1e, 0xc0, 0x71, 0x1c, 0x2c, 0x90, 0x2e, 0x83, 0x10, 0x1d, 0x5b,
0x9c, 0x78, 0x33, 0xd1, 0x7d, 0x06, 0xad, 0x8d, 0x8d, 0xa4, 0x03, 0xc6, 0x15, 0xae, 0xa4, 0x70,
0x3e, 0xe4, 0xb4, 0xae, 0x83, 0x79, 0xa6, 0x74, 0xe7, 0xc1, 0x17, 0xfa, 0x67, 0x9a, 0xfb, 0xb7,
0x06, 0x75, 0x69, 0x23, 0x69, 0x83, 0x1e, 0xcd, 0xe4, 0x36, 0x3d, 0x12, 0xf2, 0x29, 0x86, 0x29,
0x32, 0xb9, 0x4d, 0x46, 0x37, 0x22, 0x8d, 0x75, 0x91, 0x5f, 0xad, 0x89, 0x34, 0x85, 0xc8, 0x0f,
0xaa, 0x3f, 0xd7, 0x7e, 0x32, 0x6b, 0x07, 0x95, 0x39, 0x05, 0xdb, 0x47, 0x9a, 0x64, 0x69, 0x88,
0xbc, 0x06, 0x38, 0xaa, 0xdc, 0x28, 0xc6, 0x95, 0x75, 0xd1, 0x05, 0x1b, 0xe3, 0xd9, 0x32, 0x89,
0x62, 0x26, 0x0a, 0xe3, 0xd8, 0x2f, 0x62, 0xf7, 0xad, 0x06, 0x27, 0x13, 0x8c, 0x31, 0x0d, 0x18,
0xca, 0x3a, 0xde, 0xb2, 0xaf, 0xb0, 0x49, 0x5f, 0xb7, 0xe9, 0xeb, 0x35, 0x9b, 0x0c, 0x61, 0xd3,
0xc7, 0x25, 0x9b, 0x4a, 0xb8, 0xfb, 0xd9, 0x65, 0x1e, 0xd4, 0xae, 0x11, 0x74, 0x6e, 0x58, 0xc8,
0xeb, 0xf8, 0x09, 0xd4, 0xe5, 0x35, 0x13, 0x18, 0xbb, 0x6f, 0xa3, 0x4a, 0x73, 0xdf, 0x40, 0x73,
0x92, 0x06, 0x31, 0x53, 0x06, 0x11, 0x30, 0xb9, 0x07, 0xca, 0x78, 0x3e, 0x26, 0x4f, 0xc1, 0x4e,
0xe5, 0x87, 0x11, 0x34, 0x1a, 0x83, 0x77, 0x4a, 0xb0, 0xea, 0xbb, 0xf9, 0x45, 0xa2, 0x7b, 0x02,
0x2d, 0x09, 0x9c, 0x73, 0x73, 0x7f, 0x84, 0x96, 0x8f, 0xd7, 0xc9, 0x15, 0x1e, 0xfc, 0xa8, 0x0e,
0xb4, 0x15, 0xb2, 0x3c, 0xeb, 0x43, 0x68, 0xbf, 0x88, 0xe9, 0x12, 0xc3, 0x42, 0x57, 0x65, 0xab,
0x71, 0x9f, 0xc3, 0x49, 0x91, 0xf7, 0x9f, 0x2d, 0xfc, 0x09, 0x9a, 0xa2, 0x35, 0xec, 0xaa, 0xb1,
0x5d, 0x57, 0xf4, 0x3d, 0x68, 0x0a, 0x16, 0xbf, 0xc8, 0xfe, 0x95, 0x37, 0xb6, 0x86, 0x98, 0x1b,
0x8b, 0x29, 0xf7, 0x19, 0xb4, 0x24, 0xb4, 0x64, 0xf7, 0x78, 0x5d, 0x46, 0x63, 0x70, 0x5a, 0xd5,
0xa2, 0x94, 0xb8, 0x3f, 0x35, 0x30, 0xfd, 0x6c, 0x8e, 0x5b, 0x84, 0x94, 0xf1, 0xfa, 0x0e, 0xe3,
0x8d, 0x3d, 0x8d, 0x27, 0x4f, 0xc0, 0x0a, 0xc2, 0x10, 0x29, 0x15, 0xa5, 0xdd, 0x1e, 0xdc, 0xdd,
0xb6, 0x0a, 0x29, 0xf5, 0x65, 0x92, 0xfb, 0x87, 0x06, 0xad, 0xe7, 0xa2, 0x6d, 0x1f, 0xba, 0x04,
0xd6, 0x98, 0x18, 0xfb, 0x30, 0xe9, 0x40, 0x5b, 0x11, 0x91, 0x15, 0xc3, 0xb9, 0x8d, 0x70, 0x8e,
0xff, 0x0b, 0x6e, 0x8a, 0x88, 0xe4, 0xd6, 0x82, 0x06, 0xff, 0xf9, 0xaa, 0x7f, 0xf1, 0xe7, 0xd0,
0xcc, 0x43, 0x59, 0x13, 0x1f, 0x41, 0x2d, 0xcd, 0x78, 0x0f, 0xcb, 0x7f, 0xc0, 0x77, 0xca, 0x8c,
0xb2, 0x39, 0xfa, 0x79, 0xc6, 0x63, 0x0f, 0xac, 0xfc, 0x34, 0xd2, 0x80, 0xfa, 0x0f, 0xd3, 0x6f,
0xa6, 0xdf, 0xbd, 0x99, 0x76, 0x8e, 0x78, 0x30, 0xf1, 0x87, 0xd3, 0xd7, 0xe3, 0x51, 0x47, 0x23,
0x00, 0xd6, 0x68, 0x3c, 0x7d, 0x31, 0x1e, 0x75, 0xf4, 0xc1, 0x3f, 0x1a, 0x98, 0xc3, 0x8c, 0x5d,
0x92, 0x57, 0x60, 0xab, 0x66, 0x43, 0x1e, 0xdd, 0xde, 0x0b, 0xbb, 0xef, 0xee, 0x5c, 0x97, 0x7a,
0x8e, 0xc8, 0x4b, 0xa8, 0xcb, 0x7b, 0x47, 0x1e, 0x96, 0xb2, 0x37, 0xef, 0x6d, 0xf7, 0xd1, 0xae,
0xe5, 0x02, 0x6b, 0xa4, 0x5e, 0x13, 0xf7, 0x2b, 0x2f, 0x83, 0xc4, 0x79, 0x50, 0xbd, 0xa8, 0x50,
0x06, 0x3f, 0x83, 0xad, 0x1e, 0x37, 0xe4, 0x7b, 0x30, 0xb9, 0xc1, 0xa4, 0xfc, 0x00, 0xa8, 0x78,
0x18, 0x75, 0xdf, 0xbf, 0x35, 0xa7, 0x80, 0x7f, 0xab, 0x41, 0x8d, 0x7f, 0x08, 0x4a, 0x26, 0x60,
0xe5, 0xa5, 0x47, 0xca, 0x94, 0x36, 0xae, 0x46, 0xf7, 0xe1, 0x8e, 0xd5, 0x42, 0xf7, 0x04, 0xac,
0xbc, 0x4e, 0xb6, 0x80, 0x36, 0xea, 0x78, 0x0b, 0xa8, 0x54, 0x5c, 0x47, 0x64, 0x28, 0xe5, 0x76,
0x2b, 0xa4, 0x28, 0x90, 0xfb, 0x95, 0x6b, 0x0a, 0xe2, 0xdc, 0x12, 0x6f, 0xc9, 0xa7, 0xff, 0x06,
0x00, 0x00, 0xff, 0xff, 0x24, 0x1b, 0xf8, 0x32, 0x86, 0x0a, 0x00, 0x00,
// 896 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0x4b, 0x6f, 0xdb, 0x46,
0x10, 0x36, 0x49, 0x89, 0x92, 0x47, 0x0f, 0x0b, 0x1b, 0x27, 0x25, 0x98, 0x47, 0x1d, 0xa6, 0x28,
0xdc, 0xa0, 0xa1, 0x0b, 0xe5, 0xd0, 0x47, 0x2e, 0x35, 0x22, 0x41, 0x4d, 0xda, 0xa8, 0x28, 0x91,
0x22, 0xbd, 0x14, 0x01, 0x43, 0x4d, 0x6d, 0xc2, 0x32, 0xc9, 0xee, 0x2e, 0x8d, 0xfa, 0x52, 0xa0,
0xa7, 0xde, 0x7a, 0xea, 0x4f, 0xe8, 0xcf, 0xea, 0xbd, 0x7f, 0xa3, 0xe0, 0x3e, 0x28, 0x91, 0xa2,
0x02, 0xa3, 0xf5, 0x21, 0xb7, 0x9d, 0x07, 0x67, 0xe6, 0xfb, 0x66, 0x76, 0xb8, 0xf0, 0xe9, 0x49,
0xcc, 0x4f, 0xf3, 0x37, 0x7e, 0x94, 0x9e, 0x1f, 0x9d, 0xc7, 0x11, 0x4d, 0x8f, 0x4e, 0xd2, 0x47,
0xf2, 0x10, 0xe6, 0xfc, 0xf4, 0x88, 0x21, 0xbd, 0x88, 0x23, 0x3c, 0xca, 0x68, 0xca, 0xa5, 0xca,
0x17, 0x47, 0x32, 0x38, 0x49, 0x7d, 0xe1, 0xe7, 0x17, 0x4a, 0xef, 0x26, 0xdc, 0xf8, 0x26, 0x66,
0xfc, 0x38, 0x8a, 0xd2, 0x3c, 0xe1, 0x2c, 0xc0, 0x9f, 0x73, 0x64, 0xdc, 0x7b, 0x0e, 0xfb, 0x55,
0x35, 0xcb, 0xd2, 0x84, 0x21, 0x19, 0x43, 0x37, 0x54, 0x3a, 0xc7, 0x38, 0xb0, 0x0e, 0x7b, 0xe3,
0x5b, 0x7e, 0x25, 0xa0, 0xaf, 0x3e, 0x09, 0x4a, 0x3f, 0xef, 0x37, 0x03, 0xda, 0x2f, 0xd3, 0x33,
0x4c, 0xc8, 0x7d, 0xe8, 0x87, 0x51, 0x84, 0x8c, 0xbd, 0xe6, 0x85, 0xec, 0x18, 0x07, 0xc6, 0xe1,
0x6e, 0xd0, 0x93, 0x3a, 0xe9, 0xf2, 0x00, 0x06, 0x14, 0x7f, 0xa2, 0xc8, 0x4e, 0x95, 0x8f, 0x29,
0x7c, 0xfa, 0x4a, 0x29, 0x9d, 0x1c, 0xe8, 0x44, 0x14, 0x43, 0x8e, 0x0b, 0xc7, 0x3a, 0x30, 0x0e,
0xad, 0x40, 0x8b, 0xe4, 0x16, 0xd8, 0xf8, 0x4b, 0x16, 0xd3, 0x4b, 0xa7, 0x25, 0x0c, 0x4a, 0xf2,
0xfe, 0x34, 0xa1, 0xa3, 0x2a, 0x23, 0x43, 0x30, 0xe3, 0x85, 0xca, 0x6d, 0xc6, 0x0b, 0x42, 0xa0,
0xc5, 0x2f, 0x33, 0x54, 0x99, 0xc4, 0x99, 0xec, 0x43, 0x9b, 0xa6, 0x4b, 0x64, 0x8e, 0x75, 0x60,
0x1d, 0xee, 0x06, 0x52, 0x20, 0x5f, 0x42, 0xf7, 0x1c, 0x79, 0xb8, 0x08, 0x79, 0xe8, 0xb4, 0x04,
0xfa, 0x0f, 0x9a, 0xd1, 0xfb, 0x2f, 0x94, 0xdb, 0x34, 0xe1, 0xf4, 0x32, 0x28, 0xbf, 0x22, 0x77,
0x60, 0x37, 0x09, 0xcf, 0x91, 0x65, 0x61, 0x84, 0x4e, 0x5b, 0x24, 0x5c, 0x29, 0x88, 0x0b, 0xdd,
0x8c, 0xa6, 0x17, 0xf1, 0x02, 0xa9, 0x63, 0x0b, 0x63, 0x29, 0x17, 0xc8, 0x18, 0x46, 0x14, 0xb9,
0xd3, 0x11, 0x16, 0x25, 0xb9, 0x4f, 0x60, 0x50, 0x49, 0x46, 0x46, 0x60, 0x9d, 0xe1, 0xa5, 0xc2,
0x57, 0x1c, 0x0b, 0x30, 0x17, 0xe1, 0x32, 0xd7, 0x08, 0xa5, 0xf0, 0x85, 0xf9, 0x99, 0xe1, 0xcd,
0xa1, 0x1b, 0x20, 0x4b, 0x73, 0x1a, 0x61, 0x41, 0x43, 0x51, 0x89, 0xfa, 0x50, 0x9c, 0x1b, 0xa9,
0x71, 0xa1, 0x8b, 0xc9, 0x22, 0x4b, 0xe3, 0x84, 0x0b, 0xf6, 0x77, 0x83, 0x52, 0xf6, 0xfe, 0x32,
0x61, 0x6f, 0x86, 0x09, 0xd2, 0x90, 0xa3, 0x1a, 0xa5, 0x0d, 0xba, 0x4b, 0x6a, 0xcd, 0x75, 0x6a,
0xbf, 0x5a, 0xa3, 0xd6, 0x12, 0xd4, 0x7e, 0x5c, 0xa3, 0xb6, 0x16, 0xf7, 0x6a, 0x14, 0xb7, 0xea,
0x14, 0xaf, 0x68, 0x6c, 0xaf, 0xd3, 0x58, 0x22, 0xb5, 0xab, 0x48, 0xcb, 0x76, 0x74, 0xaa, 0xed,
0xf8, 0x7f, 0xb4, 0x4f, 0x60, 0xb4, 0x42, 0xa3, 0x6e, 0xd6, 0x27, 0xd0, 0x51, 0x37, 0x46, 0xc4,
0xd8, 0x7e, 0xb1, 0xb4, 0x9b, 0xf7, 0x0a, 0xfa, 0x33, 0x1a, 0x26, 0x5c, 0x13, 0x4d, 0xa0, 0x55,
0x70, 0xa9, 0x1b, 0x58, 0x9c, 0xc9, 0x63, 0xe8, 0x52, 0xd5, 0x60, 0x51, 0x46, 0x6f, 0xfc, 0x5e,
0x2d, 0xac, 0xee, 0x7f, 0x50, 0x3a, 0x7a, 0x7b, 0x30, 0x50, 0x81, 0x65, 0x6d, 0xde, 0x0f, 0x30,
0x08, 0xf0, 0x22, 0x3d, 0xc3, 0x6b, 0x4f, 0x35, 0x82, 0xa1, 0x8e, 0xac, 0x72, 0x7d, 0x08, 0xc3,
0x67, 0x09, 0xcb, 0x30, 0x2a, 0x71, 0xed, 0x43, 0x7b, 0x7d, 0x5d, 0x48, 0xc1, 0x7b, 0x0a, 0x7b,
0xa5, 0xdf, 0x7f, 0xa6, 0xf0, 0x57, 0xe8, 0x8b, 0x8d, 0xb2, 0x6d, 0x56, 0x57, 0xd3, 0x62, 0x56,
0xa6, 0x65, 0x63, 0x4b, 0x59, 0x0d, 0x5b, 0xea, 0x3e, 0xf4, 0x85, 0xf1, 0x75, 0x65, 0x23, 0xf5,
0x84, 0x6e, 0x2a, 0xd7, 0xd2, 0x13, 0x18, 0xa8, 0xfc, 0x0a, 0xc2, 0xc3, 0x75, 0xac, 0xbd, 0xf1,
0x7e, 0x0d, 0x80, 0x74, 0x56, 0x0c, 0xfc, 0x61, 0x40, 0x2b, 0xc8, 0x97, 0xd8, 0xb4, 0xd0, 0x44,
0x77, 0xcc, 0x2d, 0xdd, 0xb1, 0xae, 0xd8, 0x1d, 0xf2, 0x08, 0x6c, 0xb9, 0x9b, 0x45, 0xed, 0xc3,
0xf1, 0xcd, 0x4d, 0x3e, 0x91, 0xb1, 0x40, 0x39, 0x79, 0xbf, 0x1b, 0x30, 0x78, 0x2a, 0x16, 0xf1,
0x75, 0xcf, 0xc9, 0x5a, 0x25, 0xd6, 0x55, 0x2a, 0x19, 0xc1, 0x50, 0x17, 0xa2, 0xc6, 0xaa, 0xa8,
0x6d, 0x82, 0x4b, 0x7c, 0x27, 0x6a, 0xd3, 0x85, 0xa8, 0xda, 0x06, 0xd0, 0x2b, 0x7e, 0xb6, 0xfa,
0xdf, 0xfb, 0x39, 0xf4, 0xa5, 0xa8, 0x66, 0xe2, 0x23, 0x68, 0xd3, 0xbc, 0x58, 0x98, 0xf2, 0x87,
0x7b, 0xa3, 0x5e, 0x51, 0xbe, 0xc4, 0x40, 0x7a, 0x3c, 0xf4, 0xc1, 0x96, 0xd9, 0x48, 0x0f, 0x3a,
0xdf, 0xcf, 0xbf, 0x9e, 0x7f, 0xfb, 0x6a, 0x3e, 0xda, 0x29, 0x84, 0x59, 0x70, 0x3c, 0x7f, 0x39,
0x9d, 0x8c, 0x0c, 0x02, 0x60, 0x4f, 0xa6, 0xf3, 0x67, 0xd3, 0xc9, 0xc8, 0x1c, 0xff, 0x63, 0x40,
0xeb, 0x38, 0xe7, 0xa7, 0xe4, 0x05, 0x74, 0xf5, 0x46, 0x22, 0xf7, 0xde, 0xbe, 0x78, 0xdd, 0xf7,
0xb7, 0xda, 0x15, 0x9e, 0x1d, 0xf2, 0x1c, 0x3a, 0xea, 0x72, 0x92, 0xbb, 0x35, 0xef, 0xea, 0xe5,
0x76, 0xef, 0x6d, 0x33, 0x97, 0xb1, 0x26, 0xfa, 0xf5, 0x70, 0xbb, 0xf1, 0x32, 0xa8, 0x38, 0x77,
0x9a, 0x8d, 0x3a, 0xca, 0xf8, 0x47, 0xe8, 0xea, 0xc7, 0x0c, 0xf9, 0x0e, 0x5a, 0x05, 0xc1, 0xc4,
0xab, 0x7d, 0xd3, 0xf0, 0x10, 0x72, 0x1f, 0xbc, 0xd5, 0xa7, 0x0c, 0xff, 0xb7, 0x01, 0xed, 0xa2,
0x11, 0x8c, 0xcc, 0xc0, 0x96, 0xa3, 0x47, 0xea, 0x25, 0x55, 0xae, 0x86, 0x7b, 0x77, 0x8b, 0xb5,
0xc4, 0x3d, 0x03, 0x5b, 0xce, 0xc9, 0x46, 0xa0, 0xca, 0x1c, 0x6f, 0x04, 0xaa, 0x0d, 0xd7, 0x0e,
0x39, 0x56, 0x70, 0xdd, 0x06, 0x28, 0x3a, 0xc8, 0xed, 0x46, 0x9b, 0x0e, 0xf1, 0xc6, 0x16, 0x6f,
0xc7, 0xc7, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x4b, 0x8f, 0xf4, 0x22, 0x76, 0x0a, 0x00, 0x00,
}

View File

@ -26,22 +26,20 @@ message ListAccountsResponse {
}
message Token {
string token = 1;
string type = 2;
string access_token = 1;
string refresh_token = 2;
int64 created = 3;
int64 expiry = 4;
string subject = 5;
repeated string roles = 6;
map<string, string> metadata = 7;
string namespace = 8;
}
message Account {
string id = 1;
string secret = 2;
string type = 2;
repeated string roles = 3;
map<string, string> metadata = 4;
string namespace = 5;
string provider = 6;
string secret = 7;
}
message Resource{
@ -55,6 +53,9 @@ message GenerateRequest {
repeated string roles = 2;
map<string, string> metadata = 3;
string namespace = 4;
string secret = 5;
string type = 6;
string provider = 7;
}
message GenerateResponse {
@ -86,7 +87,8 @@ message InspectResponse {
message TokenRequest {
string id = 1;
string secret = 2;
int64 token_expiry = 3;
string refresh_token = 3;
int64 token_expiry = 4;
}
message TokenResponse {

View File

@ -77,7 +77,7 @@ func (s *svc) Init(opts ...auth.Option) {
tokenTimer := time.NewTicker(time.Minute)
go func() {
s.loadToken()
s.refreshToken()
for {
<-tokenTimer.C
@ -94,7 +94,7 @@ func (s *svc) Init(opts ...auth.Option) {
// all the services calling the auth service
// at the exact same time
time.Sleep(jitter.Do(time.Second * 5))
s.loadToken()
s.refreshToken()
}
}()
}
@ -112,8 +112,11 @@ func (s *svc) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, e
rsp, err := s.auth.Generate(context.TODO(), &pb.GenerateRequest{
Id: id,
Type: options.Type,
Secret: options.Secret,
Roles: options.Roles,
Metadata: options.Metadata,
Provider: options.Provider,
Namespace: options.Namespace,
})
if err != nil {
@ -191,23 +194,14 @@ func (s *svc) Verify(acc *auth.Account, res *auth.Resource) error {
// Inspect a token
func (s *svc) Inspect(token string) (*auth.Account, error) {
// try to decode JWT locally and fall back to srv if an error
// occurs, TODO: find a better way of determining if the token
// is a JWT, possibly update the interface to take an auth.Token
// and not just the string
// try to decode JWT locally and fall back to srv if an error occurs
if len(strings.Split(token, ".")) == 3 && s.jwt != nil {
if tok, err := s.jwt.Inspect(token); err == nil {
return &auth.Account{
ID: tok.Subject,
Roles: tok.Roles,
Metadata: tok.Metadata,
}, nil
if acc, err := s.jwt.Inspect(token); err == nil {
return acc, nil
}
}
rsp, err := s.auth.Inspect(context.TODO(), &pb.InspectRequest{
Token: token,
})
rsp, err := s.auth.Inspect(context.TODO(), &pb.InspectRequest{Token: token})
if err != nil {
return nil, err
}
@ -216,13 +210,14 @@ func (s *svc) Inspect(token string) (*auth.Account, error) {
}
// Token generation using an account ID and secret
func (s *svc) Token(id, secret string, opts ...auth.TokenOption) (*auth.Token, error) {
func (s *svc) Token(opts ...auth.TokenOption) (*auth.Token, error) {
options := auth.NewTokenOptions(opts...)
rsp, err := s.auth.Token(context.Background(), &pb.TokenRequest{
Id: id,
Secret: secret,
TokenExpiry: int64(options.TokenExpiry.Seconds()),
Id: options.ID,
Secret: options.Secret,
RefreshToken: options.RefreshToken,
TokenExpiry: int64(options.Expiry.Seconds()),
})
if err != nil {
return nil, err
@ -286,13 +281,22 @@ func (s *svc) loadRules() {
s.rules = rsp.Rules
}
// loadToken generates a new token for the service to use when making calls
func (s *svc) loadToken() {
rsp, err := s.auth.Token(context.TODO(), &pb.TokenRequest{
Id: s.Options().ID,
Secret: s.Options().Secret,
// refreshToken generates a new token for the service to use when making calls
func (s *svc) refreshToken() {
req := &pb.TokenRequest{
TokenExpiry: int64((time.Minute * 15).Seconds()),
})
}
if s.Options().Token == nil {
// we do not have a token, use the credentials to get one
req.Id = s.Options().ID
req.Secret = s.Options().Secret
} else {
// we have a token, refresh it
req.RefreshToken = s.Options().Token.RefreshToken
}
rsp, err := s.auth.Token(context.TODO(), req)
s.Lock()
defer s.Unlock()
@ -306,13 +310,10 @@ func (s *svc) loadToken() {
func serializeToken(t *pb.Token) *auth.Token {
return &auth.Token{
Token: t.Token,
Type: t.Type,
AccessToken: t.AccessToken,
RefreshToken: t.RefreshToken,
Created: time.Unix(t.Created, 0),
Expiry: time.Unix(t.Expiry, 0),
Subject: t.Subject,
Roles: t.Roles,
Metadata: t.Metadata,
}
}
@ -320,8 +321,9 @@ func serializeAccount(a *pb.Account) *auth.Account {
return &auth.Account{
ID: a.Id,
Roles: a.Roles,
Metadata: a.Metadata,
Namespace: a.Namespace,
Secret: a.Secret,
Metadata: a.Metadata,
Provider: a.Provider,
Namespace: a.Namespace,
}
}

View File

@ -35,30 +35,19 @@ func NewTokenProvider(opts ...token.Option) token.Provider {
}
// Generate a token for an account
func (b *Basic) Generate(subject string, opts ...token.GenerateOption) (*auth.Token, error) {
func (b *Basic) Generate(acc *auth.Account, opts ...token.GenerateOption) (*token.Token, error) {
options := token.NewGenerateOptions(opts...)
// construct the token
token := auth.Token{
Subject: subject,
Type: b.String(),
Token: uuid.New().String(),
Created: time.Now(),
Expiry: time.Now().Add(options.Expiry),
Metadata: options.Metadata,
Roles: options.Roles,
Namespace: options.Namespace,
}
// marshal the account to bytes
bytes, err := json.Marshal(token)
bytes, err := json.Marshal(acc)
if err != nil {
return nil, err
}
// write to the store
key := uuid.New().String()
err = b.store.Write(&store.Record{
Key: fmt.Sprintf("%v%v", StorePrefix, token.Token),
Key: fmt.Sprintf("%v%v", StorePrefix, key),
Value: bytes,
Expiry: options.Expiry,
})
@ -67,11 +56,15 @@ func (b *Basic) Generate(subject string, opts ...token.GenerateOption) (*auth.To
}
// return the token
return &token, nil
return &token.Token{
Token: key,
Created: time.Now(),
Expiry: time.Now().Add(options.Expiry),
}, nil
}
// Inspect a token
func (b *Basic) Inspect(t string) (*auth.Token, error) {
func (b *Basic) Inspect(t string) (*auth.Account, error) {
// lookup the token in the store
recs, err := b.store.Read(StorePrefix + t)
if err == store.ErrNotFound {
@ -82,18 +75,12 @@ func (b *Basic) Inspect(t string) (*auth.Token, error) {
bytes := recs[0].Value
// unmarshal the bytes
var tok *auth.Token
if err := json.Unmarshal(bytes, &tok); err != nil {
var acc *auth.Account
if err := json.Unmarshal(bytes, &acc); err != nil {
return nil, err
}
// ensure the token hasn't expired, the store should
// expire the token but we're checking again
if tok.Expiry.Unix() < time.Now().Unix() {
return nil, token.ErrInvalidToken
}
return tok, err
return acc, nil
}
// String returns basic

View File

@ -2,8 +2,8 @@ package basic
import (
"testing"
"time"
"github.com/micro/go-micro/v2/auth"
"github.com/micro/go-micro/v2/auth/token"
"github.com/micro/go-micro/v2/store/memory"
)
@ -12,7 +12,7 @@ func TestGenerate(t *testing.T) {
store := memory.NewStore()
b := NewTokenProvider(token.WithStore(store))
_, err := b.Generate("test")
_, err := b.Generate(&auth.Account{ID: "test"})
if err != nil {
t.Fatalf("Generate returned %v error, expected nil", err)
}
@ -35,12 +35,7 @@ func TestInspect(t *testing.T) {
roles := []string{"admin"}
subject := "test"
opts := []token.GenerateOption{
token.WithMetadata(md),
token.WithRoles(roles...),
}
tok, err := b.Generate(subject, opts...)
tok, err := b.Generate(&auth.Account{ID: subject, Roles: roles, Metadata: md})
if err != nil {
t.Fatalf("Generate returned %v error, expected nil", err)
}
@ -49,8 +44,8 @@ func TestInspect(t *testing.T) {
if err != nil {
t.Fatalf("Inspect returned %v error, expected nil", err)
}
if tok2.Subject != subject {
t.Errorf("Inspect returned %v as the token subject, expected %v", tok2.Subject, subject)
if tok2.ID != subject {
t.Errorf("Inspect returned %v as the token subject, expected %v", tok2.ID, subject)
}
if len(tok2.Roles) != len(roles) {
t.Errorf("Inspect returned %v roles, expected %v", len(tok2.Roles), len(roles))
@ -60,17 +55,6 @@ func TestInspect(t *testing.T) {
}
})
t.Run("Expired token", func(t *testing.T) {
tok, err := b.Generate("foo", token.WithExpiry(-10*time.Second))
if err != nil {
t.Fatalf("Generate returned %v error, expected nil", err)
}
if _, err = b.Inspect(tok.Token); err != token.ErrInvalidToken {
t.Fatalf("Inspect returned %v error, expected %v", err, token.ErrInvalidToken)
}
})
t.Run("Invalid token", func(t *testing.T) {
_, err := b.Inspect("Invalid token")
if err != token.ErrInvalidToken {

View File

@ -11,7 +11,9 @@ import (
// authClaims to be encoded in the JWT
type authClaims struct {
Type string `json:"type"`
Roles []string `json:"roles"`
Provider string `json:"provider"`
Metadata map[string]string `json:"metadata"`
Namespace string `json:"namespace"`
@ -31,7 +33,7 @@ func NewTokenProvider(opts ...token.Option) token.Provider {
}
// Generate a new JWT
func (j *JWT) Generate(subject string, opts ...token.GenerateOption) (*auth.Token, error) {
func (j *JWT) Generate(acc *auth.Account, opts ...token.GenerateOption) (*token.Token, error) {
// decode the private key
priv, err := base64.StdEncoding.DecodeString(j.opts.PrivateKey)
if err != nil {
@ -50,8 +52,8 @@ func (j *JWT) Generate(subject string, opts ...token.GenerateOption) (*auth.Toke
// generate the JWT
expiry := time.Now().Add(options.Expiry)
t := jwt.NewWithClaims(jwt.SigningMethodRS256, authClaims{
options.Roles, options.Metadata, options.Namespace, jwt.StandardClaims{
Subject: subject,
acc.Type, acc.Roles, acc.Provider, acc.Metadata, acc.Namespace, jwt.StandardClaims{
Subject: acc.ID,
ExpiresAt: expiry.Unix(),
},
})
@ -61,20 +63,15 @@ func (j *JWT) Generate(subject string, opts ...token.GenerateOption) (*auth.Toke
}
// return the token
return &auth.Token{
Subject: subject,
return &token.Token{
Token: tok,
Type: j.String(),
Created: time.Now(),
Expiry: expiry,
Roles: options.Roles,
Metadata: options.Metadata,
Namespace: options.Namespace,
Created: time.Now(),
}, nil
}
// Inspect a JWT
func (j *JWT) Inspect(t string) (*auth.Token, error) {
func (j *JWT) Inspect(t string) (*auth.Account, error) {
// decode the public key
pub, err := base64.StdEncoding.DecodeString(j.opts.PublicKey)
if err != nil {
@ -99,11 +96,12 @@ func (j *JWT) Inspect(t string) (*auth.Token, error) {
}
// return the token
return &auth.Token{
Token: t,
Subject: claims.Subject,
Metadata: claims.Metadata,
return &auth.Account{
ID: claims.Subject,
Type: claims.Type,
Roles: claims.Roles,
Provider: claims.Provider,
Metadata: claims.Metadata,
Namespace: claims.Namespace,
}, nil
}

View File

@ -5,6 +5,7 @@ import (
"testing"
"time"
"github.com/micro/go-micro/v2/auth"
"github.com/micro/go-micro/v2/auth/token"
)
@ -18,7 +19,7 @@ func TestGenerate(t *testing.T) {
token.WithPrivateKey(string(privKey)),
)
_, err = j.Generate("test")
_, err = j.Generate(&auth.Account{ID: "test"})
if err != nil {
t.Fatalf("Generate returned %v error, expected nil", err)
}
@ -44,12 +45,8 @@ func TestInspect(t *testing.T) {
roles := []string{"admin"}
subject := "test"
opts := []token.GenerateOption{
token.WithMetadata(md),
token.WithRoles(roles...),
}
tok, err := j.Generate(subject, opts...)
acc := &auth.Account{ID: subject, Roles: roles, Metadata: md}
tok, err := j.Generate(acc)
if err != nil {
t.Fatalf("Generate returned %v error, expected nil", err)
}
@ -58,8 +55,8 @@ func TestInspect(t *testing.T) {
if err != nil {
t.Fatalf("Inspect returned %v error, expected nil", err)
}
if tok2.Subject != subject {
t.Errorf("Inspect returned %v as the token subject, expected %v", tok2.Subject, subject)
if acc.ID != subject {
t.Errorf("Inspect returned %v as the token subject, expected %v", acc.ID, subject)
}
if len(tok2.Roles) != len(roles) {
t.Errorf("Inspect returned %v roles, expected %v", len(tok2.Roles), len(roles))
@ -70,7 +67,7 @@ func TestInspect(t *testing.T) {
})
t.Run("Expired token", func(t *testing.T) {
tok, err := j.Generate("foo", token.WithExpiry(-10*time.Second))
tok, err := j.Generate(&auth.Account{}, token.WithExpiry(-10*time.Second))
if err != nil {
t.Fatalf("Generate returned %v error, expected nil", err)
}

View File

@ -53,12 +53,6 @@ func NewOptions(opts ...Option) Options {
type GenerateOptions struct {
// Expiry for the token
Expiry time.Duration
// Metadata associated with the account
Metadata map[string]string
// Roles/scopes associated with the account
Roles []string
// Namespace the account belongs too
Namespace string
}
type GenerateOption func(o *GenerateOptions)
@ -70,27 +64,6 @@ func WithExpiry(d time.Duration) GenerateOption {
}
}
// WithMetadata for the token
func WithMetadata(md map[string]string) func(o *GenerateOptions) {
return func(o *GenerateOptions) {
o.Metadata = md
}
}
// WithRoles for the token
func WithRoles(rs ...string) func(o *GenerateOptions) {
return func(o *GenerateOptions) {
o.Roles = rs
}
}
// WithNamespace for the token
func WithNamespace(n string) func(o *GenerateOptions) {
return func(o *GenerateOptions) {
o.Namespace = n
}
}
// NewGenerateOptions from a slice of options
func NewGenerateOptions(opts ...GenerateOption) GenerateOptions {
var options GenerateOptions

View File

@ -2,6 +2,7 @@ package token
import (
"errors"
"time"
"github.com/micro/go-micro/v2/auth"
)
@ -17,7 +18,16 @@ var (
// Provider generates and inspects tokens
type Provider interface {
Generate(subject string, opts ...GenerateOption) (*auth.Token, error)
Inspect(token string) (*auth.Token, error)
Generate(account *auth.Account, opts ...GenerateOption) (*Token, error)
Inspect(token string) (*auth.Account, error)
String() string
}
type Token struct {
// The actual token
Token string `json:"token"`
// Time of token creation
Created time.Time `json:"created"`
// Time of token expiry
Expiry time.Time `json:"expiry"`
}

View File

@ -135,7 +135,7 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R
// was passed with the request, set the service token
var srvToken string
if g.opts.Auth != nil && g.opts.Auth.Options().Token != nil {
srvToken = g.opts.Auth.Options().Token.Token
srvToken = g.opts.Auth.Options().Token.AccessToken
}
if (opts.ServiceToken || len(header["authorization"]) == 0) && len(srvToken) > 0 {
header["authorization"] = auth.BearerScheme + srvToken

View File

@ -670,7 +670,6 @@ func (c *cmd) Before(ctx *cli.Context) error {
if len(ctx.String("auth_public_key")) > 0 {
authOpts = append(authOpts, auth.PublicKey(ctx.String("auth_public_key")))
}
if len(ctx.String("auth_private_key")) > 0 {
authOpts = append(authOpts, auth.PrivateKey(ctx.String("auth_private_key")))
}