Updated auth interface (#1384)
* Updated auth interface * Add Rule * Remove Rule * Return token from Renew * Renew => Refresh * Implement Tokens & Default Auth Implementation * Change default auth to noop * Change default auth to noop * Move token.Token to auth.Token * Remove Token from Account * Auth service implementation * Decode JWT locally * Cookie for secret * Move string to bottom of interface definition * Depricate auth_exclude * Update auth wrappers * Update go.sum Co-authored-by: Ben Toogood <ben@micro.mu>
This commit is contained in:
parent
9826ddbd64
commit
e0e77f3983
@ -43,44 +43,42 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
} else {
|
||||
// Get the token out the cookies if not provided in headers
|
||||
if c, err := req.Cookie("micro-token"); err == nil && c != nil {
|
||||
token = strings.TrimPrefix(c.Value, auth.CookieName+"=")
|
||||
token = strings.TrimPrefix(c.Value, auth.TokenCookieName+"=")
|
||||
req.Header.Set("Authorization", BearerScheme+token)
|
||||
}
|
||||
}
|
||||
|
||||
// Return if the user disabled auth on this endpoint
|
||||
excludes := h.auth.Options().Exclude
|
||||
excludes = append(excludes, DefaultExcludes...)
|
||||
|
||||
loginURL := h.auth.Options().LoginURL
|
||||
if len(loginURL) > 0 {
|
||||
excludes = append(excludes, loginURL)
|
||||
// Get the account using the token, fallback to a blank account
|
||||
// since some endpoints can be unauthenticated, so the lack of an
|
||||
// account doesn't necesserially mean a forbidden request
|
||||
acc, err := h.auth.Inspect(token)
|
||||
if err != nil {
|
||||
acc = &auth.Account{}
|
||||
}
|
||||
err = h.auth.Verify(acc, &auth.Resource{
|
||||
Type: "service",
|
||||
Name: "go.micro.web",
|
||||
Endpoint: req.URL.Path,
|
||||
})
|
||||
|
||||
for _, e := range excludes {
|
||||
// is a standard exclude, e.g. /rpc
|
||||
if e == req.URL.Path {
|
||||
// The account has the necessary permissions to access the
|
||||
// resource
|
||||
if err == nil {
|
||||
h.handler.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
// is a wildcard exclude, e.g. /services/*
|
||||
wildcard := strings.Replace(e, "*", "", 1)
|
||||
if strings.HasSuffix(e, "*") && strings.HasPrefix(req.URL.Path, wildcard) {
|
||||
h.handler.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If the token is valid, allow the request
|
||||
if _, err := h.auth.Verify(token); err == nil {
|
||||
h.handler.ServeHTTP(w, req)
|
||||
// The account is set, but they don't have enough permissions,
|
||||
// hence we 403.
|
||||
if len(acc.ID) > 0 {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
// If there is no auth login url set, 401
|
||||
loginURL := h.auth.Options().LoginURL
|
||||
if loginURL == "" {
|
||||
w.WriteHeader(401)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
|
89
auth/auth.go
89
auth/auth.go
@ -4,24 +4,44 @@ package auth
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNotFound is returned when a resouce cannot be found
|
||||
ErrNotFound = errors.New("not found")
|
||||
// ErrEncodingToken is returned when the service encounters an error during encoding
|
||||
ErrEncodingToken = errors.New("error encoding the token")
|
||||
// ErrInvalidToken is returned when the token provided is not valid
|
||||
ErrInvalidToken = errors.New("invalid token provided")
|
||||
// ErrInvalidRole is returned when the role provided was invalid
|
||||
ErrInvalidRole = errors.New("invalid role")
|
||||
// ErrForbidden is returned when a user does not have the necessary roles to access a resource
|
||||
ErrForbidden = errors.New("resource forbidden")
|
||||
)
|
||||
|
||||
// Auth providers authentication and authorization
|
||||
type Auth interface {
|
||||
// Init the auth package
|
||||
Init(opts ...Option) error
|
||||
// Options returns the options set
|
||||
// Init the auth
|
||||
Init(opts ...Option)
|
||||
// Options set for auth
|
||||
Options() Options
|
||||
// Generate a new auth Account
|
||||
// Generate a new account
|
||||
Generate(id string, opts ...GenerateOption) (*Account, error)
|
||||
// Revoke an authorization Account
|
||||
Revoke(token string) error
|
||||
// Verify an account token
|
||||
Verify(token string) (*Account, error)
|
||||
// String returns the implementation
|
||||
// Grant access to a resource
|
||||
Grant(role string, res *Resource) error
|
||||
// Revoke access to a resource
|
||||
Revoke(role string, res *Resource) error
|
||||
// Verify an account has access to a resource
|
||||
Verify(acc *Account, res *Resource) error
|
||||
// Inspect a token
|
||||
Inspect(token string) (*Account, error)
|
||||
// Refresh an account using a secret
|
||||
Refresh(secret string, opts ...RefreshOption) (*Token, error)
|
||||
// String returns the name of the implementation
|
||||
String() string
|
||||
}
|
||||
|
||||
@ -31,40 +51,47 @@ type Resource struct {
|
||||
Name string
|
||||
// Type of resource, e.g.
|
||||
Type string
|
||||
}
|
||||
|
||||
// Role an account has
|
||||
type Role struct {
|
||||
// Name of the role
|
||||
Name string
|
||||
// The resource it has access
|
||||
// TODO: potentially remove
|
||||
Resource *Resource
|
||||
// Endpoint resource e.g NotesService.Create
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
// Account provided by an auth provider
|
||||
type Account struct {
|
||||
// ID of the account (UUIDV4, email or username)
|
||||
Id string `json:"id"`
|
||||
// Token used to authenticate
|
||||
Token string `json:"token"`
|
||||
// Time of Account creation
|
||||
Created time.Time `json:"created"`
|
||||
// Time of Account expiry
|
||||
Expiry time.Time `json:"expiry"`
|
||||
ID string `json:"id"`
|
||||
// Secret used to renew the account
|
||||
Secret *Token `json:"secret"`
|
||||
// Roles associated with the Account
|
||||
Roles []*Role `json:"roles"`
|
||||
Roles []string `json:"roles"`
|
||||
// Any other associated metadata
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
}
|
||||
|
||||
// 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"`
|
||||
// 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"`
|
||||
}
|
||||
|
||||
const (
|
||||
// MetadataKey is the key used when storing the account
|
||||
// in metadata
|
||||
// MetadataKey is the key used when storing the account in metadata
|
||||
MetadataKey = "auth-account"
|
||||
// CookieName is the name of the cookie which stores the
|
||||
// auth token
|
||||
CookieName = "micro-token"
|
||||
// TokenCookieName is the name of the cookie which stores the auth token
|
||||
TokenCookieName = "micro-token"
|
||||
// SecretCookieName is the name of the cookie which stores the auth secret
|
||||
SecretCookieName = "micro-secret"
|
||||
)
|
||||
|
||||
// AccountFromContext gets the account from the context, which
|
||||
|
134
auth/default.go
134
auth/default.go
@ -1,122 +1,70 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"sync"
|
||||
"time"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultAuth = NewAuth()
|
||||
)
|
||||
|
||||
func genAccount(id string) *Account {
|
||||
// return a pseudo account
|
||||
return &Account{
|
||||
Id: id,
|
||||
Token: base32.StdEncoding.EncodeToString([]byte(id)),
|
||||
Created: time.Now(),
|
||||
Expiry: time.Now().Add(time.Hour * 24),
|
||||
Metadata: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// NewAuth returns a new default registry which is memory
|
||||
func NewAuth(opts ...Option) Auth {
|
||||
var options Options
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
return &noop{}
|
||||
}
|
||||
|
||||
return &memory{
|
||||
accounts: make(map[string]*Account),
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: replace with https://github.com/nats-io/nkeys
|
||||
// We'll then register public key in registry to use
|
||||
type memory struct {
|
||||
type noop struct {
|
||||
opts Options
|
||||
// accounts
|
||||
sync.RWMutex
|
||||
accounts map[string]*Account
|
||||
}
|
||||
|
||||
func (n *memory) Init(opts ...Option) error {
|
||||
// String returns the name of the implementation
|
||||
func (n *noop) String() string {
|
||||
return "noop"
|
||||
}
|
||||
|
||||
// Init the auth
|
||||
func (n *noop) Init(opts ...Option) {
|
||||
for _, o := range opts {
|
||||
o(&n.opts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *memory) Options() Options {
|
||||
// Options set for auth
|
||||
func (n *noop) Options() Options {
|
||||
return n.opts
|
||||
}
|
||||
|
||||
func (n *memory) Generate(id string, opts ...GenerateOption) (*Account, error) {
|
||||
var options GenerateOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
// Generate a new account
|
||||
func (n *noop) Generate(id string, opts ...GenerateOption) (*Account, error) {
|
||||
options := NewGenerateOptions(opts...)
|
||||
|
||||
// return a pseudo account
|
||||
acc := genAccount(id)
|
||||
|
||||
// set opts
|
||||
if len(options.Roles) > 0 {
|
||||
acc.Roles = options.Roles
|
||||
}
|
||||
if options.Metadata != nil {
|
||||
acc.Metadata = options.Metadata
|
||||
}
|
||||
|
||||
// TODO: don't overwrite
|
||||
n.Lock()
|
||||
// maybe save by account id?
|
||||
n.accounts[acc.Token] = acc
|
||||
n.Unlock()
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
func (n *memory) Revoke(token string) error {
|
||||
n.Lock()
|
||||
delete(n.accounts, token)
|
||||
n.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *memory) Verify(token string) (*Account, error) {
|
||||
n.RLock()
|
||||
defer n.RUnlock()
|
||||
|
||||
if len(token) == 0 {
|
||||
// pseudo account?
|
||||
return genAccount(""), nil
|
||||
}
|
||||
|
||||
// try get the local account if it exists
|
||||
if acc, ok := n.accounts[token]; ok {
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// decode the token otherwise
|
||||
b, err := base32.StdEncoding.DecodeString(token)
|
||||
if err != nil {
|
||||
return genAccount(""), nil
|
||||
}
|
||||
|
||||
// return a pseudo account based on token/id
|
||||
return &Account{
|
||||
Id: string(b),
|
||||
Token: token,
|
||||
Created: time.Now(),
|
||||
Expiry: time.Now().Add(time.Hour * 24),
|
||||
Metadata: make(map[string]string),
|
||||
ID: id,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *memory) String() string {
|
||||
return "memory"
|
||||
// Grant access to a resource
|
||||
func (n *noop) Grant(role string, res *Resource) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Revoke access to a resource
|
||||
func (n *noop) Revoke(role string, res *Resource) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify an account has access to a resource
|
||||
func (n *noop) Verify(acc *Account, res *Resource) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Inspect a token
|
||||
func (n *noop) Inspect(token string) (*Account, error) {
|
||||
return &Account{ID: uuid.New().String()}, nil
|
||||
}
|
||||
|
||||
// Refresh an account using a secret
|
||||
func (n *noop) Refresh(secret string, opts ...RefreshOption) (*Token, error) {
|
||||
return &Token{}, nil
|
||||
}
|
||||
|
133
auth/jwt/jwt.go
133
auth/jwt/jwt.go
@ -1,133 +0,0 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidPrivateKey is returned when the service provided an invalid private key
|
||||
ErrInvalidPrivateKey = errors.New("An invalid private key was provided")
|
||||
|
||||
// ErrEncodingToken is returned when the service encounters an error during encoding
|
||||
ErrEncodingToken = errors.New("An error occured while encoding the JWT")
|
||||
|
||||
// ErrInvalidToken is returned when the token provided is not valid
|
||||
ErrInvalidToken = errors.New("An invalid token was provided")
|
||||
|
||||
// ErrMissingToken is returned when no token is provided
|
||||
ErrMissingToken = errors.New("A valid JWT is required")
|
||||
)
|
||||
|
||||
// NewAuth returns a new instance of the Auth service
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
svc := new(svc)
|
||||
svc.Init(opts...)
|
||||
return svc
|
||||
}
|
||||
|
||||
// svc is the JWT implementation of the Auth interface
|
||||
type svc struct {
|
||||
options auth.Options
|
||||
}
|
||||
|
||||
func (s *svc) String() string {
|
||||
return "jwt"
|
||||
}
|
||||
|
||||
func (s *svc) Options() auth.Options {
|
||||
return s.options
|
||||
}
|
||||
|
||||
func (s *svc) Init(opts ...auth.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&s.options)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthClaims to be encoded in the JWT
|
||||
type AuthClaims struct {
|
||||
Roles []*auth.Role `json:"roles"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
// Generate a new JWT
|
||||
func (s *svc) Generate(id string, ops ...auth.GenerateOption) (*auth.Account, error) {
|
||||
// decode the private key
|
||||
priv, err := base64.StdEncoding.DecodeString(s.options.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := jwt.ParseRSAPrivateKeyFromPEM(priv)
|
||||
if err != nil {
|
||||
return nil, ErrEncodingToken
|
||||
}
|
||||
|
||||
options := auth.NewGenerateOptions(ops...)
|
||||
account := jwt.NewWithClaims(jwt.SigningMethodRS256, AuthClaims{
|
||||
options.Roles, options.Metadata, jwt.StandardClaims{
|
||||
Subject: id,
|
||||
ExpiresAt: options.Expiry.Unix(),
|
||||
},
|
||||
})
|
||||
|
||||
token, err := account.SignedString(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &auth.Account{
|
||||
Id: id,
|
||||
Token: token,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Revoke an authorization account
|
||||
func (s *svc) Revoke(token string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify a JWT
|
||||
func (s *svc) Verify(token string) (*auth.Account, error) {
|
||||
if token == "" {
|
||||
return nil, ErrMissingToken
|
||||
}
|
||||
|
||||
// decode the public key
|
||||
pub, err := base64.StdEncoding.DecodeString(s.options.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := jwt.ParseWithClaims(token, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwt.ParseRSAPublicKeyFromPEM(pub)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !res.Valid {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
claims, ok := res.Claims.(*AuthClaims)
|
||||
if !ok {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
return &auth.Account{
|
||||
Id: claims.Subject,
|
||||
Metadata: claims.Metadata,
|
||||
Roles: claims.Roles,
|
||||
}, nil
|
||||
}
|
@ -4,6 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth/provider"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
@ -13,20 +14,20 @@ type Options struct {
|
||||
PublicKey string
|
||||
// Private key base64 encoded
|
||||
PrivateKey string
|
||||
// Endpoints to exclude
|
||||
Exclude []string
|
||||
// Provider is an auth provider
|
||||
Provider provider.Provider
|
||||
// LoginURL is the relative url path where a user can login
|
||||
LoginURL string
|
||||
// Store to back auth
|
||||
Store store.Store
|
||||
}
|
||||
|
||||
type Option func(o *Options)
|
||||
|
||||
// Exclude ecludes a set of endpoints from authorization
|
||||
func Exclude(e ...string) Option {
|
||||
// Store to back auth
|
||||
func Store(s store.Store) Option {
|
||||
return func(o *Options) {
|
||||
o.Exclude = e
|
||||
o.Store = s
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,8 +45,8 @@ func PrivateKey(key string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// Token sets an auth token
|
||||
func Token(t string) Option {
|
||||
// ServiceToken sets an auth token
|
||||
func ServiceToken(t string) Option {
|
||||
return func(o *Options) {
|
||||
o.Token = t
|
||||
}
|
||||
@ -69,31 +70,31 @@ type GenerateOptions struct {
|
||||
// Metadata associated with the account
|
||||
Metadata map[string]string
|
||||
// Roles/scopes associated with the account
|
||||
Roles []*Role
|
||||
//Expiry of the token
|
||||
Expiry time.Time
|
||||
Roles []string
|
||||
// SecretExpiry is the time the secret should live for
|
||||
SecretExpiry time.Duration
|
||||
}
|
||||
|
||||
type GenerateOption func(o *GenerateOptions)
|
||||
|
||||
// Metadata for the generated account
|
||||
func Metadata(md map[string]string) func(o *GenerateOptions) {
|
||||
// WithMetadata for the generated account
|
||||
func WithMetadata(md map[string]string) GenerateOption {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Metadata = md
|
||||
}
|
||||
}
|
||||
|
||||
// Roles for the generated account
|
||||
func Roles(rs []*Role) func(o *GenerateOptions) {
|
||||
// WithRoles for the generated account
|
||||
func WithRoles(rs []string) GenerateOption {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Roles = rs
|
||||
}
|
||||
}
|
||||
|
||||
// Expiry for the generated account's token expires
|
||||
func Expiry(ex time.Time) func(o *GenerateOptions) {
|
||||
// WithSecretExpiry for the generated account's secret expires
|
||||
func WithSecretExpiry(ex time.Duration) GenerateOption {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Expiry = ex
|
||||
o.SecretExpiry = ex
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,9 +104,40 @@ func NewGenerateOptions(opts ...GenerateOption) GenerateOptions {
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
//set defualt expiry of token
|
||||
if options.Expiry.IsZero() {
|
||||
options.Expiry = time.Now().Add(time.Hour * 24)
|
||||
|
||||
// set defualt expiry of secret
|
||||
if options.SecretExpiry == 0 {
|
||||
options.SecretExpiry = time.Hour * 24 * 7
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
type RefreshOptions struct {
|
||||
// TokenExpiry is the time the token should live for
|
||||
TokenExpiry time.Duration
|
||||
}
|
||||
|
||||
type RefreshOption func(o *RefreshOptions)
|
||||
|
||||
// WithTokenExpiry for the token
|
||||
func WithTokenExpiry(ex time.Duration) RefreshOption {
|
||||
return func(o *RefreshOptions) {
|
||||
o.TokenExpiry = ex
|
||||
}
|
||||
}
|
||||
|
||||
// NewRefreshOptions from a slice of options
|
||||
func NewRefreshOptions(opts ...RefreshOption) RefreshOptions {
|
||||
var options RefreshOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
// set defualt expiry of token
|
||||
if options.TokenExpiry == 0 {
|
||||
options.TokenExpiry = time.Minute
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: micro/go-micro/auth/service/proto/auth.proto
|
||||
// source: auth/service/proto/auth.proto
|
||||
|
||||
package go_micro_auth
|
||||
|
||||
@ -20,13 +20,98 @@ var _ = math.Inf
|
||||
// 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"`
|
||||
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"`
|
||||
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"`
|
||||
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"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Token) Reset() { *m = Token{} }
|
||||
func (m *Token) String() string { return proto.CompactTextString(m) }
|
||||
func (*Token) ProtoMessage() {}
|
||||
func (*Token) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{0}
|
||||
}
|
||||
|
||||
func (m *Token) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Token.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Token) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Token.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Token) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Token.Merge(m, src)
|
||||
}
|
||||
func (m *Token) XXX_Size() int {
|
||||
return xxx_messageInfo_Token.Size(m)
|
||||
}
|
||||
func (m *Token) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Token.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Token proto.InternalMessageInfo
|
||||
|
||||
func (m *Token) GetToken() string {
|
||||
if m != nil {
|
||||
return m.Token
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Token) GetType() string {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Token) GetCreated() int64 {
|
||||
if m != nil {
|
||||
return m.Created
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Token) GetExpiry() int64 {
|
||||
if m != nil {
|
||||
return m.Expiry
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Secret *Token `protobuf:"bytes,2,opt,name=secret,proto3" json:"secret,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"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -36,7 +121,7 @@ func (m *Account) Reset() { *m = Account{} }
|
||||
func (m *Account) String() string { return proto.CompactTextString(m) }
|
||||
func (*Account) ProtoMessage() {}
|
||||
func (*Account) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{0}
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{1}
|
||||
}
|
||||
|
||||
func (m *Account) XXX_Unmarshal(b []byte) error {
|
||||
@ -64,28 +149,14 @@ func (m *Account) GetId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Account) GetToken() string {
|
||||
func (m *Account) GetSecret() *Token {
|
||||
if m != nil {
|
||||
return m.Token
|
||||
return m.Secret
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
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 {
|
||||
func (m *Account) GetRoles() []string {
|
||||
if m != nil {
|
||||
return m.Roles
|
||||
}
|
||||
@ -99,56 +170,10 @@ func (m *Account) GetMetadata() map[string]string {
|
||||
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_de609d4872dacc78, []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"`
|
||||
Endpoint string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -158,7 +183,7 @@ func (m *Resource) Reset() { *m = Resource{} }
|
||||
func (m *Resource) String() string { return proto.CompactTextString(m) }
|
||||
func (*Resource) ProtoMessage() {}
|
||||
func (*Resource) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{2}
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{2}
|
||||
}
|
||||
|
||||
func (m *Resource) XXX_Unmarshal(b []byte) error {
|
||||
@ -193,8 +218,18 @@ func (m *Resource) GetType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Resource) GetEndpoint() string {
|
||||
if m != nil {
|
||||
return m.Endpoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GenerateRequest struct {
|
||||
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
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"`
|
||||
SecretExpiry int64 `protobuf:"varint,4,opt,name=secret_expiry,json=secretExpiry,proto3" json:"secret_expiry,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -204,7 +239,7 @@ func (m *GenerateRequest) Reset() { *m = GenerateRequest{} }
|
||||
func (m *GenerateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenerateRequest) ProtoMessage() {}
|
||||
func (*GenerateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{3}
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{3}
|
||||
}
|
||||
|
||||
func (m *GenerateRequest) XXX_Unmarshal(b []byte) error {
|
||||
@ -225,13 +260,34 @@ func (m *GenerateRequest) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_GenerateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *GenerateRequest) GetAccount() *Account {
|
||||
func (m *GenerateRequest) GetId() string {
|
||||
if m != nil {
|
||||
return m.Account
|
||||
return m.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GenerateRequest) GetRoles() []string {
|
||||
if m != nil {
|
||||
return m.Roles
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GenerateRequest) GetMetadata() map[string]string {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GenerateRequest) GetSecretExpiry() int64 {
|
||||
if m != nil {
|
||||
return m.SecretExpiry
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GenerateResponse struct {
|
||||
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
@ -243,7 +299,7 @@ func (m *GenerateResponse) Reset() { *m = GenerateResponse{} }
|
||||
func (m *GenerateResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenerateResponse) ProtoMessage() {}
|
||||
func (*GenerateResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{4}
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{4}
|
||||
}
|
||||
|
||||
func (m *GenerateResponse) XXX_Unmarshal(b []byte) error {
|
||||
@ -271,8 +327,87 @@ func (m *GenerateResponse) GetAccount() *Account {
|
||||
return nil
|
||||
}
|
||||
|
||||
type GrantRequest struct {
|
||||
Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,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 *GrantRequest) Reset() { *m = GrantRequest{} }
|
||||
func (m *GrantRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GrantRequest) ProtoMessage() {}
|
||||
func (*GrantRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{5}
|
||||
}
|
||||
|
||||
func (m *GrantRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GrantRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GrantRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GrantRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GrantRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GrantRequest.Merge(m, src)
|
||||
}
|
||||
func (m *GrantRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_GrantRequest.Size(m)
|
||||
}
|
||||
func (m *GrantRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GrantRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GrantRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *GrantRequest) GetRole() string {
|
||||
if m != nil {
|
||||
return m.Role
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GrantRequest) GetResource() *Resource {
|
||||
if m != nil {
|
||||
return m.Resource
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GrantResponse struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GrantResponse) Reset() { *m = GrantResponse{} }
|
||||
func (m *GrantResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GrantResponse) ProtoMessage() {}
|
||||
func (*GrantResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{6}
|
||||
}
|
||||
|
||||
func (m *GrantResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GrantResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GrantResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GrantResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GrantResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GrantResponse.Merge(m, src)
|
||||
}
|
||||
func (m *GrantResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_GrantResponse.Size(m)
|
||||
}
|
||||
func (m *GrantResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GrantResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GrantResponse proto.InternalMessageInfo
|
||||
|
||||
type VerifyRequest struct {
|
||||
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,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:"-"`
|
||||
@ -282,7 +417,7 @@ func (m *VerifyRequest) Reset() { *m = VerifyRequest{} }
|
||||
func (m *VerifyRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*VerifyRequest) ProtoMessage() {}
|
||||
func (*VerifyRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{5}
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{7}
|
||||
}
|
||||
|
||||
func (m *VerifyRequest) XXX_Unmarshal(b []byte) error {
|
||||
@ -303,15 +438,21 @@ func (m *VerifyRequest) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_VerifyRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *VerifyRequest) GetToken() string {
|
||||
func (m *VerifyRequest) GetAccount() *Account {
|
||||
if m != nil {
|
||||
return m.Token
|
||||
return m.Account
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *VerifyRequest) GetResource() *Resource {
|
||||
if m != nil {
|
||||
return m.Resource
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type VerifyResponse struct {
|
||||
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@ -321,7 +462,7 @@ func (m *VerifyResponse) Reset() { *m = VerifyResponse{} }
|
||||
func (m *VerifyResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*VerifyResponse) ProtoMessage() {}
|
||||
func (*VerifyResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{6}
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{8}
|
||||
}
|
||||
|
||||
func (m *VerifyResponse) XXX_Unmarshal(b []byte) error {
|
||||
@ -342,15 +483,9 @@ func (m *VerifyResponse) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_VerifyResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *VerifyResponse) 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"`
|
||||
Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,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:"-"`
|
||||
@ -360,7 +495,7 @@ func (m *RevokeRequest) Reset() { *m = RevokeRequest{} }
|
||||
func (m *RevokeRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RevokeRequest) ProtoMessage() {}
|
||||
func (*RevokeRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{7}
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{9}
|
||||
}
|
||||
|
||||
func (m *RevokeRequest) XXX_Unmarshal(b []byte) error {
|
||||
@ -381,13 +516,20 @@ func (m *RevokeRequest) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_RevokeRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *RevokeRequest) GetToken() string {
|
||||
func (m *RevokeRequest) GetRole() string {
|
||||
if m != nil {
|
||||
return m.Token
|
||||
return m.Role
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RevokeRequest) GetResource() *Resource {
|
||||
if m != nil {
|
||||
return m.Resource
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RevokeResponse struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
@ -398,7 +540,7 @@ func (m *RevokeResponse) Reset() { *m = RevokeResponse{} }
|
||||
func (m *RevokeResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*RevokeResponse) ProtoMessage() {}
|
||||
func (*RevokeResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{8}
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{10}
|
||||
}
|
||||
|
||||
func (m *RevokeResponse) XXX_Unmarshal(b []byte) error {
|
||||
@ -419,50 +561,235 @@ func (m *RevokeResponse) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_RevokeResponse proto.InternalMessageInfo
|
||||
|
||||
type InspectRequest 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 *InspectRequest) Reset() { *m = InspectRequest{} }
|
||||
func (m *InspectRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*InspectRequest) ProtoMessage() {}
|
||||
func (*InspectRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{11}
|
||||
}
|
||||
|
||||
func (m *InspectRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_InspectRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *InspectRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_InspectRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *InspectRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_InspectRequest.Merge(m, src)
|
||||
}
|
||||
func (m *InspectRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_InspectRequest.Size(m)
|
||||
}
|
||||
func (m *InspectRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_InspectRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_InspectRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *InspectRequest) GetToken() string {
|
||||
if m != nil {
|
||||
return m.Token
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type InspectResponse 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 *InspectResponse) Reset() { *m = InspectResponse{} }
|
||||
func (m *InspectResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*InspectResponse) ProtoMessage() {}
|
||||
func (*InspectResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{12}
|
||||
}
|
||||
|
||||
func (m *InspectResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_InspectResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *InspectResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_InspectResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *InspectResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_InspectResponse.Merge(m, src)
|
||||
}
|
||||
func (m *InspectResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_InspectResponse.Size(m)
|
||||
}
|
||||
func (m *InspectResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_InspectResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_InspectResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *InspectResponse) GetAccount() *Account {
|
||||
if m != nil {
|
||||
return m.Account
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RefreshRequest struct {
|
||||
Secret string `protobuf:"bytes,1,opt,name=secret,proto3" json:"secret,omitempty"`
|
||||
TokenExpiry int64 `protobuf:"varint,2,opt,name=token_expiry,json=tokenExpiry,proto3" json:"token_expiry,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RefreshRequest) Reset() { *m = RefreshRequest{} }
|
||||
func (m *RefreshRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RefreshRequest) ProtoMessage() {}
|
||||
func (*RefreshRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{13}
|
||||
}
|
||||
|
||||
func (m *RefreshRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RefreshRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *RefreshRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_RefreshRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *RefreshRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RefreshRequest.Merge(m, src)
|
||||
}
|
||||
func (m *RefreshRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_RefreshRequest.Size(m)
|
||||
}
|
||||
func (m *RefreshRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RefreshRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RefreshRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *RefreshRequest) GetSecret() string {
|
||||
if m != nil {
|
||||
return m.Secret
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RefreshRequest) GetTokenExpiry() int64 {
|
||||
if m != nil {
|
||||
return m.TokenExpiry
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type RefreshResponse struct {
|
||||
Token *Token `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RefreshResponse) Reset() { *m = RefreshResponse{} }
|
||||
func (m *RefreshResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*RefreshResponse) ProtoMessage() {}
|
||||
func (*RefreshResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_21300bfacc51fc2a, []int{14}
|
||||
}
|
||||
|
||||
func (m *RefreshResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RefreshResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *RefreshResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_RefreshResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *RefreshResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RefreshResponse.Merge(m, src)
|
||||
}
|
||||
func (m *RefreshResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_RefreshResponse.Size(m)
|
||||
}
|
||||
func (m *RefreshResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RefreshResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RefreshResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *RefreshResponse) GetToken() *Token {
|
||||
if m != nil {
|
||||
return m.Token
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
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((*Role)(nil), "go.micro.auth.Role")
|
||||
proto.RegisterType((*Resource)(nil), "go.micro.auth.Resource")
|
||||
proto.RegisterType((*GenerateRequest)(nil), "go.micro.auth.GenerateRequest")
|
||||
proto.RegisterMapType((map[string]string)(nil), "go.micro.auth.GenerateRequest.MetadataEntry")
|
||||
proto.RegisterType((*GenerateResponse)(nil), "go.micro.auth.GenerateResponse")
|
||||
proto.RegisterType((*GrantRequest)(nil), "go.micro.auth.GrantRequest")
|
||||
proto.RegisterType((*GrantResponse)(nil), "go.micro.auth.GrantResponse")
|
||||
proto.RegisterType((*VerifyRequest)(nil), "go.micro.auth.VerifyRequest")
|
||||
proto.RegisterType((*VerifyResponse)(nil), "go.micro.auth.VerifyResponse")
|
||||
proto.RegisterType((*RevokeRequest)(nil), "go.micro.auth.RevokeRequest")
|
||||
proto.RegisterType((*RevokeResponse)(nil), "go.micro.auth.RevokeResponse")
|
||||
proto.RegisterType((*InspectRequest)(nil), "go.micro.auth.InspectRequest")
|
||||
proto.RegisterType((*InspectResponse)(nil), "go.micro.auth.InspectResponse")
|
||||
proto.RegisterType((*RefreshRequest)(nil), "go.micro.auth.RefreshRequest")
|
||||
proto.RegisterType((*RefreshResponse)(nil), "go.micro.auth.RefreshResponse")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("micro/go-micro/auth/service/proto/auth.proto", fileDescriptor_de609d4872dacc78)
|
||||
}
|
||||
func init() { proto.RegisterFile("auth/service/proto/auth.proto", fileDescriptor_21300bfacc51fc2a) }
|
||||
|
||||
var fileDescriptor_de609d4872dacc78 = []byte{
|
||||
// 432 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x4b, 0x6f, 0xd3, 0x40,
|
||||
0x10, 0xae, 0x1d, 0xe7, 0xc1, 0x44, 0x09, 0xd1, 0x80, 0x8a, 0x15, 0xf1, 0x88, 0x56, 0x20, 0x05,
|
||||
0x09, 0x1c, 0xe4, 0x5e, 0x10, 0x5c, 0x28, 0x0f, 0xf5, 0x54, 0x21, 0xed, 0x81, 0xfb, 0xe2, 0x0c,
|
||||
0xad, 0x95, 0xc4, 0x6b, 0xd6, 0xeb, 0x08, 0xff, 0x06, 0x7e, 0x28, 0x7f, 0x03, 0x79, 0xd7, 0x1b,
|
||||
0x6a, 0xb7, 0xe5, 0x00, 0xb7, 0x79, 0x7c, 0xf3, 0xcd, 0xf7, 0x8d, 0x76, 0xe1, 0xc5, 0x2e, 0x4d,
|
||||
0x94, 0x5c, 0x5d, 0xc8, 0x97, 0x36, 0x10, 0xa5, 0xbe, 0x5c, 0x15, 0xa4, 0xf6, 0x69, 0x42, 0xab,
|
||||
0x5c, 0x49, 0x6d, 0x4b, 0x91, 0x09, 0x71, 0x72, 0x21, 0x23, 0x83, 0x8b, 0xea, 0x22, 0xfb, 0xe9,
|
||||
0xc3, 0xf0, 0x34, 0x49, 0x64, 0x99, 0x69, 0x9c, 0x82, 0x9f, 0xae, 0x43, 0x6f, 0xe1, 0x2d, 0xef,
|
||||
0x70, 0x3f, 0x5d, 0xe3, 0x7d, 0xe8, 0x6b, 0xb9, 0xa1, 0x2c, 0xf4, 0x4d, 0xc9, 0x26, 0x18, 0xc2,
|
||||
0x30, 0x51, 0x24, 0x34, 0xad, 0xc3, 0xde, 0xc2, 0x5b, 0xf6, 0xb8, 0x4b, 0xf1, 0x18, 0x06, 0xf4,
|
||||
0x23, 0x4f, 0x55, 0x15, 0x06, 0xa6, 0xd1, 0x64, 0xf8, 0x1c, 0xfa, 0x4a, 0x6e, 0xa9, 0x08, 0xfb,
|
||||
0x8b, 0xde, 0x72, 0x1c, 0xdf, 0x8b, 0x5a, 0x12, 0x22, 0x2e, 0xb7, 0xc4, 0x2d, 0x02, 0xdf, 0xc1,
|
||||
0x68, 0x47, 0x5a, 0xac, 0x85, 0x16, 0xe1, 0xc0, 0xa0, 0x9f, 0x76, 0xd0, 0x8d, 0xd8, 0xe8, 0xbc,
|
||||
0x81, 0x7d, 0xca, 0xb4, 0xaa, 0xf8, 0x61, 0x6a, 0xfe, 0x16, 0x26, 0xad, 0x16, 0xce, 0xa0, 0xb7,
|
||||
0xa1, 0xaa, 0xb1, 0x55, 0x87, 0xb5, 0xaf, 0xbd, 0xd8, 0x96, 0xe4, 0x7c, 0x99, 0xe4, 0x8d, 0xff,
|
||||
0xda, 0x63, 0x9f, 0x21, 0xa8, 0xd5, 0x20, 0x42, 0x90, 0x89, 0x1d, 0x35, 0x43, 0x26, 0xc6, 0x13,
|
||||
0x18, 0x29, 0x2a, 0x64, 0xa9, 0x12, 0x3b, 0x38, 0x8e, 0x1f, 0x74, 0x8d, 0x34, 0x6d, 0x7e, 0x00,
|
||||
0xb2, 0x18, 0x46, 0xae, 0x7a, 0x23, 0x29, 0x42, 0xa0, 0xab, 0xdc, 0x29, 0x31, 0x31, 0xfb, 0x00,
|
||||
0x77, 0xcf, 0x28, 0x23, 0x25, 0x34, 0x71, 0xfa, 0x5e, 0x52, 0xa1, 0xf1, 0x15, 0x0c, 0x85, 0xf5,
|
||||
0x6d, 0xa6, 0xc7, 0xf1, 0xf1, 0xcd, 0x57, 0xe1, 0x0e, 0xc6, 0x3e, 0xc2, 0xec, 0x0f, 0x49, 0x91,
|
||||
0xcb, 0xac, 0xa0, 0x7f, 0x60, 0x79, 0x06, 0x93, 0x2f, 0xa4, 0xd2, 0x6f, 0x95, 0x13, 0x72, 0x78,
|
||||
0x12, 0xde, 0x95, 0x27, 0xc1, 0xde, 0xc3, 0xd4, 0xc1, 0xfe, 0x67, 0x15, 0xa7, 0xbd, 0xdc, 0xd0,
|
||||
0xdf, 0x57, 0xcd, 0x60, 0xea, 0x60, 0x76, 0x55, 0xfc, 0xcb, 0x83, 0xe0, 0xb4, 0xd4, 0x97, 0x78,
|
||||
0x0e, 0x23, 0x67, 0x19, 0x1f, 0x77, 0xd6, 0x75, 0x0e, 0x3a, 0x7f, 0x72, 0x6b, 0xdf, 0xb2, 0xb2,
|
||||
0x23, 0x3c, 0x83, 0x81, 0x35, 0x85, 0x0f, 0x3b, 0xe0, 0xd6, 0x49, 0xe6, 0x8f, 0x6e, 0xe9, 0x5e,
|
||||
0x25, 0xb2, 0x92, 0xaf, 0x11, 0xb5, 0x0c, 0x5f, 0x23, 0x6a, 0xfb, 0x64, 0x47, 0x5f, 0x07, 0xe6,
|
||||
0x07, 0x9f, 0xfc, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x34, 0xce, 0x17, 0xf1, 0x03, 0x00, 0x00,
|
||||
var fileDescriptor_21300bfacc51fc2a = []byte{
|
||||
// 663 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xdd, 0x6e, 0xd3, 0x4c,
|
||||
0x10, 0xad, 0xed, 0xfc, 0x75, 0x52, 0x27, 0xd1, 0xaa, 0xea, 0x67, 0xf9, 0xa3, 0x25, 0x18, 0x84,
|
||||
0x2a, 0x54, 0xb9, 0x28, 0xbd, 0x41, 0x20, 0x10, 0x15, 0xad, 0xca, 0x8f, 0xca, 0x85, 0x85, 0x80,
|
||||
0x3b, 0xe4, 0x3a, 0x53, 0x6a, 0xd2, 0xd8, 0x66, 0xbd, 0x8e, 0xc8, 0x5b, 0xf0, 0x52, 0xbc, 0x05,
|
||||
0x77, 0xbc, 0x08, 0xda, 0xf5, 0xae, 0x6b, 0x3b, 0x09, 0x12, 0x05, 0xee, 0x76, 0x76, 0x66, 0xcf,
|
||||
0x99, 0x39, 0x73, 0xe2, 0xc0, 0xb6, 0x9f, 0xb1, 0x8b, 0xfd, 0x14, 0xe9, 0x2c, 0x0c, 0x70, 0x3f,
|
||||
0xa1, 0x31, 0x8b, 0xf7, 0xf9, 0x95, 0x2b, 0x8e, 0xc4, 0xfc, 0x18, 0xbb, 0xd3, 0x30, 0xa0, 0xb1,
|
||||
0xcb, 0x2f, 0x9d, 0xaf, 0x3a, 0x34, 0xdf, 0xc4, 0x13, 0x8c, 0xc8, 0x26, 0x34, 0x19, 0x3f, 0x58,
|
||||
0xda, 0x50, 0xdb, 0x5d, 0xf7, 0xf2, 0x80, 0x10, 0x68, 0xb0, 0x79, 0x82, 0x96, 0x2e, 0x2e, 0xc5,
|
||||
0x99, 0x58, 0xd0, 0x0e, 0x28, 0xfa, 0x0c, 0xc7, 0x96, 0x31, 0xd4, 0x76, 0x0d, 0x4f, 0x85, 0x64,
|
||||
0x0b, 0x5a, 0xf8, 0x25, 0x09, 0xe9, 0xdc, 0x6a, 0x88, 0x84, 0x8c, 0xf8, 0x8b, 0x34, 0x3b, 0xfb,
|
||||
0x84, 0x01, 0xb3, 0x9a, 0x02, 0x48, 0x85, 0x9c, 0x95, 0xc6, 0x97, 0x98, 0x5a, 0xad, 0xa1, 0xc1,
|
||||
0x59, 0x45, 0x40, 0x9e, 0x40, 0x67, 0x8a, 0xcc, 0x1f, 0xfb, 0xcc, 0xb7, 0xda, 0x43, 0x63, 0xb7,
|
||||
0x3b, 0x72, 0xdc, 0x4a, 0xdf, 0xae, 0xe8, 0xd9, 0x3d, 0x95, 0x45, 0xc7, 0x11, 0xa3, 0x73, 0xaf,
|
||||
0x78, 0x63, 0x3f, 0x02, 0xb3, 0x92, 0x22, 0x03, 0x30, 0x26, 0x38, 0x97, 0xa3, 0xf1, 0x23, 0x27,
|
||||
0x9e, 0xf9, 0x97, 0x99, 0x9a, 0x2c, 0x0f, 0x1e, 0xea, 0x0f, 0x34, 0xe7, 0xbb, 0x06, 0xed, 0xc3,
|
||||
0x20, 0x88, 0xb3, 0x88, 0x91, 0x1e, 0xe8, 0xe1, 0x58, 0x3e, 0xd3, 0xc3, 0x31, 0xd9, 0x83, 0x56,
|
||||
0x8a, 0x01, 0x45, 0x26, 0x9e, 0x75, 0x47, 0x9b, 0xcb, 0xda, 0xf2, 0x64, 0xcd, 0xd5, 0x70, 0x46,
|
||||
0x79, 0xb8, 0xa7, 0xa5, 0xe1, 0x1a, 0x62, 0xb8, 0x3b, 0x35, 0x14, 0xc9, 0xfe, 0x6f, 0xc6, 0x7b,
|
||||
0x0d, 0x1d, 0x0f, 0xd3, 0x38, 0xa3, 0x01, 0xf2, 0xed, 0x46, 0xfe, 0x14, 0xe5, 0x43, 0x71, 0x5e,
|
||||
0xba, 0x71, 0x1b, 0x3a, 0x18, 0x8d, 0x93, 0x38, 0x8c, 0x98, 0x58, 0xf9, 0xba, 0x57, 0xc4, 0xce,
|
||||
0x0f, 0x0d, 0xfa, 0x27, 0x18, 0x21, 0xf5, 0x19, 0x7a, 0xf8, 0x39, 0xc3, 0x74, 0x51, 0xb6, 0x42,
|
||||
0x08, 0xbd, 0x2c, 0xc4, 0xf3, 0x92, 0x10, 0x86, 0x10, 0x62, 0xaf, 0x26, 0x44, 0x0d, 0x77, 0x95,
|
||||
0x20, 0xe4, 0x36, 0x98, 0xb9, 0xe4, 0x1f, 0x2a, 0xf6, 0xdb, 0xc8, 0x2f, 0x8f, 0xc5, 0xdd, 0x9f,
|
||||
0xa9, 0x76, 0x04, 0x83, 0xab, 0x66, 0xd2, 0x24, 0x8e, 0x52, 0x24, 0xf7, 0xa1, 0xed, 0xe7, 0x9b,
|
||||
0x12, 0x18, 0xdd, 0xd1, 0xd6, 0xf2, 0x3d, 0x7a, 0xaa, 0xcc, 0x79, 0x07, 0x1b, 0x27, 0xd4, 0x8f,
|
||||
0x98, 0xd2, 0x89, 0x40, 0x83, 0x4b, 0xa1, 0xf4, 0xe7, 0x67, 0x72, 0x00, 0x1d, 0x2a, 0xf7, 0x23,
|
||||
0x4d, 0xf6, 0x5f, 0x0d, 0x56, 0xad, 0xcf, 0x2b, 0x0a, 0x9d, 0x3e, 0x98, 0x12, 0x38, 0xef, 0xcd,
|
||||
0x99, 0x81, 0xf9, 0x16, 0x69, 0x78, 0x3e, 0x57, 0x54, 0xbf, 0xdd, 0xec, 0xf5, 0x1a, 0x19, 0x40,
|
||||
0x4f, 0xf1, 0xca, 0x4e, 0xde, 0x83, 0xe9, 0xe1, 0x2c, 0x9e, 0xe0, 0x5f, 0x1f, 0x7a, 0x00, 0x3d,
|
||||
0x85, 0x2c, 0xb9, 0xee, 0x42, 0xef, 0x45, 0x94, 0x26, 0x18, 0x14, 0x0a, 0x2f, 0xfd, 0xaa, 0x39,
|
||||
0xcf, 0xa0, 0x5f, 0xd4, 0x5d, 0x7b, 0x99, 0xaf, 0x38, 0xfd, 0x39, 0xc5, 0xf4, 0x42, 0x91, 0x6d,
|
||||
0x15, 0x5f, 0x87, 0x9c, 0x4d, 0x7d, 0x07, 0x6e, 0xc1, 0x86, 0xe0, 0x55, 0xee, 0xd4, 0x85, 0x3b,
|
||||
0xbb, 0xe2, 0x2e, 0x37, 0xa7, 0xf3, 0x18, 0xfa, 0x05, 0x98, 0xec, 0xe8, 0x5e, 0xb9, 0xf5, 0x55,
|
||||
0x9f, 0x9a, 0xbc, 0x64, 0xf4, 0xcd, 0x80, 0xc6, 0x61, 0xc6, 0x2e, 0xc8, 0x29, 0x74, 0x94, 0x4f,
|
||||
0xc9, 0xce, 0xaf, 0x7f, 0x4d, 0xf6, 0xcd, 0x95, 0x79, 0x29, 0xe7, 0x1a, 0x39, 0x82, 0xa6, 0xf0,
|
||||
0x15, 0xf9, 0xbf, 0x5e, 0x5b, 0xb2, 0xb1, 0x7d, 0x63, 0x79, 0xb2, 0x40, 0x39, 0x81, 0x56, 0x6e,
|
||||
0x0a, 0x52, 0xaf, 0xac, 0x78, 0xd4, 0xde, 0x5e, 0x91, 0x2d, 0x03, 0xe5, 0x1b, 0x5f, 0x00, 0xaa,
|
||||
0x58, 0x6c, 0x01, 0xa8, 0x66, 0x93, 0x35, 0xf2, 0x12, 0xda, 0xd2, 0x00, 0xa4, 0x5e, 0x5b, 0x35,
|
||||
0x90, 0xbd, 0xb3, 0x2a, 0x5d, 0xc6, 0x92, 0xab, 0x23, 0x8b, 0xbc, 0x65, 0x7f, 0x2c, 0x60, 0xd5,
|
||||
0x36, 0xee, 0xac, 0x9d, 0xb5, 0xc4, 0x9f, 0xf4, 0xc1, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb7,
|
||||
0xf8, 0x55, 0xb6, 0xc5, 0x07, 0x00, 0x00,
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: micro/go-micro/auth/service/proto/auth.proto
|
||||
// source: auth/service/proto/auth.proto
|
||||
|
||||
package go_micro_auth
|
||||
|
||||
@ -35,8 +35,11 @@ var _ server.Option
|
||||
|
||||
type AuthService interface {
|
||||
Generate(ctx context.Context, in *GenerateRequest, opts ...client.CallOption) (*GenerateResponse, error)
|
||||
Grant(ctx context.Context, in *GrantRequest, opts ...client.CallOption) (*GrantResponse, error)
|
||||
Verify(ctx context.Context, in *VerifyRequest, opts ...client.CallOption) (*VerifyResponse, error)
|
||||
Revoke(ctx context.Context, in *RevokeRequest, opts ...client.CallOption) (*RevokeResponse, error)
|
||||
Inspect(ctx context.Context, in *InspectRequest, opts ...client.CallOption) (*InspectResponse, error)
|
||||
Refresh(ctx context.Context, in *RefreshRequest, opts ...client.CallOption) (*RefreshResponse, error)
|
||||
}
|
||||
|
||||
type authService struct {
|
||||
@ -61,6 +64,16 @@ func (c *authService) Generate(ctx context.Context, in *GenerateRequest, opts ..
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authService) Grant(ctx context.Context, in *GrantRequest, opts ...client.CallOption) (*GrantResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Grant", in)
|
||||
out := new(GrantResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authService) Verify(ctx context.Context, in *VerifyRequest, opts ...client.CallOption) (*VerifyResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Verify", in)
|
||||
out := new(VerifyResponse)
|
||||
@ -81,19 +94,45 @@ func (c *authService) Revoke(ctx context.Context, in *RevokeRequest, opts ...cli
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authService) Inspect(ctx context.Context, in *InspectRequest, opts ...client.CallOption) (*InspectResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Inspect", in)
|
||||
out := new(InspectResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authService) Refresh(ctx context.Context, in *RefreshRequest, opts ...client.CallOption) (*RefreshResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Refresh", in)
|
||||
out := new(RefreshResponse)
|
||||
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
|
||||
Grant(context.Context, *GrantRequest, *GrantResponse) error
|
||||
Verify(context.Context, *VerifyRequest, *VerifyResponse) error
|
||||
Revoke(context.Context, *RevokeRequest, *RevokeResponse) error
|
||||
Inspect(context.Context, *InspectRequest, *InspectResponse) error
|
||||
Refresh(context.Context, *RefreshRequest, *RefreshResponse) error
|
||||
}
|
||||
|
||||
func RegisterAuthHandler(s server.Server, hdlr AuthHandler, opts ...server.HandlerOption) error {
|
||||
type auth interface {
|
||||
Generate(ctx context.Context, in *GenerateRequest, out *GenerateResponse) error
|
||||
Grant(ctx context.Context, in *GrantRequest, out *GrantResponse) error
|
||||
Verify(ctx context.Context, in *VerifyRequest, out *VerifyResponse) error
|
||||
Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error
|
||||
Inspect(ctx context.Context, in *InspectRequest, out *InspectResponse) error
|
||||
Refresh(ctx context.Context, in *RefreshRequest, out *RefreshResponse) error
|
||||
}
|
||||
type Auth struct {
|
||||
auth
|
||||
@ -110,6 +149,10 @@ func (h *authHandler) Generate(ctx context.Context, in *GenerateRequest, out *Ge
|
||||
return h.AuthHandler.Generate(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Grant(ctx context.Context, in *GrantRequest, out *GrantResponse) error {
|
||||
return h.AuthHandler.Grant(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Verify(ctx context.Context, in *VerifyRequest, out *VerifyResponse) error {
|
||||
return h.AuthHandler.Verify(ctx, in, out)
|
||||
}
|
||||
@ -117,3 +160,11 @@ func (h *authHandler) Verify(ctx context.Context, in *VerifyRequest, out *Verify
|
||||
func (h *authHandler) Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error {
|
||||
return h.AuthHandler.Revoke(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Inspect(ctx context.Context, in *InspectRequest, out *InspectResponse) error {
|
||||
return h.AuthHandler.Inspect(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Refresh(ctx context.Context, in *RefreshRequest, out *RefreshResponse) error {
|
||||
return h.AuthHandler.Refresh(ctx, in, out)
|
||||
}
|
||||
|
@ -4,47 +4,81 @@ package go.micro.auth;
|
||||
|
||||
service Auth {
|
||||
rpc Generate(GenerateRequest) returns (GenerateResponse) {};
|
||||
rpc Grant(GrantRequest) returns (GrantResponse) {};
|
||||
rpc Verify(VerifyRequest) returns (VerifyResponse) {};
|
||||
rpc Revoke(RevokeRequest) returns (RevokeResponse) {};
|
||||
rpc Inspect(InspectRequest) returns (InspectResponse) {};
|
||||
rpc Refresh(RefreshRequest) returns (RefreshResponse) {};
|
||||
}
|
||||
|
||||
message Token {
|
||||
string token = 1;
|
||||
string type = 2;
|
||||
int64 created = 3;
|
||||
int64 expiry = 4;
|
||||
string subject = 5;
|
||||
repeated string roles = 6;
|
||||
map<string, string> metadata = 7;
|
||||
}
|
||||
|
||||
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;
|
||||
Token secret = 2;
|
||||
repeated string roles = 3;
|
||||
map<string, string> metadata = 4;
|
||||
}
|
||||
|
||||
message Resource{
|
||||
string name = 1;
|
||||
string type = 2;
|
||||
string endpoint = 3;
|
||||
}
|
||||
|
||||
message GenerateRequest {
|
||||
Account account = 1;
|
||||
string id = 1;
|
||||
repeated string roles = 2;
|
||||
map<string, string> metadata = 3;
|
||||
int64 secret_expiry = 4;
|
||||
}
|
||||
|
||||
message GenerateResponse {
|
||||
Account account = 1;
|
||||
}
|
||||
|
||||
message VerifyRequest {
|
||||
string token = 1;
|
||||
message GrantRequest {
|
||||
string role = 1;
|
||||
Resource resource = 2;
|
||||
}
|
||||
|
||||
message VerifyResponse {
|
||||
message GrantResponse {}
|
||||
|
||||
message VerifyRequest {
|
||||
Account account = 1;
|
||||
Resource resource = 2;
|
||||
}
|
||||
|
||||
message VerifyResponse {}
|
||||
|
||||
message RevokeRequest {
|
||||
string token = 1;
|
||||
string role = 1;
|
||||
Resource resource = 2;
|
||||
}
|
||||
|
||||
message RevokeResponse {}
|
||||
|
||||
message InspectRequest {
|
||||
string token = 1;
|
||||
}
|
||||
|
||||
message InspectResponse {
|
||||
Account account = 1;
|
||||
}
|
||||
|
||||
message RefreshRequest {
|
||||
string secret = 1;
|
||||
int64 token_expiry = 2;
|
||||
}
|
||||
|
||||
message RefreshResponse {
|
||||
Token token = 1;
|
||||
}
|
@ -2,10 +2,13 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
pb "github.com/micro/go-micro/v2/auth/service/proto"
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
"github.com/micro/go-micro/v2/auth/token/jwt"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
)
|
||||
|
||||
@ -20,13 +23,14 @@ func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
type svc struct {
|
||||
options auth.Options
|
||||
auth pb.AuthService
|
||||
jwt token.Provider
|
||||
}
|
||||
|
||||
func (s *svc) String() string {
|
||||
return "service"
|
||||
}
|
||||
|
||||
func (s *svc) Init(opts ...auth.Option) error {
|
||||
func (s *svc) Init(opts ...auth.Option) {
|
||||
for _, o := range opts {
|
||||
o(&s.options)
|
||||
}
|
||||
@ -34,99 +38,140 @@ func (s *svc) Init(opts ...auth.Option) error {
|
||||
dc := client.DefaultClient
|
||||
s.auth = pb.NewAuthService("go.micro.auth", dc)
|
||||
|
||||
return nil
|
||||
// if we have a JWT public key passed as an option,
|
||||
// we can decode tokens with the type "JWT" locally
|
||||
// and not have to make an RPC call
|
||||
if key := s.options.PublicKey; len(key) > 0 {
|
||||
s.jwt = jwt.NewTokenProvider(token.WithPublicKey(key))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *svc) Options() auth.Options {
|
||||
return s.options
|
||||
}
|
||||
|
||||
// Generate a new auth account
|
||||
// Generate a new account
|
||||
func (s *svc) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
|
||||
// construct the request
|
||||
options := auth.NewGenerateOptions(opts...)
|
||||
sa := &auth.Account{
|
||||
|
||||
rsp, err := s.auth.Generate(context.TODO(), &pb.GenerateRequest{
|
||||
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)
|
||||
SecretExpiry: int64(options.SecretExpiry.Seconds()),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// format the response
|
||||
return deserializeAccount(resp.Account), nil
|
||||
return serializeAccount(rsp.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)
|
||||
// Grant access to a resource
|
||||
func (s *svc) Grant(role string, res *auth.Resource) error {
|
||||
_, err := s.auth.Grant(context.TODO(), &pb.GrantRequest{
|
||||
Role: role,
|
||||
Resource: &pb.Resource{
|
||||
Type: res.Type,
|
||||
Name: res.Name,
|
||||
Endpoint: res.Endpoint,
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify an account token
|
||||
func (s *svc) Verify(token string) (*auth.Account, error) {
|
||||
resp, err := s.auth.Verify(context.Background(), &pb.VerifyRequest{Token: token})
|
||||
// Revoke access to a resource
|
||||
func (s *svc) Revoke(role string, res *auth.Resource) error {
|
||||
_, err := s.auth.Revoke(context.TODO(), &pb.RevokeRequest{
|
||||
Role: role,
|
||||
Resource: &pb.Resource{
|
||||
Type: res.Type,
|
||||
Name: res.Name,
|
||||
Endpoint: res.Endpoint,
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify an account has access to a resource
|
||||
func (s *svc) Verify(acc *auth.Account, res *auth.Resource) error {
|
||||
_, err := s.auth.Verify(context.TODO(), &pb.VerifyRequest{
|
||||
Account: &pb.Account{
|
||||
Id: acc.ID,
|
||||
Roles: acc.Roles,
|
||||
},
|
||||
Resource: &pb.Resource{
|
||||
Type: res.Type,
|
||||
Name: res.Name,
|
||||
Endpoint: res.Endpoint,
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
rsp, err := s.auth.Inspect(context.TODO(), &pb.InspectRequest{
|
||||
Token: token,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return deserializeAccount(resp.Account), nil
|
||||
return serializeAccount(rsp.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,
|
||||
// Refresh an account using a secret
|
||||
func (s *svc) Refresh(secret string, opts ...auth.RefreshOption) (*auth.Token, error) {
|
||||
options := auth.NewRefreshOptions(opts...)
|
||||
|
||||
rsp, err := s.auth.Refresh(context.Background(), &pb.RefreshRequest{
|
||||
Secret: secret,
|
||||
TokenExpiry: int64(options.TokenExpiry.Seconds()),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if r.Resource != nil {
|
||||
roles[i].Resource = &pb.Resource{
|
||||
Name: r.Resource.Name,
|
||||
Type: r.Resource.Type,
|
||||
return serializeToken(rsp.Token), nil
|
||||
}
|
||||
|
||||
func serializeToken(t *pb.Token) *auth.Token {
|
||||
return &auth.Token{
|
||||
Token: t.Token,
|
||||
Type: t.Type,
|
||||
Created: time.Unix(t.Created, 0),
|
||||
Expiry: time.Unix(t.Expiry, 0),
|
||||
Subject: t.Subject,
|
||||
Roles: t.Roles,
|
||||
Metadata: t.Metadata,
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.Account{
|
||||
Id: sa.Id,
|
||||
Roles: roles,
|
||||
Metadata: sa.Metadata,
|
||||
}
|
||||
func serializeAccount(a *pb.Account) *auth.Account {
|
||||
var secret *auth.Token
|
||||
if a.Secret != nil {
|
||||
secret = serializeToken(a.Secret)
|
||||
}
|
||||
|
||||
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),
|
||||
return &auth.Account{
|
||||
ID: a.Id,
|
||||
Roles: a.Roles,
|
||||
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,
|
||||
Secret: secret,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sa
|
||||
}
|
||||
|
72
auth/store/rules.go
Normal file
72
auth/store/rules.go
Normal file
@ -0,0 +1,72 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
)
|
||||
|
||||
// Rule is an access control rule
|
||||
type Rule struct {
|
||||
Role string `json:"rule"`
|
||||
Resource *auth.Resource `json:"resource"`
|
||||
}
|
||||
|
||||
// Key to be used when written to the store
|
||||
func (r *Rule) Key() string {
|
||||
comps := []string{r.Resource.Type, r.Resource.Name, r.Resource.Endpoint, r.Role}
|
||||
return strings.Join(comps, "/")
|
||||
}
|
||||
|
||||
// Bytes returns json encoded bytes
|
||||
func (r *Rule) Bytes() []byte {
|
||||
bytes, _ := json.Marshal(r)
|
||||
return bytes
|
||||
}
|
||||
|
||||
// isValidRule returns a bool, indicating if a rule permits access to a
|
||||
// resource for a given account
|
||||
func isValidRule(rule Rule, acc *auth.Account, res *auth.Resource) bool {
|
||||
if rule.Role == "*" {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, role := range acc.Roles {
|
||||
if rule.Role == role {
|
||||
return true
|
||||
}
|
||||
|
||||
// allow user.anything if role is user.*
|
||||
if strings.HasSuffix(rule.Role, ".*") && strings.HasPrefix(rule.Role, role+".") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// listRules gets all the rules from the store which have a key
|
||||
// prefix matching the filters
|
||||
func (s *Store) listRules(filters ...string) ([]Rule, error) {
|
||||
// get the records from the store
|
||||
prefix := strings.Join(filters, "/")
|
||||
recs, err := s.opts.Store.Read(prefix, store.ReadPrefix())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// unmarshal the records
|
||||
rules := make([]Rule, 0, len(recs))
|
||||
for _, rec := range recs {
|
||||
var r Rule
|
||||
if err := json.Unmarshal(rec.Value, &r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rules = append(rules, r)
|
||||
}
|
||||
|
||||
// return the rules
|
||||
return rules, nil
|
||||
}
|
@ -1,130 +1,159 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
"github.com/micro/go-micro/v2/auth/token/basic"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
memStore "github.com/micro/go-micro/v2/store/memory"
|
||||
)
|
||||
|
||||
type Auth struct {
|
||||
store store.Store
|
||||
// NewAuth returns a new default registry which is store
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
var s Store
|
||||
s.Init(opts...)
|
||||
return &s
|
||||
}
|
||||
|
||||
// Store implementation of auth
|
||||
type Store struct {
|
||||
secretProvider token.Provider
|
||||
tokenProvider token.Provider
|
||||
opts auth.Options
|
||||
}
|
||||
|
||||
// NewAuth returns an instance of store auth
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
var options auth.Options
|
||||
// String returns store
|
||||
func (s *Store) String() string {
|
||||
return "store"
|
||||
}
|
||||
|
||||
// Init the auth
|
||||
func (s *Store) Init(opts ...auth.Option) {
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
o(&s.opts)
|
||||
}
|
||||
|
||||
return &Auth{
|
||||
store: store.DefaultStore,
|
||||
opts: options,
|
||||
// use the default store as a fallback
|
||||
if s.opts.Store == nil {
|
||||
s.opts.Store = store.DefaultStore
|
||||
}
|
||||
|
||||
// noop will not work for auth
|
||||
if s.opts.Store.String() == "noop" {
|
||||
s.opts.Store = memStore.NewStore()
|
||||
}
|
||||
|
||||
if s.tokenProvider == nil {
|
||||
s.tokenProvider = basic.NewTokenProvider(token.WithStore(s.opts.Store))
|
||||
}
|
||||
if s.secretProvider == nil {
|
||||
s.secretProvider = basic.NewTokenProvider(token.WithStore(s.opts.Store))
|
||||
}
|
||||
}
|
||||
|
||||
// Init the auth package
|
||||
func (a *Auth) Init(opts ...auth.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&a.opts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Options returns the options set
|
||||
func (a *Auth) Options() auth.Options {
|
||||
return a.opts
|
||||
}
|
||||
|
||||
// Generate a new auth Account
|
||||
func (a *Auth) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
|
||||
// generate the token
|
||||
token, err := uuid.NewUUID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Options returns the options
|
||||
func (s *Store) Options() auth.Options {
|
||||
return s.opts
|
||||
}
|
||||
|
||||
// Generate a new account
|
||||
func (s *Store) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
|
||||
// parse the options
|
||||
options := auth.NewGenerateOptions(opts...)
|
||||
|
||||
// construct the account
|
||||
sa := auth.Account{
|
||||
Id: id,
|
||||
Token: token.String(),
|
||||
Created: time.Now(),
|
||||
Metadata: options.Metadata,
|
||||
Roles: options.Roles,
|
||||
// Generate a long-lived secret
|
||||
secretOpts := []token.GenerateOption{
|
||||
token.WithExpiry(options.SecretExpiry),
|
||||
token.WithMetadata(options.Metadata),
|
||||
token.WithRoles(options.Roles),
|
||||
}
|
||||
|
||||
// encode the data to bytes
|
||||
// TODO: replace with json
|
||||
buf := &bytes.Buffer{}
|
||||
e := gob.NewEncoder(buf)
|
||||
if err := e.Encode(sa); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// write to the store
|
||||
err = a.store.Write(&store.Record{
|
||||
Key: token.String(),
|
||||
Value: buf.Bytes(),
|
||||
})
|
||||
secret, err := s.secretProvider.Generate(id, secretOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return the result
|
||||
return &sa, nil
|
||||
// return the account
|
||||
return &auth.Account{
|
||||
ID: id,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
Secret: secret,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Revoke an authorization Account
|
||||
func (a *Auth) Revoke(token string) error {
|
||||
records, err := a.store.Read(token, store.ReadSuffix())
|
||||
// Grant access to a resource
|
||||
func (s *Store) Grant(role string, res *auth.Resource) error {
|
||||
r := Rule{role, res}
|
||||
return s.opts.Store.Write(&store.Record{Key: r.Key(), Value: r.Bytes()})
|
||||
}
|
||||
|
||||
// Revoke access to a resource
|
||||
func (s *Store) Revoke(role string, res *auth.Resource) error {
|
||||
r := Rule{role, res}
|
||||
|
||||
err := s.opts.Store.Delete(r.Key())
|
||||
if err == store.ErrNotFound {
|
||||
return auth.ErrNotFound
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify an account has access to a resource
|
||||
func (s *Store) Verify(acc *auth.Account, res *auth.Resource) error {
|
||||
queries := [][]string{
|
||||
{res.Type, "*"}, // check for wildcard resource type, e.g. service.*
|
||||
{res.Type, res.Name, "*"}, // check for wildcard name, e.g. service.foo*
|
||||
{res.Type, res.Name, res.Endpoint, "*"}, // check for wildcard endpoints, e.g. service.foo.ListFoo:*
|
||||
{res.Type, res.Name, res.Endpoint}, // check for specific role, e.g. service.foo.ListFoo:admin
|
||||
}
|
||||
|
||||
for _, q := range queries {
|
||||
rules, err := s.listRules(q...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(records) == 0 {
|
||||
return errors.BadRequest("go.micro.auth", "token not found")
|
||||
}
|
||||
|
||||
for _, r := range records {
|
||||
if err := a.store.Delete(r.Key); err != nil {
|
||||
return errors.InternalServerError("go.micro.auth", "error deleting from store")
|
||||
}
|
||||
}
|
||||
|
||||
for _, rule := range rules {
|
||||
if isValidRule(rule, acc, res) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify an account token
|
||||
func (a *Auth) Verify(token string) (*auth.Account, error) {
|
||||
// lookup the record by token
|
||||
records, err := a.store.Read(token, store.ReadSuffix())
|
||||
if err == store.ErrNotFound || len(records) == 0 {
|
||||
return nil, errors.Unauthorized("go.micro.auth", "invalid token")
|
||||
return auth.ErrForbidden
|
||||
}
|
||||
|
||||
// Inspect a token
|
||||
func (s *Store) Inspect(t string) (*auth.Account, error) {
|
||||
tok, err := s.tokenProvider.Inspect(t)
|
||||
if err == token.ErrInvalidToken || err == token.ErrNotFound {
|
||||
return nil, auth.ErrInvalidToken
|
||||
} else if err != nil {
|
||||
return nil, errors.InternalServerError("go.micro.auth", "error reading store")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// decode the result
|
||||
// TODO: replace with json
|
||||
b := bytes.NewBuffer(records[0].Value)
|
||||
decoder := gob.NewDecoder(b)
|
||||
var sa auth.Account
|
||||
err = decoder.Decode(&sa)
|
||||
|
||||
// return the result
|
||||
return &sa, err
|
||||
return &auth.Account{
|
||||
ID: tok.Subject,
|
||||
Roles: tok.Roles,
|
||||
Metadata: tok.Metadata,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// String returns the implementation
|
||||
func (a *Auth) String() string {
|
||||
return "store"
|
||||
// Refresh an account using a secret
|
||||
func (s *Store) Refresh(secret string, opts ...auth.RefreshOption) (*auth.Token, error) {
|
||||
sec, err := s.secretProvider.Inspect(secret)
|
||||
if err == token.ErrInvalidToken || err == token.ErrNotFound {
|
||||
return nil, auth.ErrInvalidToken
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
options := auth.NewRefreshOptions(opts...)
|
||||
|
||||
return s.tokenProvider.Generate(sec.Subject,
|
||||
token.WithExpiry(options.TokenExpiry),
|
||||
token.WithMetadata(sec.Metadata),
|
||||
token.WithRoles(sec.Roles),
|
||||
)
|
||||
}
|
||||
|
287
auth/store/store_test.go
Normal file
287
auth/store/store_test.go
Normal file
@ -0,0 +1,287 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
memStore "github.com/micro/go-micro/v2/store/memory"
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
s := memStore.NewStore()
|
||||
a := NewAuth(auth.Store(s))
|
||||
|
||||
id := "test"
|
||||
roles := []string{"admin"}
|
||||
metadata := map[string]string{"foo": "bar"}
|
||||
|
||||
opts := []auth.GenerateOption{
|
||||
auth.WithRoles(roles),
|
||||
auth.WithMetadata(metadata),
|
||||
}
|
||||
|
||||
// generate the account
|
||||
acc, err := a.Generate(id, opts...)
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned an error: %v, expected nil", err)
|
||||
}
|
||||
// validate the account attributes were set correctly
|
||||
if acc.ID != id {
|
||||
t.Errorf("Generate returned %v as the ID, expected %v", acc.ID, id)
|
||||
}
|
||||
if len(acc.Roles) != len(roles) {
|
||||
t.Errorf("Generate returned %v as the roles, expected %v", acc.Roles, roles)
|
||||
}
|
||||
if len(acc.Metadata) != len(metadata) {
|
||||
t.Errorf("Generate returned %v as the metadata, expected %v", acc.Metadata, metadata)
|
||||
}
|
||||
|
||||
// validate the secret is valid
|
||||
if _, err := a.Refresh(acc.Secret.Token); err != nil {
|
||||
t.Errorf("Generate returned an invalid secret, error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGrant(t *testing.T) {
|
||||
s := memStore.NewStore()
|
||||
a := NewAuth(auth.Store(s))
|
||||
|
||||
res := &auth.Resource{Type: "service", Name: "Test", Endpoint: "Foo.Bar"}
|
||||
if err := a.Grant("users.*", res); err != nil {
|
||||
t.Fatalf("Grant returned an error: %v, expected nil", err)
|
||||
}
|
||||
|
||||
recs, err := s.List()
|
||||
if err != nil {
|
||||
t.Fatalf("Could not read from the store: %v", err)
|
||||
}
|
||||
if len(recs) != 1 {
|
||||
t.Errorf("Expected Grant to write 1 record, actually wrote %v", len(recs))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRevoke(t *testing.T) {
|
||||
s := memStore.NewStore()
|
||||
a := NewAuth(auth.Store(s))
|
||||
|
||||
res := &auth.Resource{Type: "service", Name: "Test", Endpoint: "Foo.Bar"}
|
||||
if err := a.Grant("users.*", res); err != nil {
|
||||
t.Fatalf("Grant returned an error: %v, expected nil", err)
|
||||
}
|
||||
|
||||
recs, err := s.List()
|
||||
if err != nil {
|
||||
t.Fatalf("Could not read from the store: %v", err)
|
||||
}
|
||||
if len(recs) != 1 {
|
||||
t.Fatalf("Expected Grant to write 1 record, actually wrote %v", len(recs))
|
||||
}
|
||||
|
||||
if err := a.Revoke("users.*", res); err != nil {
|
||||
t.Fatalf("Revoke returned an error: %v, expected nil", err)
|
||||
}
|
||||
|
||||
recs, err = s.List()
|
||||
if err != nil {
|
||||
t.Fatalf("Could not read from the store: %v", err)
|
||||
}
|
||||
if len(recs) != 0 {
|
||||
t.Fatalf("Expected Revoke to delete 1 record, actually deleted %v", 1-len(recs))
|
||||
}
|
||||
}
|
||||
|
||||
func TestInspect(t *testing.T) {
|
||||
a := NewAuth()
|
||||
|
||||
t.Run("Valid Token", func(t *testing.T) {
|
||||
id := "test"
|
||||
roles := []string{"admin"}
|
||||
metadata := map[string]string{"foo": "bar"}
|
||||
|
||||
opts := []auth.GenerateOption{
|
||||
auth.WithRoles(roles),
|
||||
auth.WithMetadata(metadata),
|
||||
}
|
||||
|
||||
// generate and inspect the token
|
||||
acc, err := a.Generate("test", opts...)
|
||||
if err != nil {
|
||||
log.Fatalf("Generate returned an error: %v, expected nil", err)
|
||||
}
|
||||
tok, err := a.Refresh(acc.Secret.Token)
|
||||
if err != nil {
|
||||
log.Fatalf("Refresh returned an error: %v, expected nil", err)
|
||||
}
|
||||
acc2, err := a.Inspect(tok.Token)
|
||||
if err != nil {
|
||||
log.Fatalf("Inspect returned an error: %v, expected nil", err)
|
||||
}
|
||||
|
||||
// validate the account attributes were retrieved correctly
|
||||
if acc2.ID != id {
|
||||
t.Errorf("Generate returned %v as the ID, expected %v", acc.ID, id)
|
||||
}
|
||||
if len(acc2.Roles) != len(roles) {
|
||||
t.Errorf("Generate returned %v as the roles, expected %v", acc.Roles, roles)
|
||||
}
|
||||
if len(acc2.Metadata) != len(metadata) {
|
||||
t.Errorf("Generate returned %v as the metadata, expected %v", acc.Metadata, metadata)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Invalid Token", func(t *testing.T) {
|
||||
_, err := a.Inspect("invalid token")
|
||||
if err != auth.ErrInvalidToken {
|
||||
t.Errorf("Inspect returned %v error, expected %v", err, auth.ErrInvalidToken)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRefresh(t *testing.T) {
|
||||
a := NewAuth()
|
||||
|
||||
t.Run("Valid Secret", func(t *testing.T) {
|
||||
roles := []string{"admin"}
|
||||
metadata := map[string]string{"foo": "bar"}
|
||||
|
||||
opts := []auth.GenerateOption{
|
||||
auth.WithRoles(roles),
|
||||
auth.WithMetadata(metadata),
|
||||
}
|
||||
|
||||
// generate the account
|
||||
acc, err := a.Generate("test", opts...)
|
||||
if err != nil {
|
||||
log.Fatalf("Generate returned an error: %v, expected nil", err)
|
||||
}
|
||||
|
||||
// refresh the token
|
||||
tok, err := a.Refresh(acc.Secret.Token)
|
||||
if err != nil {
|
||||
log.Fatalf("Refresh returned an error: %v, expected nil", err)
|
||||
}
|
||||
|
||||
// validate the account attributes were set correctly
|
||||
if acc.ID != tok.Subject {
|
||||
t.Errorf("Refresh returned %v as the ID, expected %v", acc.ID, tok.Subject)
|
||||
}
|
||||
if len(acc.Roles) != len(tok.Roles) {
|
||||
t.Errorf("Refresh returned %v as the roles, expected %v", acc.Roles, tok.Subject)
|
||||
}
|
||||
if len(acc.Metadata) != len(tok.Metadata) {
|
||||
t.Errorf("Refresh returned %v as the metadata, expected %v", acc.Metadata, tok.Metadata)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Invalid Secret", func(t *testing.T) {
|
||||
_, err := a.Refresh("invalid secret")
|
||||
if err != auth.ErrInvalidToken {
|
||||
t.Errorf("Inspect returned %v error, expected %v", err, auth.ErrInvalidToken)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestVerify(t *testing.T) {
|
||||
testRules := []struct {
|
||||
Role string
|
||||
Resource *auth.Resource
|
||||
}{
|
||||
{
|
||||
Role: "*",
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.PublicList"},
|
||||
},
|
||||
{
|
||||
Role: "user.*",
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.List"},
|
||||
},
|
||||
{
|
||||
Role: "user.developer",
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.Update"},
|
||||
},
|
||||
{
|
||||
Role: "admin",
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.Delete"},
|
||||
},
|
||||
{
|
||||
Role: "admin",
|
||||
Resource: &auth.Resource{Type: "service", Name: "*", Endpoint: "*"},
|
||||
},
|
||||
}
|
||||
|
||||
a := NewAuth()
|
||||
for _, r := range testRules {
|
||||
if err := a.Grant(r.Role, r.Resource); err != nil {
|
||||
t.Fatalf("Grant returned an error: %v, expected nil", err)
|
||||
}
|
||||
}
|
||||
|
||||
testTable := []struct {
|
||||
Name string
|
||||
Roles []string
|
||||
Resource *auth.Resource
|
||||
Error error
|
||||
}{
|
||||
{
|
||||
Name: "An account with no roles accessing a public endpoint",
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.PublicList"},
|
||||
},
|
||||
{
|
||||
Name: "An account with no roles accessing a private endpoint",
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.Update"},
|
||||
Error: auth.ErrForbidden,
|
||||
},
|
||||
{
|
||||
Name: "An account with the user role accessing a user* endpoint",
|
||||
Roles: []string{"user"},
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.List"},
|
||||
},
|
||||
{
|
||||
Name: "An account with the user role accessing a user.admin endpoint",
|
||||
Roles: []string{"user"},
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.Delete"},
|
||||
Error: auth.ErrForbidden,
|
||||
},
|
||||
{
|
||||
Name: "An account with the developer role accessing a user.developer endpoint",
|
||||
Roles: []string{"user.developer"},
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.Update"},
|
||||
},
|
||||
{
|
||||
Name: "An account with the developer role accessing an admin endpoint",
|
||||
Roles: []string{"user.developer"},
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.Delete"},
|
||||
Error: auth.ErrForbidden,
|
||||
},
|
||||
{
|
||||
Name: "An admin account accessing an admin endpoint",
|
||||
Roles: []string{"admin"},
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.apps", Endpoint: "Apps.Delete"},
|
||||
},
|
||||
{
|
||||
Name: "An admin account accessing a generic service endpoint",
|
||||
Roles: []string{"admin"},
|
||||
Resource: &auth.Resource{Type: "service", Name: "go.micro.foo", Endpoint: "Foo.Bar"},
|
||||
},
|
||||
{
|
||||
Name: "An admin account accessing an unauthorised endpoint",
|
||||
Roles: []string{"admin"},
|
||||
Resource: &auth.Resource{Type: "infra", Name: "go.micro.foo", Endpoint: "Foo.Bar"},
|
||||
Error: auth.ErrForbidden,
|
||||
},
|
||||
{
|
||||
Name: "A account with no roles accessing an unauthorised endpoint",
|
||||
Resource: &auth.Resource{Type: "infra", Name: "go.micro.foo", Endpoint: "Foo.Bar"},
|
||||
Error: auth.ErrForbidden,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
acc := &auth.Account{Roles: tc.Roles}
|
||||
if err := a.Verify(acc, tc.Resource); err != tc.Error {
|
||||
t.Errorf("Verify returned %v error, expected %v", err, tc.Error)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
95
auth/token/basic/basic.go
Normal file
95
auth/token/basic/basic.go
Normal file
@ -0,0 +1,95 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
)
|
||||
|
||||
// Basic implementation of token provider, backed by the store
|
||||
type Basic struct {
|
||||
store store.Store
|
||||
}
|
||||
|
||||
// NewTokenProvider returns an initialized basic provider
|
||||
func NewTokenProvider(opts ...token.Option) token.Provider {
|
||||
options := token.NewOptions(opts...)
|
||||
|
||||
if options.Store == nil {
|
||||
options.Store = store.DefaultStore
|
||||
}
|
||||
|
||||
return &Basic{
|
||||
store: options.Store,
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a token for an account
|
||||
func (b *Basic) Generate(subject string, opts ...token.GenerateOption) (*auth.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,
|
||||
}
|
||||
|
||||
// marshal the account to bytes
|
||||
bytes, err := json.Marshal(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// write to the store
|
||||
err = b.store.Write(&store.Record{
|
||||
Key: token.Token,
|
||||
Value: bytes,
|
||||
Expiry: options.Expiry,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return the token
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
// Inspect a token
|
||||
func (b *Basic) Inspect(t string) (*auth.Token, error) {
|
||||
// lookup the token in the store
|
||||
recs, err := b.store.Read(t)
|
||||
if err == store.ErrNotFound {
|
||||
return nil, token.ErrInvalidToken
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bytes := recs[0].Value
|
||||
|
||||
// unmarshal the bytes
|
||||
var tok *auth.Token
|
||||
if err := json.Unmarshal(bytes, &tok); 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
|
||||
}
|
||||
|
||||
// String returns basic
|
||||
func (b *Basic) String() string {
|
||||
return "basic"
|
||||
}
|
80
auth/token/basic/basic_test.go
Normal file
80
auth/token/basic/basic_test.go
Normal file
@ -0,0 +1,80 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
"github.com/micro/go-micro/v2/store/memory"
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
store := memory.NewStore()
|
||||
b := NewTokenProvider(token.WithStore(store))
|
||||
|
||||
_, err := b.Generate("test")
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
|
||||
recs, err := store.List()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read from store: %v", err)
|
||||
}
|
||||
if len(recs) != 1 {
|
||||
t.Errorf("Generate didn't write to the store, expected 1 record, got %v", len(recs))
|
||||
}
|
||||
}
|
||||
|
||||
func TestInspect(t *testing.T) {
|
||||
store := memory.NewStore()
|
||||
b := NewTokenProvider(token.WithStore(store))
|
||||
|
||||
t.Run("Valid token", func(t *testing.T) {
|
||||
md := map[string]string{"foo": "bar"}
|
||||
roles := []string{"admin"}
|
||||
subject := "test"
|
||||
|
||||
opts := []token.GenerateOption{
|
||||
token.WithMetadata(md),
|
||||
token.WithRoles(roles),
|
||||
}
|
||||
|
||||
tok, err := b.Generate(subject, opts...)
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
|
||||
tok2, err := b.Inspect(tok.Token)
|
||||
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 len(tok2.Roles) != len(roles) {
|
||||
t.Errorf("Inspect returned %v roles, expected %v", len(tok2.Roles), len(roles))
|
||||
}
|
||||
if len(tok2.Metadata) != len(md) {
|
||||
t.Errorf("Inspect returned %v as the token metadata, expected %v", tok2.Metadata, md)
|
||||
}
|
||||
})
|
||||
|
||||
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 {
|
||||
t.Fatalf("Inspect returned %v error, expected %v", err, token.ErrInvalidToken)
|
||||
}
|
||||
})
|
||||
}
|
111
auth/token/jwt/jwt.go
Normal file
111
auth/token/jwt/jwt.go
Normal file
@ -0,0 +1,111 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
)
|
||||
|
||||
// authClaims to be encoded in the JWT
|
||||
type authClaims struct {
|
||||
Roles []string `json:"roles"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
// JWT implementation of token provider
|
||||
type JWT struct {
|
||||
opts token.Options
|
||||
}
|
||||
|
||||
// NewTokenProvider returns an initialized basic provider
|
||||
func NewTokenProvider(opts ...token.Option) token.Provider {
|
||||
return &JWT{
|
||||
opts: token.NewOptions(opts...),
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a new JWT
|
||||
func (j *JWT) Generate(subject string, opts ...token.GenerateOption) (*auth.Token, error) {
|
||||
// decode the private key
|
||||
priv, err := base64.StdEncoding.DecodeString(j.opts.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse the private key
|
||||
key, err := jwt.ParseRSAPrivateKeyFromPEM(priv)
|
||||
if err != nil {
|
||||
return nil, token.ErrEncodingToken
|
||||
}
|
||||
|
||||
// parse the options
|
||||
options := token.NewGenerateOptions(opts...)
|
||||
|
||||
// generate the JWT
|
||||
expiry := time.Now().Add(options.Expiry)
|
||||
t := jwt.NewWithClaims(jwt.SigningMethodRS256, authClaims{
|
||||
options.Roles, options.Metadata, jwt.StandardClaims{
|
||||
Subject: subject,
|
||||
ExpiresAt: expiry.Unix(),
|
||||
},
|
||||
})
|
||||
tok, err := t.SignedString(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return the token
|
||||
return &auth.Token{
|
||||
Subject: subject,
|
||||
Token: tok,
|
||||
Type: j.String(),
|
||||
Created: time.Now(),
|
||||
Expiry: expiry,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Inspect a JWT
|
||||
func (j *JWT) Inspect(t string) (*auth.Token, error) {
|
||||
// decode the public key
|
||||
pub, err := base64.StdEncoding.DecodeString(j.opts.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse the public key
|
||||
res, err := jwt.ParseWithClaims(t, &authClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwt.ParseRSAPublicKeyFromPEM(pub)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, token.ErrInvalidToken
|
||||
}
|
||||
|
||||
// validate the token
|
||||
if !res.Valid {
|
||||
return nil, token.ErrInvalidToken
|
||||
}
|
||||
claims, ok := res.Claims.(*authClaims)
|
||||
if !ok {
|
||||
return nil, token.ErrInvalidToken
|
||||
}
|
||||
|
||||
// return the token
|
||||
return &auth.Token{
|
||||
Token: t,
|
||||
Subject: claims.Subject,
|
||||
Metadata: claims.Metadata,
|
||||
Roles: claims.Roles,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// String returns JWT
|
||||
func (j *JWT) String() string {
|
||||
return "jwt"
|
||||
}
|
90
auth/token/jwt/jwt_test.go
Normal file
90
auth/token/jwt/jwt_test.go
Normal file
@ -0,0 +1,90 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
privKey, err := ioutil.ReadFile("test/sample_key")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read private key: %v", err)
|
||||
}
|
||||
|
||||
j := NewTokenProvider(
|
||||
token.WithPrivateKey(string(privKey)),
|
||||
)
|
||||
|
||||
_, err = j.Generate("test")
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInspect(t *testing.T) {
|
||||
pubKey, err := ioutil.ReadFile("test/sample_key.pub")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read public key: %v", err)
|
||||
}
|
||||
privKey, err := ioutil.ReadFile("test/sample_key")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read private key: %v", err)
|
||||
}
|
||||
|
||||
j := NewTokenProvider(
|
||||
token.WithPublicKey(string(pubKey)),
|
||||
token.WithPrivateKey(string(privKey)),
|
||||
)
|
||||
|
||||
t.Run("Valid token", func(t *testing.T) {
|
||||
md := map[string]string{"foo": "bar"}
|
||||
roles := []string{"admin"}
|
||||
subject := "test"
|
||||
|
||||
opts := []token.GenerateOption{
|
||||
token.WithMetadata(md),
|
||||
token.WithRoles(roles),
|
||||
}
|
||||
|
||||
tok, err := j.Generate(subject, opts...)
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
|
||||
tok2, err := j.Inspect(tok.Token)
|
||||
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 len(tok2.Roles) != len(roles) {
|
||||
t.Errorf("Inspect returned %v roles, expected %v", len(tok2.Roles), len(roles))
|
||||
}
|
||||
if len(tok2.Metadata) != len(md) {
|
||||
t.Errorf("Inspect returned %v as the token metadata, expected %v", tok2.Metadata, md)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Expired token", func(t *testing.T) {
|
||||
tok, err := j.Generate("foo", token.WithExpiry(-10*time.Second))
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
|
||||
if _, err = j.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 := j.Inspect("Invalid token")
|
||||
if err != token.ErrInvalidToken {
|
||||
t.Fatalf("Inspect returned %v error, expected %v", err, token.ErrInvalidToken)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
1
auth/token/jwt/test/sample_key
Normal file
1
auth/token/jwt/test/sample_key
Normal file
@ -0,0 +1 @@
|
||||
LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS3dJQkFBS0NBZ0VBOFNiSlA1WGJFaWRSbTViMnNOcExHbzJlV2ZVNU9KZTBpemdySHdEOEg3RjZQa1BkCi9SbDkvMXBNVjdNaU8zTEh3dGhIQzJCUllxcisxd0Zkb1pDR0JZckxhWHVYRnFLMHZ1WmhQcUUzYXpqdUlIUXUKMEJIL2xYUU1xeUVxRjVNSTJ6ZWpDNHpNenIxNU9OK2dFNEpuaXBqcC9DZGpPUEFEbUpHK0JKOXFlRS9RUGVtLwptVWRJVC9MYUY3a1F4eVlLNVZLbitOZ09Xek1sektBQXBDbjdUVEtCVWU4RlpHNldTWDdMVjBlTEdIc29pYnhsCm85akRqbFk1b0JPY3pmcWVOV0hLNUdYQjdRd3BMTmg5NDZQelpucW9hcFdVZStZL1JPaUhpekpUY3I1Wk1TTDUKd2xFcThoTmhtaG01Tk5lL08rR2dqQkROU2ZVaDA2K3E0bmdtYm1OWDVoODM4QmJqUmN5YzM2ZHd6NkpVK2R1bwpSdFFoZ2lZOTEwcFBmOWJhdVhXcXdVQ1VhNHFzSHpqS1IwTC9OMVhYQXlsQ0RqeWVnWnp6Y093MkNIOFNrZkZVCnJnTHJQYkVCOWVnY0drMzgrYnBLczNaNlJyNSt0bkQxQklQSUZHTGVJMFVPQzAreGlCdjBvenhJRE9GbldhOVUKVEdEeFV4OG9qOFZJZVJuV0RxNk1jMWlKcDhVeWNpQklUUnR3NGRabzcweG1mbmVJV3pyM0tTTmFoU29nSmRSMApsYVF6QXVQM2FpV1hJTXAyc2M4U2MrQmwrTGpYbUJveEJyYUJIaDlLa0pKRWNnQUZ3czJib2pDbEpPWXhvRi9YCmdGS1NzSW5IRHJIVk95V1BCZTNmYWRFYzc3YituYi9leE96cjFFcnhoR2c5akZtcmtPK3M0eEdodjZNQ0F3RUEKQVFLQ0FnRUFqUzc1Q2VvUlRRcUtBNzZaaFNiNGEzNVlKRENtcEpSazFsRTNKYnFzNFYxRnhXaDBjZmJYeG9VMgpSdTRRYjUrZWhsdWJGSFQ2a1BxdG9uRWhRVExjMUNmVE9WbHJOb3hocDVZM2ZyUmlQcnNnNXcwK1R3RUtrcFJUCnltanJQTXdQbGxCM2U0NmVaYmVXWGc3R3FFVmptMGcxVFRRK0tocVM4R0w3VGJlTFhRN1ZTem9ydTNCNVRKMVEKeEN6TVB0dnQ2eDYrU3JrcmhvZG1iT3VNRkpDam1TbWxmck9pZzQ4Zkc3NUpERHRObXpLWHBEUVJpYUNodFJhVQpQRHpmUTlTamhYdFFqdkZvWFFFT3BqdkZVRjR2WldNUWNQNUw1VklDM3JRSWp4MFNzQTN6S0FwakVUbjJHNjN2CktZby8zVWttbzhkUCtGRHA3NCs5a3pLNHFFaFJycEl3bEtiN0VOZWtDUXZqUFl1K3pyKzMyUXdQNTJ2L2FveWQKdjJJaUY3M2laTU1vZDhhYjJuQStyVEI2T0cvOVlSYk5kV21tay9VTi9jUHYrN214TmZ6Y1d1ZU1XcThxMXh4eAptNTNpR0NSQ29PQ1lDQk4zcUFkb1JwYW5xd3lCOUxrLzFCQjBHUld3MjgxK3VhNXNYRnZBVDBKeTVURnduMncvClU1MlJKWFlNOXVhMFBvd214b0RDUWRuNFZYVkdNZGdXaHN4aXhHRlYwOUZObWJJQWJaN0xaWGtkS1gzc1ZVbTcKWU1WYWIzVVo2bEhtdXYzT1NzcHNVUlRqN1hiRzZpaVVlaDU1aW91OENWbnRndWtFcnEzQTQwT05FVzhjNDBzOQphVTBGaSs4eWZpQTViaVZHLzF0bWlucUVERkhuQStnWk1xNEhlSkZxcWZxaEZKa1JwRGtDZ2dFQkFQeGR1NGNKCm5Da1duZDdPWFlHMVM3UDdkVWhRUzgwSDlteW9uZFc5bGFCQm84RWRPeTVTZzNOUmsxQ2pNZFZ1a3FMcjhJSnkKeStLWk15SVpvSlJvbllaMEtIUUVMR3ZLbzFOS2NLQ1FJbnYvWHVCdFJpRzBVb1pQNVkwN0RpRFBRQWpYUjlXUwpBc0EzMmQ1eEtFOC91Y3h0MjVQVzJFakNBUmtVeHQ5d0tKazN3bC9JdXVYRlExTDdDWjJsOVlFUjlHeWxUbzhNCmxXUEY3YndtUFV4UVNKaTNVS0FjTzZweTVUU1lkdWQ2aGpQeXJwSXByNU42VGpmTlRFWkVBeU9LbXVpOHVkUkoKMUg3T3RQVEhGZElKQjNrNEJnRDZtRE1HbjB2SXBLaDhZN3NtRUZBbFkvaXlCZjMvOHk5VHVMb1BycEdqR3RHbgp4Y2RpMHFud2p0SGFNbFVDZ2dFQkFQU2Z0dVFCQ2dTU2JLUSswUEFSR2VVeEQyTmlvZk1teENNTmdHUzJ5Ull3CjRGaGV4ZWkwMVJoaFk1NjE3UjduR1dzb0czd1RQa3dvRTJtbE1aQkoxeWEvUU9RRnQ3WG02OVl0RGh0T2FWbDgKL0o4dlVuSTBtWmxtT2pjTlRoYnVPZDlNSDlRdGxIRUMxMlhYdHJNb3Fsb0U2a05TT0pJalNxYm9wcDRXc1BqcApvZTZ0Nkdyd1RhOHBHeUJWWS90Mi85Ym5ORHVPVlpjODBaODdtY2gzcDNQclBqU3h5di9saGxYMFMwYUdHTkhTCk1XVjdUa25OaGo1TWlIRXFnZ1pZemtBWTkyd1JoVENnU1A2M0VNcitUWXFudXVuMXJHbndPYm95TDR2aFRpV0UKcU42UDNCTFlCZ1FpMllDTDludEJrOEl6RHZyd096dW5GVnhhZ0g5SVVoY0NnZ0VCQUwzQXlLa1BlOENWUmR6cQpzL284VkJDZmFSOFhhUGRnSGxTek1BSXZpNXEwNENqckRyMlV3MHZwTVdnM1hOZ0xUT3g5bFJpd3NrYk9SRmxHCmhhd3hRUWlBdkk0SE9WTlBTU0R1WHVNTG5USTQ0S0RFNlMrY2cxU0VMS2pWbDVqcDNFOEpkL1RJMVpLc0xBQUsKZTNHakM5UC9ZbE8xL21ndW4xNjVkWk01cFAwWHBPb2FaeFV2RHFFTktyekR0V1g0RngyOTZlUzdaSFJodFpCNwovQ2t1VUhlcmxrN2RDNnZzdWhTaTh2eTM3c0tPbmQ0K3c4cVM4czhZYVZxSDl3ZzVScUxxakp0bmJBUnc3alVDCm9KQ053M1hNdnc3clhaYzRTbnhVQUNMRGJNV2lLQy9xL1ZGWW9oTEs2WkpUVkJscWd5cjBSYzBRWmpDMlNJb0kKMjRwRWt3VUNnZ0VCQUpqb0FJVVNsVFY0WlVwaExXN3g4WkxPa01UWjBVdFFyd2NPR0hSYndPUUxGeUNGMVFWNQppejNiR2s4SmZyZHpVdk1sTmREZm9uQXVHTHhQa3VTVEUxWlg4L0xVRkJveXhyV3dvZ0cxaUtwME11QTV6em90CjROai9DbUtCQVkvWnh2anA5M2RFS21aZGxWQkdmeUFMeWpmTW5MWUovZXh5L09YSnhPUktZTUttSHg4M08zRWsKMWhvb0FwbTZabTIzMjRGME1iVU1ham5Idld2ZjhHZGJTNk5zcHd4L0dkbk1tYVMrdUJMVUhVMkNLbmc1bEIwVAp4OWJITmY0dXlPbTR0dXRmNzhCd1R5V3UreEdrVW0zZ2VZMnkvR1hqdDZyY2l1ajFGNzFDenZzcXFmZThTcDdJCnd6SHdxcTNzVHR5S2lCYTZuYUdEYWpNR1pKYSt4MVZJV204Q2dnRUJBT001ajFZR25Ba0pxR0czQWJSVDIvNUMKaVVxN0loYkswOGZsSGs5a2YwUlVjZWc0ZVlKY3dIRXJVaE4rdWQyLzE3MC81dDYra0JUdTVZOUg3bkpLREtESQpoeEg5SStyamNlVkR0RVNTRkluSXdDQ1lrOHhOUzZ0cHZMV1U5b0pibGFKMlZsalV2NGRFWGVQb0hkREh1Zk9ZClVLa0lsV2E3Uit1QzNEOHF5U1JrQnFLa3ZXZ1RxcFNmTVNkc1ZTeFIzU2Q4SVhFSHFjTDNUNEtMWGtYNEdEamYKMmZOSTFpZkx6ekhJMTN3Tk5IUTVRNU9SUC9pell2QzVzZkx4U2ZIUXJiMXJZVkpKWkI5ZjVBUjRmWFpHSVFsbApjMG8xd0JmZFlqMnZxVDlpR09IQnNSSTlSL2M2RzJQcUt3aFRpSzJVR2lmVFNEUVFuUkF6b2tpQVkrbE8vUjQ9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
|
1
auth/token/jwt/test/sample_key.pub
Normal file
1
auth/token/jwt/test/sample_key.pub
Normal file
@ -0,0 +1 @@
|
||||
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUE4U2JKUDVYYkVpZFJtNWIyc05wTApHbzJlV2ZVNU9KZTBpemdySHdEOEg3RjZQa1BkL1JsOS8xcE1WN01pTzNMSHd0aEhDMkJSWXFyKzF3RmRvWkNHCkJZckxhWHVYRnFLMHZ1WmhQcUUzYXpqdUlIUXUwQkgvbFhRTXF5RXFGNU1JMnplakM0ek16cjE1T04rZ0U0Sm4KaXBqcC9DZGpPUEFEbUpHK0JKOXFlRS9RUGVtL21VZElUL0xhRjdrUXh5WUs1VktuK05nT1d6TWx6S0FBcENuNwpUVEtCVWU4RlpHNldTWDdMVjBlTEdIc29pYnhsbzlqRGpsWTVvQk9jemZxZU5XSEs1R1hCN1F3cExOaDk0NlB6ClpucW9hcFdVZStZL1JPaUhpekpUY3I1Wk1TTDV3bEVxOGhOaG1obTVOTmUvTytHZ2pCRE5TZlVoMDYrcTRuZ20KYm1OWDVoODM4QmJqUmN5YzM2ZHd6NkpVK2R1b1J0UWhnaVk5MTBwUGY5YmF1WFdxd1VDVWE0cXNIempLUjBMLwpOMVhYQXlsQ0RqeWVnWnp6Y093MkNIOFNrZkZVcmdMclBiRUI5ZWdjR2szOCticEtzM1o2UnI1K3RuRDFCSVBJCkZHTGVJMFVPQzAreGlCdjBvenhJRE9GbldhOVVUR0R4VXg4b2o4VkllUm5XRHE2TWMxaUpwOFV5Y2lCSVRSdHcKNGRabzcweG1mbmVJV3pyM0tTTmFoU29nSmRSMGxhUXpBdVAzYWlXWElNcDJzYzhTYytCbCtMalhtQm94QnJhQgpIaDlLa0pKRWNnQUZ3czJib2pDbEpPWXhvRi9YZ0ZLU3NJbkhEckhWT3lXUEJlM2ZhZEVjNzdiK25iL2V4T3pyCjFFcnhoR2c5akZtcmtPK3M0eEdodjZNQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo=
|
96
auth/token/options.go
Normal file
96
auth/token/options.go
Normal file
@ -0,0 +1,96 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
// Store to persist the tokens
|
||||
Store store.Store
|
||||
// PublicKey base64 encoded, used by JWT
|
||||
PublicKey string
|
||||
// PrivateKey base64 encoded, used by JWT
|
||||
PrivateKey string
|
||||
}
|
||||
|
||||
type Option func(o *Options)
|
||||
|
||||
// WithStore sets the token providers store
|
||||
func WithStore(s store.Store) Option {
|
||||
return func(o *Options) {
|
||||
o.Store = s
|
||||
}
|
||||
}
|
||||
|
||||
// WithPublicKey sets the JWT public key
|
||||
func WithPublicKey(key string) Option {
|
||||
return func(o *Options) {
|
||||
o.PublicKey = key
|
||||
}
|
||||
}
|
||||
|
||||
// WithPrivateKey sets the JWT private key
|
||||
func WithPrivateKey(key string) Option {
|
||||
return func(o *Options) {
|
||||
o.PrivateKey = key
|
||||
}
|
||||
}
|
||||
|
||||
func NewOptions(opts ...Option) Options {
|
||||
var options Options
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
//set default store
|
||||
if options.Store == nil {
|
||||
options.Store = store.DefaultStore
|
||||
}
|
||||
return 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
|
||||
}
|
||||
|
||||
type GenerateOption func(o *GenerateOptions)
|
||||
|
||||
// WithExpiry for the generated account's token expires
|
||||
func WithExpiry(d time.Duration) GenerateOption {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Expiry = d
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
// NewGenerateOptions from a slice of options
|
||||
func NewGenerateOptions(opts ...GenerateOption) GenerateOptions {
|
||||
var options GenerateOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
//set default Expiry of token
|
||||
if options.Expiry == 0 {
|
||||
options.Expiry = time.Minute * 15
|
||||
}
|
||||
return options
|
||||
}
|
23
auth/token/token.go
Normal file
23
auth/token/token.go
Normal file
@ -0,0 +1,23 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNotFound is returned when a token cannot be found
|
||||
ErrNotFound = errors.New("token not found")
|
||||
// ErrEncodingToken is returned when the service encounters an error during encoding
|
||||
ErrEncodingToken = errors.New("error encoding the token")
|
||||
// ErrInvalidToken is returned when the token provided is not valid
|
||||
ErrInvalidToken = errors.New("invalid token provided")
|
||||
)
|
||||
|
||||
// Provider generates and inspects tokens
|
||||
type Provider interface {
|
||||
Generate(subject string, opts ...GenerateOption) (*auth.Token, error)
|
||||
Inspect(token string) (*auth.Token, error)
|
||||
String() string
|
||||
}
|
@ -70,8 +70,7 @@ import (
|
||||
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"
|
||||
svcAuth "github.com/micro/go-micro/v2/auth/service"
|
||||
storeAuth "github.com/micro/go-micro/v2/auth/store"
|
||||
|
||||
// auth providers
|
||||
@ -271,11 +270,6 @@ var (
|
||||
EnvVars: []string{"MICRO_AUTH_PRIVATE_KEY"},
|
||||
Usage: "Private key for JWT auth (base64 encoded PEM)",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "auth_exclude",
|
||||
EnvVars: []string{"MICRO_AUTH_EXCLUDE"},
|
||||
Usage: "Comma-separated list of endpoints excluded from authentication, e.g. Users.ListUsers",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth_provider",
|
||||
EnvVars: []string{"MICRO_AUTH_PROVIDER"},
|
||||
@ -365,9 +359,8 @@ var (
|
||||
}
|
||||
|
||||
DefaultAuths = map[string]func(...auth.Option) auth.Auth{
|
||||
"service": sAuth.NewAuth,
|
||||
"service": svcAuth.NewAuth,
|
||||
"store": storeAuth.NewAuth,
|
||||
"jwt": jwtAuth.NewAuth,
|
||||
}
|
||||
|
||||
DefaultAuthProviders = map[string]func(...provider.Option) provider.Provider{
|
||||
@ -665,7 +658,7 @@ func (c *cmd) Before(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
if len(ctx.String("auth_token")) > 0 {
|
||||
authOpts = append(authOpts, auth.Token(ctx.String("auth_token")))
|
||||
authOpts = append(authOpts, auth.ServiceToken(ctx.String("auth_token")))
|
||||
}
|
||||
|
||||
if len(ctx.String("auth_public_key")) > 0 {
|
||||
@ -676,10 +669,6 @@ func (c *cmd) Before(ctx *cli.Context) error {
|
||||
authOpts = append(authOpts, auth.PrivateKey(ctx.String("auth_private_key")))
|
||||
}
|
||||
|
||||
if len(ctx.StringSlice("auth_exclude")) > 0 {
|
||||
authOpts = append(authOpts, auth.Exclude(ctx.StringSlice("auth_exclude")...))
|
||||
}
|
||||
|
||||
if name := ctx.String("auth_provider"); len(name) > 0 {
|
||||
p, ok := DefaultAuthProviders[name]
|
||||
if !ok {
|
||||
@ -707,9 +696,7 @@ func (c *cmd) Before(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
if len(authOpts) > 0 {
|
||||
if err := (*c.opts.Auth).Init(authOpts...); err != nil {
|
||||
logger.Fatalf("Error configuring auth: %v", err)
|
||||
}
|
||||
(*c.opts.Auth).Init(authOpts...)
|
||||
}
|
||||
|
||||
if ctx.String("config") == "service" {
|
||||
|
@ -118,7 +118,7 @@ func (s *service) Init(opts ...Option) {
|
||||
// May need to re-read value on change
|
||||
// TODO: should be scoped to micro/auth/token
|
||||
if tk, _ := config.Get("token"); len(tk) > 0 {
|
||||
s.opts.Auth.Init(auth.Token(tk))
|
||||
s.opts.Auth.Init(auth.ServiceToken(tk))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -164,6 +164,11 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper {
|
||||
return h(ctx, req, rsp)
|
||||
}
|
||||
|
||||
// Check for auth service endpoints which should be excluded from auth
|
||||
if strings.HasPrefix(req.Endpoint(), "Auth.") {
|
||||
return h(ctx, req, rsp)
|
||||
}
|
||||
|
||||
// Extract the token if present. Note: if noop is being used
|
||||
// then the token can be blank without erroring
|
||||
var token string
|
||||
@ -177,29 +182,16 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper {
|
||||
}
|
||||
|
||||
// Verify the token
|
||||
account, authErr := a.Verify(token)
|
||||
account, err := a.Inspect(token)
|
||||
if err != nil {
|
||||
return errors.Unauthorized("go.micro.auth", err.Error())
|
||||
}
|
||||
|
||||
// If there is an account, set it in the context
|
||||
if authErr == nil {
|
||||
var err error
|
||||
// There is an account, set it in the context
|
||||
ctx, err = auth.ContextWithAccount(ctx, account)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Return if the user disabled auth on this endpoint
|
||||
for _, e := range a.Options().Exclude {
|
||||
if e == req.Endpoint() {
|
||||
return h(ctx, req, rsp)
|
||||
}
|
||||
}
|
||||
|
||||
// If the authErr is set, prevent the user from calling the endpoint
|
||||
if authErr != nil {
|
||||
return errors.Unauthorized("go.micro.auth", authErr.Error())
|
||||
}
|
||||
|
||||
// The user is authorised, allow the call
|
||||
return h(ctx, req, rsp)
|
||||
|
Loading…
Reference in New Issue
Block a user