v3 refactor (#1868)
* Move to v3 Co-authored-by: Ben Toogood <bentoogood@gmail.com>
This commit is contained in:
@@ -1,85 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultAuth = NewAuth()
|
||||
)
|
||||
|
||||
func NewAuth(opts ...Option) Auth {
|
||||
var options Options
|
||||
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
return &noop{
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
type noop struct {
|
||||
opts Options
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
// Options set for auth
|
||||
func (n *noop) Options() Options {
|
||||
return n.opts
|
||||
}
|
||||
|
||||
// Generate a new account
|
||||
func (n *noop) Generate(id string, opts ...GenerateOption) (*Account, error) {
|
||||
options := NewGenerateOptions(opts...)
|
||||
|
||||
return &Account{
|
||||
ID: id,
|
||||
Secret: options.Secret,
|
||||
Metadata: options.Metadata,
|
||||
Scopes: options.Scopes,
|
||||
Issuer: n.Options().Issuer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Grant access to a resource
|
||||
func (n *noop) Grant(rule *Rule) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Revoke access to a resource
|
||||
func (n *noop) Revoke(rule *Rule) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Rules used to verify requests
|
||||
func (n *noop) Rules(opts ...RulesOption) ([]*Rule, error) {
|
||||
return []*Rule{}, nil
|
||||
}
|
||||
|
||||
// Verify an account has access to a resource
|
||||
func (n *noop) Verify(acc *Account, res *Resource, opts ...VerifyOption) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Inspect a token
|
||||
func (n *noop) Inspect(token string) (*Account, error) {
|
||||
return &Account{ID: uuid.New().String(), Issuer: n.Options().Issuer}, nil
|
||||
}
|
||||
|
||||
// Token generation using an account id and secret
|
||||
func (n *noop) Token(opts ...TokenOption) (*Token, error) {
|
||||
return &Token{}, nil
|
||||
}
|
@@ -5,9 +5,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/util/token"
|
||||
"github.com/micro/go-micro/v2/util/token/jwt"
|
||||
"github.com/micro/go-micro/v3/auth"
|
||||
"github.com/micro/go-micro/v3/util/token"
|
||||
"github.com/micro/go-micro/v3/util/token/jwt"
|
||||
)
|
||||
|
||||
// NewAuth returns a new instance of the Auth service
|
||||
|
81
auth/noop/noop.go
Normal file
81
auth/noop/noop.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package noop
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/v3/auth"
|
||||
)
|
||||
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
var options auth.Options
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
return &noop{
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
type noop struct {
|
||||
opts auth.Options
|
||||
}
|
||||
|
||||
// String returns the name of the implementation
|
||||
func (n *noop) String() string {
|
||||
return "noop"
|
||||
}
|
||||
|
||||
// Init the auth
|
||||
func (n *noop) Init(opts ...auth.Option) {
|
||||
for _, o := range opts {
|
||||
o(&n.opts)
|
||||
}
|
||||
}
|
||||
|
||||
// Options set for auth
|
||||
func (n *noop) Options() auth.Options {
|
||||
return n.opts
|
||||
}
|
||||
|
||||
// Generate a new account
|
||||
func (n *noop) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
|
||||
options := auth.NewGenerateOptions(opts...)
|
||||
|
||||
return &auth.Account{
|
||||
ID: id,
|
||||
Secret: options.Secret,
|
||||
Metadata: options.Metadata,
|
||||
Scopes: options.Scopes,
|
||||
Issuer: n.Options().Issuer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Grant access to a resource
|
||||
func (n *noop) Grant(rule *auth.Rule) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Revoke access to a resource
|
||||
func (n *noop) Revoke(rule *auth.Rule) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Rules used to verify requests
|
||||
func (n *noop) Rules(opts ...auth.RulesOption) ([]*auth.Rule, error) {
|
||||
return []*auth.Rule{}, nil
|
||||
}
|
||||
|
||||
// Verify an account has access to a resource
|
||||
func (n *noop) Verify(acc *auth.Account, res *auth.Resource, opts ...auth.VerifyOption) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Inspect a token
|
||||
func (n *noop) Inspect(token string) (*auth.Account, error) {
|
||||
return &auth.Account{ID: uuid.New().String(), Issuer: n.Options().Issuer}, nil
|
||||
}
|
||||
|
||||
// Token generation using an account id and secret
|
||||
func (n *noop) Token(opts ...auth.TokenOption) (*auth.Token, error) {
|
||||
return &auth.Token{}, nil
|
||||
}
|
@@ -4,8 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
"github.com/micro/go-micro/v3/store"
|
||||
)
|
||||
|
||||
func NewOptions(opts ...Option) Options {
|
||||
@@ -13,10 +12,6 @@ func NewOptions(opts ...Option) Options {
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
if options.Client == nil {
|
||||
options.Client = client.DefaultClient
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
@@ -37,10 +32,10 @@ type Options struct {
|
||||
LoginURL string
|
||||
// Store to back auth
|
||||
Store store.Store
|
||||
// Client to use for RPC
|
||||
Client client.Client
|
||||
// Addrs sets the addresses of auth
|
||||
Addrs []string
|
||||
// Context to store other options
|
||||
Context context.Context
|
||||
}
|
||||
|
||||
type Option func(o *Options)
|
||||
@@ -102,13 +97,6 @@ func LoginURL(url string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithClient sets the client to use when making requests
|
||||
func WithClient(c client.Client) Option {
|
||||
return func(o *Options) {
|
||||
o.Client = c
|
||||
}
|
||||
}
|
||||
|
||||
type GenerateOptions struct {
|
||||
// Metadata associated with the account
|
||||
Metadata map[string]string
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,296 +0,0 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: auth/service/proto/auth.proto
|
||||
|
||||
package go_micro_auth
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
import (
|
||||
context "context"
|
||||
api "github.com/micro/go-micro/v2/api"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ api.Endpoint
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Api Endpoints for Auth service
|
||||
|
||||
func NewAuthEndpoints() []*api.Endpoint {
|
||||
return []*api.Endpoint{}
|
||||
}
|
||||
|
||||
// Client API for Auth service
|
||||
|
||||
type AuthService interface {
|
||||
Generate(ctx context.Context, in *GenerateRequest, opts ...client.CallOption) (*GenerateResponse, error)
|
||||
Inspect(ctx context.Context, in *InspectRequest, opts ...client.CallOption) (*InspectResponse, error)
|
||||
Token(ctx context.Context, in *TokenRequest, opts ...client.CallOption) (*TokenResponse, error)
|
||||
}
|
||||
|
||||
type authService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewAuthService(name string, c client.Client) AuthService {
|
||||
return &authService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *authService) Generate(ctx context.Context, in *GenerateRequest, opts ...client.CallOption) (*GenerateResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Generate", in)
|
||||
out := new(GenerateResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authService) 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) Token(ctx context.Context, in *TokenRequest, opts ...client.CallOption) (*TokenResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Token", in)
|
||||
out := new(TokenResponse)
|
||||
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
|
||||
Inspect(context.Context, *InspectRequest, *InspectResponse) error
|
||||
Token(context.Context, *TokenRequest, *TokenResponse) error
|
||||
}
|
||||
|
||||
func RegisterAuthHandler(s server.Server, hdlr AuthHandler, opts ...server.HandlerOption) error {
|
||||
type auth interface {
|
||||
Generate(ctx context.Context, in *GenerateRequest, out *GenerateResponse) error
|
||||
Inspect(ctx context.Context, in *InspectRequest, out *InspectResponse) error
|
||||
Token(ctx context.Context, in *TokenRequest, out *TokenResponse) error
|
||||
}
|
||||
type Auth struct {
|
||||
auth
|
||||
}
|
||||
h := &authHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Auth{h}, opts...))
|
||||
}
|
||||
|
||||
type authHandler struct {
|
||||
AuthHandler
|
||||
}
|
||||
|
||||
func (h *authHandler) Generate(ctx context.Context, in *GenerateRequest, out *GenerateResponse) error {
|
||||
return h.AuthHandler.Generate(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Inspect(ctx context.Context, in *InspectRequest, out *InspectResponse) error {
|
||||
return h.AuthHandler.Inspect(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Token(ctx context.Context, in *TokenRequest, out *TokenResponse) error {
|
||||
return h.AuthHandler.Token(ctx, in, out)
|
||||
}
|
||||
|
||||
// Api Endpoints for Accounts service
|
||||
|
||||
func NewAccountsEndpoints() []*api.Endpoint {
|
||||
return []*api.Endpoint{}
|
||||
}
|
||||
|
||||
// Client API for Accounts service
|
||||
|
||||
type AccountsService interface {
|
||||
List(ctx context.Context, in *ListAccountsRequest, opts ...client.CallOption) (*ListAccountsResponse, error)
|
||||
Delete(ctx context.Context, in *DeleteAccountRequest, opts ...client.CallOption) (*DeleteAccountResponse, error)
|
||||
}
|
||||
|
||||
type accountsService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewAccountsService(name string, c client.Client) AccountsService {
|
||||
return &accountsService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *accountsService) List(ctx context.Context, in *ListAccountsRequest, opts ...client.CallOption) (*ListAccountsResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Accounts.List", in)
|
||||
out := new(ListAccountsResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *accountsService) Delete(ctx context.Context, in *DeleteAccountRequest, opts ...client.CallOption) (*DeleteAccountResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Accounts.Delete", in)
|
||||
out := new(DeleteAccountResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Accounts service
|
||||
|
||||
type AccountsHandler interface {
|
||||
List(context.Context, *ListAccountsRequest, *ListAccountsResponse) error
|
||||
Delete(context.Context, *DeleteAccountRequest, *DeleteAccountResponse) error
|
||||
}
|
||||
|
||||
func RegisterAccountsHandler(s server.Server, hdlr AccountsHandler, opts ...server.HandlerOption) error {
|
||||
type accounts interface {
|
||||
List(ctx context.Context, in *ListAccountsRequest, out *ListAccountsResponse) error
|
||||
Delete(ctx context.Context, in *DeleteAccountRequest, out *DeleteAccountResponse) error
|
||||
}
|
||||
type Accounts struct {
|
||||
accounts
|
||||
}
|
||||
h := &accountsHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Accounts{h}, opts...))
|
||||
}
|
||||
|
||||
type accountsHandler struct {
|
||||
AccountsHandler
|
||||
}
|
||||
|
||||
func (h *accountsHandler) List(ctx context.Context, in *ListAccountsRequest, out *ListAccountsResponse) error {
|
||||
return h.AccountsHandler.List(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *accountsHandler) Delete(ctx context.Context, in *DeleteAccountRequest, out *DeleteAccountResponse) error {
|
||||
return h.AccountsHandler.Delete(ctx, in, out)
|
||||
}
|
||||
|
||||
// Api Endpoints for Rules service
|
||||
|
||||
func NewRulesEndpoints() []*api.Endpoint {
|
||||
return []*api.Endpoint{}
|
||||
}
|
||||
|
||||
// Client API for Rules service
|
||||
|
||||
type RulesService interface {
|
||||
Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error)
|
||||
Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error)
|
||||
List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error)
|
||||
}
|
||||
|
||||
type rulesService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewRulesService(name string, c client.Client) RulesService {
|
||||
return &rulesService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *rulesService) Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Rules.Create", in)
|
||||
out := new(CreateResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *rulesService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Rules.Delete", in)
|
||||
out := new(DeleteResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *rulesService) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Rules.List", in)
|
||||
out := new(ListResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Rules service
|
||||
|
||||
type RulesHandler interface {
|
||||
Create(context.Context, *CreateRequest, *CreateResponse) error
|
||||
Delete(context.Context, *DeleteRequest, *DeleteResponse) error
|
||||
List(context.Context, *ListRequest, *ListResponse) error
|
||||
}
|
||||
|
||||
func RegisterRulesHandler(s server.Server, hdlr RulesHandler, opts ...server.HandlerOption) error {
|
||||
type rules interface {
|
||||
Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error
|
||||
Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error
|
||||
List(ctx context.Context, in *ListRequest, out *ListResponse) error
|
||||
}
|
||||
type Rules struct {
|
||||
rules
|
||||
}
|
||||
h := &rulesHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Rules{h}, opts...))
|
||||
}
|
||||
|
||||
type rulesHandler struct {
|
||||
RulesHandler
|
||||
}
|
||||
|
||||
func (h *rulesHandler) Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error {
|
||||
return h.RulesHandler.Create(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *rulesHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error {
|
||||
return h.RulesHandler.Delete(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *rulesHandler) List(ctx context.Context, in *ListRequest, out *ListResponse) error {
|
||||
return h.RulesHandler.List(ctx, in, out)
|
||||
}
|
@@ -1,148 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package go.micro.auth;
|
||||
|
||||
service Auth {
|
||||
rpc Generate(GenerateRequest) returns (GenerateResponse) {};
|
||||
rpc Inspect(InspectRequest) returns (InspectResponse) {};
|
||||
rpc Token(TokenRequest) returns (TokenResponse) {};
|
||||
}
|
||||
|
||||
service Accounts {
|
||||
rpc List(ListAccountsRequest) returns (ListAccountsResponse) {};
|
||||
rpc Delete(DeleteAccountRequest) returns (DeleteAccountResponse) {};
|
||||
}
|
||||
|
||||
service Rules {
|
||||
rpc Create(CreateRequest) returns (CreateResponse) {};
|
||||
rpc Delete(DeleteRequest) returns (DeleteResponse) {};
|
||||
rpc List(ListRequest) returns (ListResponse) {};
|
||||
}
|
||||
|
||||
message ListAccountsRequest {
|
||||
Options options = 1;
|
||||
}
|
||||
|
||||
message ListAccountsResponse {
|
||||
repeated Account accounts = 1;
|
||||
}
|
||||
|
||||
message DeleteAccountRequest {
|
||||
string id = 1;
|
||||
Options options = 2;
|
||||
}
|
||||
|
||||
message DeleteAccountResponse {}
|
||||
|
||||
message Token {
|
||||
string access_token = 1;
|
||||
string refresh_token = 2;
|
||||
int64 created = 3;
|
||||
int64 expiry = 4;
|
||||
}
|
||||
|
||||
message Account {
|
||||
string id = 1;
|
||||
string type = 2;
|
||||
map<string, string> metadata = 4;
|
||||
repeated string scopes = 5;
|
||||
string issuer = 6;
|
||||
string secret = 7;
|
||||
}
|
||||
|
||||
message Resource{
|
||||
string name = 1;
|
||||
string type = 2;
|
||||
string endpoint = 3;
|
||||
}
|
||||
|
||||
message GenerateRequest {
|
||||
string id = 1;
|
||||
map<string, string> metadata = 3;
|
||||
repeated string scopes = 4;
|
||||
string secret = 5;
|
||||
string type = 6;
|
||||
string provider = 7;
|
||||
Options options = 8;
|
||||
}
|
||||
|
||||
message GenerateResponse {
|
||||
Account account = 1;
|
||||
}
|
||||
|
||||
message GrantRequest {
|
||||
string scope = 1;
|
||||
Resource resource = 2;
|
||||
Options options = 3;
|
||||
}
|
||||
|
||||
message GrantResponse {}
|
||||
|
||||
message RevokeRequest {
|
||||
string scope = 1;
|
||||
Resource resource = 2;
|
||||
Options options = 3;
|
||||
}
|
||||
|
||||
message RevokeResponse {}
|
||||
|
||||
message InspectRequest {
|
||||
string token = 1;
|
||||
Options options = 2;
|
||||
}
|
||||
|
||||
message InspectResponse {
|
||||
Account account = 1;
|
||||
}
|
||||
|
||||
message TokenRequest {
|
||||
string id = 1;
|
||||
string secret = 2;
|
||||
string refresh_token = 3;
|
||||
int64 token_expiry = 4;
|
||||
Options options = 5;
|
||||
}
|
||||
|
||||
message TokenResponse {
|
||||
Token token = 1;
|
||||
}
|
||||
|
||||
enum Access {
|
||||
UNKNOWN = 0;
|
||||
GRANTED = 1;
|
||||
DENIED = 2;
|
||||
}
|
||||
|
||||
message Rule {
|
||||
string id = 1;
|
||||
string scope = 2;
|
||||
Resource resource = 3;
|
||||
Access access = 4;
|
||||
int32 priority = 5;
|
||||
}
|
||||
|
||||
message Options {
|
||||
string namespace = 1;
|
||||
}
|
||||
|
||||
message CreateRequest {
|
||||
Rule rule = 1;
|
||||
Options options = 2;
|
||||
}
|
||||
|
||||
message CreateResponse {}
|
||||
|
||||
message DeleteRequest {
|
||||
string id = 1;
|
||||
Options options = 2;
|
||||
}
|
||||
|
||||
message DeleteResponse {}
|
||||
|
||||
message ListRequest {
|
||||
Options options = 2;
|
||||
}
|
||||
|
||||
message ListResponse {
|
||||
repeated Rule rules = 1;
|
||||
}
|
@@ -1,325 +0,0 @@
|
||||
// Package servie is a micro service implementation of the auth interface
|
||||
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/client"
|
||||
"github.com/micro/go-micro/v2/util/token"
|
||||
"github.com/micro/go-micro/v2/util/token/jwt"
|
||||
)
|
||||
|
||||
// svc is the service implementation of the Auth interface
|
||||
type svcAuth struct {
|
||||
options auth.Options
|
||||
auth pb.AuthService
|
||||
rules pb.RulesService
|
||||
token token.Provider
|
||||
}
|
||||
|
||||
func (s *svcAuth) String() string {
|
||||
return "service"
|
||||
}
|
||||
|
||||
func (s *svcAuth) Init(opts ...auth.Option) {
|
||||
for _, o := range opts {
|
||||
o(&s.options)
|
||||
}
|
||||
|
||||
s.auth = pb.NewAuthService("go.micro.auth", s.options.Client)
|
||||
s.rules = pb.NewRulesService("go.micro.auth", s.options.Client)
|
||||
|
||||
s.setupJWT()
|
||||
}
|
||||
|
||||
func (s *svcAuth) Options() auth.Options {
|
||||
return s.options
|
||||
}
|
||||
|
||||
// Generate a new account
|
||||
func (s *svcAuth) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
|
||||
options := auth.NewGenerateOptions(opts...)
|
||||
if len(options.Issuer) == 0 {
|
||||
options.Issuer = s.options.Issuer
|
||||
}
|
||||
|
||||
// we have the JWT private key and generate ourselves an account
|
||||
if len(s.options.PrivateKey) > 0 {
|
||||
acc := &auth.Account{
|
||||
ID: id,
|
||||
Type: options.Type,
|
||||
Scopes: options.Scopes,
|
||||
Metadata: options.Metadata,
|
||||
Issuer: options.Issuer,
|
||||
}
|
||||
|
||||
tok, err := s.token.Generate(acc, token.WithExpiry(time.Hour*24*365))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// when using JWTs, the account secret is the JWT's token. This
|
||||
// can be used as an argument in the Token method.
|
||||
acc.Secret = tok.Token
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
rsp, err := s.auth.Generate(context.TODO(), &pb.GenerateRequest{
|
||||
Id: id,
|
||||
Type: options.Type,
|
||||
Secret: options.Secret,
|
||||
Scopes: options.Scopes,
|
||||
Metadata: options.Metadata,
|
||||
Provider: options.Provider,
|
||||
Options: &pb.Options{
|
||||
Namespace: options.Issuer,
|
||||
},
|
||||
}, s.callOpts()...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return serializeAccount(rsp.Account), nil
|
||||
}
|
||||
|
||||
// Grant access to a resource
|
||||
func (s *svcAuth) Grant(rule *auth.Rule) error {
|
||||
access := pb.Access_UNKNOWN
|
||||
if rule.Access == auth.AccessGranted {
|
||||
access = pb.Access_GRANTED
|
||||
} else if rule.Access == auth.AccessDenied {
|
||||
access = pb.Access_DENIED
|
||||
}
|
||||
|
||||
_, err := s.rules.Create(context.TODO(), &pb.CreateRequest{
|
||||
Rule: &pb.Rule{
|
||||
Id: rule.ID,
|
||||
Scope: rule.Scope,
|
||||
Priority: rule.Priority,
|
||||
Access: access,
|
||||
Resource: &pb.Resource{
|
||||
Type: rule.Resource.Type,
|
||||
Name: rule.Resource.Name,
|
||||
Endpoint: rule.Resource.Endpoint,
|
||||
},
|
||||
},
|
||||
Options: &pb.Options{
|
||||
Namespace: s.Options().Issuer,
|
||||
},
|
||||
}, s.callOpts()...)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Revoke access to a resource
|
||||
func (s *svcAuth) Revoke(rule *auth.Rule) error {
|
||||
_, err := s.rules.Delete(context.TODO(), &pb.DeleteRequest{
|
||||
Id: rule.ID, Options: &pb.Options{
|
||||
Namespace: s.Options().Issuer,
|
||||
},
|
||||
}, s.callOpts()...)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *svcAuth) Rules(opts ...auth.RulesOption) ([]*auth.Rule, error) {
|
||||
var options auth.RulesOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
if options.Context == nil {
|
||||
options.Context = context.TODO()
|
||||
}
|
||||
if len(options.Namespace) == 0 {
|
||||
options.Namespace = s.options.Issuer
|
||||
}
|
||||
|
||||
callOpts := append(s.callOpts(), client.WithCache(time.Second*30))
|
||||
rsp, err := s.rules.List(options.Context, &pb.ListRequest{
|
||||
Options: &pb.Options{Namespace: options.Namespace},
|
||||
}, callOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules := make([]*auth.Rule, len(rsp.Rules))
|
||||
for i, r := range rsp.Rules {
|
||||
rules[i] = serializeRule(r)
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
// Verify an account has access to a resource
|
||||
func (s *svcAuth) Verify(acc *auth.Account, res *auth.Resource, opts ...auth.VerifyOption) error {
|
||||
var options auth.VerifyOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
rs, err := s.Rules(
|
||||
auth.RulesContext(options.Context),
|
||||
auth.RulesNamespace(options.Namespace),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return auth.VerifyAccess(rs, acc, res)
|
||||
}
|
||||
|
||||
// Inspect a token
|
||||
func (s *svcAuth) Inspect(token string) (*auth.Account, error) {
|
||||
// try to decode JWT locally and fall back to srv if an error occurs
|
||||
if len(strings.Split(token, ".")) == 3 && len(s.options.PublicKey) > 0 {
|
||||
return s.token.Inspect(token)
|
||||
}
|
||||
|
||||
// the token is not a JWT or we do not have the keys to decode it,
|
||||
// fall back to the auth service
|
||||
rsp, err := s.auth.Inspect(context.TODO(), &pb.InspectRequest{
|
||||
Token: token, Options: &pb.Options{Namespace: s.Options().Issuer},
|
||||
}, s.callOpts()...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return serializeAccount(rsp.Account), nil
|
||||
}
|
||||
|
||||
// Token generation using an account ID and secret
|
||||
func (s *svcAuth) Token(opts ...auth.TokenOption) (*auth.Token, error) {
|
||||
options := auth.NewTokenOptions(opts...)
|
||||
if len(options.Issuer) == 0 {
|
||||
options.Issuer = s.options.Issuer
|
||||
}
|
||||
|
||||
// we have the JWT private key and refresh accounts locally
|
||||
if len(s.options.PrivateKey) > 0 {
|
||||
tok := options.RefreshToken
|
||||
if len(options.Secret) > 0 {
|
||||
tok = options.Secret
|
||||
}
|
||||
|
||||
acc, err := s.token.Inspect(tok)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
token, err := s.token.Generate(acc, token.WithExpiry(options.Expiry))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &auth.Token{
|
||||
Expiry: token.Expiry,
|
||||
AccessToken: token.Token,
|
||||
RefreshToken: tok,
|
||||
}, nil
|
||||
}
|
||||
|
||||
rsp, err := s.auth.Token(context.Background(), &pb.TokenRequest{
|
||||
Id: options.ID,
|
||||
Secret: options.Secret,
|
||||
RefreshToken: options.RefreshToken,
|
||||
TokenExpiry: int64(options.Expiry.Seconds()),
|
||||
Options: &pb.Options{
|
||||
Namespace: options.Issuer,
|
||||
},
|
||||
}, s.callOpts()...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return serializeToken(rsp.Token), nil
|
||||
}
|
||||
|
||||
func serializeToken(t *pb.Token) *auth.Token {
|
||||
return &auth.Token{
|
||||
AccessToken: t.AccessToken,
|
||||
RefreshToken: t.RefreshToken,
|
||||
Created: time.Unix(t.Created, 0),
|
||||
Expiry: time.Unix(t.Expiry, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func serializeAccount(a *pb.Account) *auth.Account {
|
||||
return &auth.Account{
|
||||
ID: a.Id,
|
||||
Secret: a.Secret,
|
||||
Issuer: a.Issuer,
|
||||
Metadata: a.Metadata,
|
||||
Scopes: a.Scopes,
|
||||
}
|
||||
}
|
||||
|
||||
func serializeRule(r *pb.Rule) *auth.Rule {
|
||||
var access auth.Access
|
||||
if r.Access == pb.Access_GRANTED {
|
||||
access = auth.AccessGranted
|
||||
} else {
|
||||
access = auth.AccessDenied
|
||||
}
|
||||
|
||||
return &auth.Rule{
|
||||
ID: r.Id,
|
||||
Scope: r.Scope,
|
||||
Access: access,
|
||||
Priority: r.Priority,
|
||||
Resource: &auth.Resource{
|
||||
Type: r.Resource.Type,
|
||||
Name: r.Resource.Name,
|
||||
Endpoint: r.Resource.Endpoint,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *svcAuth) callOpts() []client.CallOption {
|
||||
return []client.CallOption{
|
||||
client.WithAddress(s.options.Addrs...),
|
||||
}
|
||||
}
|
||||
|
||||
// NewAuth returns a new instance of the Auth service
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
options := auth.NewOptions(opts...)
|
||||
if options.Client == nil {
|
||||
options.Client = client.DefaultClient
|
||||
}
|
||||
if len(options.Addrs) == 0 {
|
||||
options.Addrs = []string{"127.0.0.1:8010"}
|
||||
}
|
||||
|
||||
service := &svcAuth{
|
||||
auth: pb.NewAuthService("go.micro.auth", options.Client),
|
||||
rules: pb.NewRulesService("go.micro.auth", options.Client),
|
||||
options: options,
|
||||
}
|
||||
service.setupJWT()
|
||||
|
||||
return service
|
||||
}
|
||||
|
||||
func (s *svcAuth) setupJWT() {
|
||||
tokenOpts := []token.Option{}
|
||||
|
||||
// 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 {
|
||||
tokenOpts = append(tokenOpts, token.WithPublicKey(key))
|
||||
}
|
||||
|
||||
// if we have a JWT private key passed as an option,
|
||||
// we can generate accounts locally and not have to make
|
||||
// an RPC call, this is used for micro clients such as
|
||||
// api, web, proxy.
|
||||
if key := s.options.PrivateKey; len(key) > 0 {
|
||||
tokenOpts = append(tokenOpts, token.WithPrivateKey(key))
|
||||
}
|
||||
|
||||
s.token = jwt.NewTokenProvider(tokenOpts...)
|
||||
}
|
Reference in New Issue
Block a user