Merge pull request #1635 from micro/auth-fixes
Auth: Move token generation logic out the client wrappers
This commit is contained in:
		| @@ -2,6 +2,7 @@ package jwt | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"sync" | 	"sync" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/v2/auth" | 	"github.com/micro/go-micro/v2/auth" | ||||||
| 	"github.com/micro/go-micro/v2/auth/token" | 	"github.com/micro/go-micro/v2/auth/token" | ||||||
| @@ -176,15 +177,20 @@ func (j *jwt) Token(opts ...auth.TokenOption) (*auth.Token, error) { | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	tok, err := j.jwt.Generate(account, token.WithExpiry(options.Expiry)) | 	access, err := j.jwt.Generate(account, token.WithExpiry(options.Expiry)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	refresh, err := j.jwt.Generate(account, token.WithExpiry(options.Expiry+time.Hour)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &auth.Token{ | 	return &auth.Token{ | ||||||
| 		Created:      tok.Created, | 		Created:      access.Created, | ||||||
| 		Expiry:       tok.Expiry, | 		Expiry:       access.Expiry, | ||||||
| 		AccessToken:  tok.Token, | 		AccessToken:  access.Token, | ||||||
| 		RefreshToken: tok.Token, | 		RefreshToken: refresh.Token, | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -23,7 +23,6 @@ type svc struct { | |||||||
| 	auth    pb.AuthService | 	auth    pb.AuthService | ||||||
| 	rule    pb.RulesService | 	rule    pb.RulesService | ||||||
| 	jwt     token.Provider | 	jwt     token.Provider | ||||||
| 	addrs   []string |  | ||||||
|  |  | ||||||
| 	rules []*pb.Rule | 	rules []*pb.Rule | ||||||
| 	sync.Mutex | 	sync.Mutex | ||||||
| @@ -71,7 +70,7 @@ func (s *svc) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, e | |||||||
| 		Metadata:  options.Metadata, | 		Metadata:  options.Metadata, | ||||||
| 		Provider:  options.Provider, | 		Provider:  options.Provider, | ||||||
| 		Namespace: options.Namespace, | 		Namespace: options.Namespace, | ||||||
| 	}, client.WithAddress(s.addrs...)) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @@ -90,7 +89,7 @@ func (s *svc) Grant(role string, res *auth.Resource) error { | |||||||
| 			Name:      res.Name, | 			Name:      res.Name, | ||||||
| 			Endpoint:  res.Endpoint, | 			Endpoint:  res.Endpoint, | ||||||
| 		}, | 		}, | ||||||
| 	}, client.WithAddress(s.addrs...)) | 	}) | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -105,7 +104,7 @@ func (s *svc) Revoke(role string, res *auth.Resource) error { | |||||||
| 			Name:      res.Name, | 			Name:      res.Name, | ||||||
| 			Endpoint:  res.Endpoint, | 			Endpoint:  res.Endpoint, | ||||||
| 		}, | 		}, | ||||||
| 	}, client.WithAddress(s.addrs...)) | 	}) | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -175,7 +174,7 @@ func (s *svc) Inspect(token string) (*auth.Account, error) { | |||||||
|  |  | ||||||
| 	// the token is not a JWT or we do not have the keys to decode it, | 	// the token is not a JWT or we do not have the keys to decode it, | ||||||
| 	// fall back to the auth service | 	// fall back to the auth service | ||||||
| 	rsp, err := s.auth.Inspect(context.TODO(), &pb.InspectRequest{Token: token}, client.WithAddress(s.addrs...)) | 	rsp, err := s.auth.Inspect(context.TODO(), &pb.InspectRequest{Token: token}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @@ -191,7 +190,7 @@ func (s *svc) Token(opts ...auth.TokenOption) (*auth.Token, error) { | |||||||
| 		Secret:       options.Secret, | 		Secret:       options.Secret, | ||||||
| 		RefreshToken: options.RefreshToken, | 		RefreshToken: options.RefreshToken, | ||||||
| 		TokenExpiry:  int64(options.Expiry.Seconds()), | 		TokenExpiry:  int64(options.Expiry.Seconds()), | ||||||
| 	}, client.WithAddress(s.addrs...)) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @@ -256,7 +255,7 @@ func (s *svc) listRules(filters ...string) []*pb.Rule { | |||||||
|  |  | ||||||
| // loadRules retrieves the rules from the auth service | // loadRules retrieves the rules from the auth service | ||||||
| func (s *svc) loadRules() { | func (s *svc) loadRules() { | ||||||
| 	rsp, err := s.rule.List(context.TODO(), &pb.ListRequest{}, client.WithAddress(s.addrs...)) | 	rsp, err := s.rule.List(context.TODO(), &pb.ListRequest{}) | ||||||
| 	s.Lock() | 	s.Lock() | ||||||
| 	defer s.Unlock() | 	defer s.Unlock() | ||||||
|  |  | ||||||
| @@ -301,21 +300,14 @@ func serializeAccount(a *pb.Account) *auth.Account { | |||||||
| // NewAuth returns a new instance of the Auth service | // NewAuth returns a new instance of the Auth service | ||||||
| func NewAuth(opts ...auth.Option) auth.Auth { | func NewAuth(opts ...auth.Option) auth.Auth { | ||||||
| 	options := auth.NewOptions(opts...) | 	options := auth.NewOptions(opts...) | ||||||
|  |  | ||||||
| 	if options.Client == nil { | 	if options.Client == nil { | ||||||
| 		options.Client = client.DefaultClient | 		options.Client = client.DefaultClient | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	addrs := options.Addrs |  | ||||||
| 	// if len(addrs) == 0 { |  | ||||||
| 	// 	addrs = []string{"127.0.0.1:8010"} |  | ||||||
| 	// } |  | ||||||
|  |  | ||||||
| 	service := &svc{ | 	service := &svc{ | ||||||
| 		auth:    pb.NewAuthService("go.micro.auth", options.Client), | 		auth:    pb.NewAuthService("go.micro.auth", options.Client), | ||||||
| 		rule:    pb.NewRulesService("go.micro.auth", options.Client), | 		rule:    pb.NewRulesService("go.micro.auth", options.Client), | ||||||
| 		options: options, | 		options: options, | ||||||
| 		addrs:   addrs, |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// load rules periodically from the auth service | 	// load rules periodically from the auth service | ||||||
| @@ -323,9 +315,9 @@ func NewAuth(opts ...auth.Option) auth.Auth { | |||||||
| 		ruleTimer := time.NewTicker(time.Second * 30) | 		ruleTimer := time.NewTicker(time.Second * 30) | ||||||
|  |  | ||||||
| 		for { | 		for { | ||||||
|  | 			<-ruleTimer.C | ||||||
| 			time.Sleep(jitter.Do(time.Second * 5)) | 			time.Sleep(jitter.Do(time.Second * 5)) | ||||||
| 			service.loadRules() | 			service.loadRules() | ||||||
| 			<-ruleTimer.C |  | ||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ import ( | |||||||
| 	"github.com/micro/go-micro/v2/auth/provider" | 	"github.com/micro/go-micro/v2/auth/provider" | ||||||
| 	"github.com/micro/go-micro/v2/broker" | 	"github.com/micro/go-micro/v2/broker" | ||||||
| 	"github.com/micro/go-micro/v2/client" | 	"github.com/micro/go-micro/v2/client" | ||||||
|  | 	"github.com/micro/go-micro/v2/client/grpc" | ||||||
| 	"github.com/micro/go-micro/v2/client/selector" | 	"github.com/micro/go-micro/v2/client/selector" | ||||||
| 	"github.com/micro/go-micro/v2/config" | 	"github.com/micro/go-micro/v2/config" | ||||||
| 	configSrc "github.com/micro/go-micro/v2/config/source" | 	configSrc "github.com/micro/go-micro/v2/config/source" | ||||||
| @@ -21,10 +22,12 @@ import ( | |||||||
| 	"github.com/micro/go-micro/v2/debug/trace" | 	"github.com/micro/go-micro/v2/debug/trace" | ||||||
| 	"github.com/micro/go-micro/v2/logger" | 	"github.com/micro/go-micro/v2/logger" | ||||||
| 	"github.com/micro/go-micro/v2/registry" | 	"github.com/micro/go-micro/v2/registry" | ||||||
|  | 	registrySrv "github.com/micro/go-micro/v2/registry/service" | ||||||
| 	"github.com/micro/go-micro/v2/runtime" | 	"github.com/micro/go-micro/v2/runtime" | ||||||
| 	"github.com/micro/go-micro/v2/server" | 	"github.com/micro/go-micro/v2/server" | ||||||
| 	"github.com/micro/go-micro/v2/store" | 	"github.com/micro/go-micro/v2/store" | ||||||
| 	"github.com/micro/go-micro/v2/transport" | 	"github.com/micro/go-micro/v2/transport" | ||||||
|  | 	"github.com/micro/go-micro/v2/util/wrapper" | ||||||
|  |  | ||||||
| 	// clients | 	// clients | ||||||
| 	cgrpc "github.com/micro/go-micro/v2/client/grpc" | 	cgrpc "github.com/micro/go-micro/v2/client/grpc" | ||||||
| @@ -468,6 +471,10 @@ func (c *cmd) Before(ctx *cli.Context) error { | |||||||
| 	var serverOpts []server.Option | 	var serverOpts []server.Option | ||||||
| 	var clientOpts []client.Option | 	var clientOpts []client.Option | ||||||
|  |  | ||||||
|  | 	// setup a client to use when calling the runtime | ||||||
|  | 	authFn := func() auth.Auth { return *c.opts.Auth } | ||||||
|  | 	microClient := wrapper.AuthClient(authFn, grpc.NewClient()) | ||||||
|  |  | ||||||
| 	// Set the store | 	// Set the store | ||||||
| 	if name := ctx.String("store"); len(name) > 0 { | 	if name := ctx.String("store"); len(name) > 0 { | ||||||
| 		s, ok := c.opts.Stores[name] | 		s, ok := c.opts.Stores[name] | ||||||
| @@ -475,7 +482,7 @@ func (c *cmd) Before(ctx *cli.Context) error { | |||||||
| 			return fmt.Errorf("Unsupported store: %s", name) | 			return fmt.Errorf("Unsupported store: %s", name) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		*c.opts.Store = s() | 		*c.opts.Store = s(store.WithClient(microClient)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Set the runtime | 	// Set the runtime | ||||||
| @@ -485,7 +492,7 @@ func (c *cmd) Before(ctx *cli.Context) error { | |||||||
| 			return fmt.Errorf("Unsupported runtime: %s", name) | 			return fmt.Errorf("Unsupported runtime: %s", name) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		*c.opts.Runtime = r() | 		*c.opts.Runtime = r(runtime.WithClient(microClient)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Set the tracer | 	// Set the tracer | ||||||
| @@ -504,8 +511,7 @@ func (c *cmd) Before(ctx *cli.Context) error { | |||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return fmt.Errorf("Unsupported auth: %s", name) | 			return fmt.Errorf("Unsupported auth: %s", name) | ||||||
| 		} | 		} | ||||||
|  | 		*c.opts.Auth = a(auth.WithClient(microClient)) | ||||||
| 		*c.opts.Auth = a() |  | ||||||
| 		serverOpts = append(serverOpts, server.Auth(*c.opts.Auth)) | 		serverOpts = append(serverOpts, server.Auth(*c.opts.Auth)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -554,7 +560,7 @@ func (c *cmd) Before(ctx *cli.Context) error { | |||||||
| 			return fmt.Errorf("Registry %s not found", name) | 			return fmt.Errorf("Registry %s not found", name) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		*c.opts.Registry = r() | 		*c.opts.Registry = r(registrySrv.WithClient(microClient)) | ||||||
| 		serverOpts = append(serverOpts, server.Registry(*c.opts.Registry)) | 		serverOpts = append(serverOpts, server.Registry(*c.opts.Registry)) | ||||||
| 		clientOpts = append(clientOpts, client.Registry(*c.opts.Registry)) | 		clientOpts = append(clientOpts, client.Registry(*c.opts.Registry)) | ||||||
|  |  | ||||||
| @@ -725,7 +731,7 @@ func (c *cmd) Before(ctx *cli.Context) error { | |||||||
| 	(*c.opts.Auth).Init(authOpts...) | 	(*c.opts.Auth).Init(authOpts...) | ||||||
|  |  | ||||||
| 	if ctx.String("config") == "service" { | 	if ctx.String("config") == "service" { | ||||||
| 		opt := config.WithSource(configSrv.NewSource(configSrc.WithClient(*c.opts.Client))) | 		opt := config.WithSource(configSrv.NewSource(configSrc.WithClient(microClient))) | ||||||
| 		if err := (*c.opts.Config).Init(opt); err != nil { | 		if err := (*c.opts.Config).Init(opt); err != nil { | ||||||
| 			logger.Fatalf("Error configuring config: %v", err) | 			logger.Fatalf("Error configuring config: %v", err) | ||||||
| 		} | 		} | ||||||
|   | |||||||
							
								
								
									
										92
									
								
								service.go
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								service.go
									
									
									
									
									
								
							| @@ -7,6 +7,7 @@ import ( | |||||||
| 	rtime "runtime" | 	rtime "runtime" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/micro/go-micro/v2/auth" | 	"github.com/micro/go-micro/v2/auth" | ||||||
| 	"github.com/micro/go-micro/v2/client" | 	"github.com/micro/go-micro/v2/client" | ||||||
| @@ -42,7 +43,7 @@ func newService(opts ...Option) Service { | |||||||
| 	// wrap client to inject From-Service header on any calls | 	// wrap client to inject From-Service header on any calls | ||||||
| 	options.Client = wrapper.FromService(serviceName, options.Client) | 	options.Client = wrapper.FromService(serviceName, options.Client) | ||||||
| 	options.Client = wrapper.TraceCall(serviceName, trace.DefaultTracer, options.Client) | 	options.Client = wrapper.TraceCall(serviceName, trace.DefaultTracer, options.Client) | ||||||
| 	options.Client = wrapper.AuthClient(serviceName, options.Server.Options().Id, authFn, options.Client) | 	options.Client = wrapper.AuthClient(authFn, options.Client) | ||||||
|  |  | ||||||
| 	// wrap the server to provide handler stats | 	// wrap the server to provide handler stats | ||||||
| 	options.Server.Init( | 	options.Server.Init( | ||||||
| @@ -51,12 +52,6 @@ func newService(opts ...Option) Service { | |||||||
| 		server.WrapHandler(wrapper.AuthHandler(authFn)), | 		server.WrapHandler(wrapper.AuthHandler(authFn)), | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	// set the client in the service implementations |  | ||||||
| 	// options.Auth.Init(auth.WithClient(options.Client)) |  | ||||||
| 	// options.Registry.Init(registrySrv.WithClient(options.Client)) |  | ||||||
| 	// options.Runtime.Init(runtime.WithClient(options.Client)) |  | ||||||
| 	// options.Store.Init(store.WithClient(options.Client)) |  | ||||||
|  |  | ||||||
| 	// set opts | 	// set opts | ||||||
| 	service.opts = options | 	service.opts = options | ||||||
|  |  | ||||||
| @@ -119,15 +114,6 @@ func (s *service) Init(opts ...Option) { | |||||||
| 		// Explicitly set the table name to the service name | 		// Explicitly set the table name to the service name | ||||||
| 		name := s.opts.Cmd.App().Name | 		name := s.opts.Cmd.App().Name | ||||||
| 		s.opts.Store.Init(store.Table(name)) | 		s.opts.Store.Init(store.Table(name)) | ||||||
|  |  | ||||||
| 		// Reset the clients for the micro services, this is done |  | ||||||
| 		// previously in newService for micro (since init is never called) |  | ||||||
| 		// however it needs to be done again here since for normal go-micro |  | ||||||
| 		// services the implementation may have changed by CLI flags. |  | ||||||
| 		// s.opts.Auth.Init(auth.WithClient(s.Client())) |  | ||||||
| 		// s.opts.Registry.Init(registrySrv.WithClient(s.Client())) |  | ||||||
| 		// s.opts.Runtime.Init(runtime.WithClient(s.Client())) |  | ||||||
| 		// s.opts.Store.Init(store.WithClient(s.Client())) |  | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -240,25 +226,71 @@ func (s *service) Run() error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (s *service) generateAccount() error { | func (s *service) generateAccount() error { | ||||||
| 	// generate a new auth account for the service | 	// extract the account creds from options, these can be set by flags | ||||||
| 	name := fmt.Sprintf("%v-%v", s.Name(), s.Server().Options().Id) | 	accID := s.Options().Auth.Options().ID | ||||||
| 	opts := []auth.GenerateOption{ | 	accSecret := s.Options().Auth.Options().Secret | ||||||
| 		auth.WithType("service"), |  | ||||||
| 		auth.WithRoles("service"), | 	// if no credentials were provided, generate an account | ||||||
| 		auth.WithNamespace(s.Options().Auth.Options().Namespace), | 	if len(accID) == 0 || len(accSecret) == 0 { | ||||||
|  | 		name := fmt.Sprintf("%v-%v", s.Name(), s.Server().Options().Id) | ||||||
|  | 		opts := []auth.GenerateOption{ | ||||||
|  | 			auth.WithType("service"), | ||||||
|  | 			auth.WithRoles("service"), | ||||||
|  | 			auth.WithNamespace(s.Options().Auth.Options().Namespace), | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		acc, err := s.Options().Auth.Generate(name, opts...) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		logger.Infof("Auth [%v] Authenticated as %v", s.Options().Auth, name) | ||||||
|  |  | ||||||
|  | 		accID = acc.ID | ||||||
|  | 		accSecret = acc.Secret | ||||||
| 	} | 	} | ||||||
| 	acc, err := s.Options().Auth.Generate(name, opts...) |  | ||||||
|  | 	// generate the first token | ||||||
|  | 	token, err := s.Options().Auth.Token( | ||||||
|  | 		auth.WithCredentials(accID, accSecret), | ||||||
|  | 		auth.WithExpiry(time.Minute*10), | ||||||
|  | 	) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// generate a token | 	// set the credentials and token in auth options | ||||||
| 	token, err := s.Options().Auth.Token(auth.WithCredentials(acc.ID, acc.Secret)) | 	s.Options().Auth.Init( | ||||||
| 	if err != nil { | 		auth.ClientToken(token), | ||||||
| 		return err | 		auth.Credentials(accID, accSecret), | ||||||
| 	} | 	) | ||||||
|  |  | ||||||
|  | 	// periodically check to see if the token needs refreshing | ||||||
|  | 	go func() { | ||||||
|  | 		timer := time.NewTicker(time.Second * 15) | ||||||
|  |  | ||||||
|  | 		for { | ||||||
|  | 			<-timer.C | ||||||
|  |  | ||||||
|  | 			// don't refresh the token if it's not close to expiring | ||||||
|  | 			tok := s.Options().Auth.Options().Token | ||||||
|  | 			if tok.Expiry.Unix() > time.Now().Add(time.Minute).Unix() { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// generate the first token | ||||||
|  | 			tok, err := s.Options().Auth.Token( | ||||||
|  | 				auth.WithCredentials(accID, accSecret), | ||||||
|  | 				auth.WithExpiry(time.Minute*10), | ||||||
|  | 			) | ||||||
|  | 			if err != nil { | ||||||
|  | 				logger.Warnf("[Auth] Error refreshing token: %v", err) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// set the token | ||||||
|  | 			s.Options().Auth.Init(auth.ClientToken(tok)) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  |  | ||||||
| 	s.Options().Auth.Init(auth.ClientToken(token), auth.Credentials(acc.ID, acc.Secret)) |  | ||||||
| 	logger.Infof("Auth [%v] Authenticated as %v", s.Options().Auth, name) |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,90 +0,0 @@ | |||||||
| package config |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"io/ioutil" |  | ||||||
| 	"os" |  | ||||||
| 	"os/user" |  | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	conf "github.com/micro/go-micro/v2/config" |  | ||||||
| 	"github.com/micro/go-micro/v2/config/source/file" |  | ||||||
| 	"github.com/micro/go-micro/v2/util/log" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // FileName for global micro config |  | ||||||
| const FileName = ".micro" |  | ||||||
|  |  | ||||||
| // config is a singleton which is required to ensure |  | ||||||
| // each function call doesn't load the .micro file |  | ||||||
| // from disk |  | ||||||
| var config = newConfig() |  | ||||||
|  |  | ||||||
| // Get a value from the .micro file |  | ||||||
| func Get(path ...string) (string, error) { |  | ||||||
| 	tk := config.Get(path...).String("") |  | ||||||
| 	return strings.TrimSpace(tk), nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Set a value in the .micro file |  | ||||||
| func Set(value string, path ...string) error { |  | ||||||
| 	// get the filepath |  | ||||||
| 	fp, err := filePath() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// set the value |  | ||||||
| 	config.Set(value, path...) |  | ||||||
|  |  | ||||||
| 	// write to the file |  | ||||||
| 	return ioutil.WriteFile(fp, config.Bytes(), 0644) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func filePath() (string, error) { |  | ||||||
| 	usr, err := user.Current() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	return filepath.Join(usr.HomeDir, FileName), nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // newConfig returns a loaded config |  | ||||||
| func newConfig() conf.Config { |  | ||||||
| 	// get the filepath |  | ||||||
| 	fp, err := filePath() |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Error(err) |  | ||||||
| 		return conf.DefaultConfig |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// write the file if it does not exist |  | ||||||
| 	if _, err := os.Stat(fp); os.IsNotExist(err) { |  | ||||||
| 		ioutil.WriteFile(fp, []byte{}, 0644) |  | ||||||
| 	} else if err != nil { |  | ||||||
| 		log.Error(err) |  | ||||||
| 		return conf.DefaultConfig |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// create a new config |  | ||||||
| 	c, err := conf.NewConfig( |  | ||||||
| 		conf.WithSource( |  | ||||||
| 			file.NewSource( |  | ||||||
| 				file.WithPath(fp), |  | ||||||
| 			), |  | ||||||
| 		), |  | ||||||
| 	) |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Error(err) |  | ||||||
| 		return conf.DefaultConfig |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// load the config |  | ||||||
| 	if err := c.Load(); err != nil { |  | ||||||
| 		log.Error(err) |  | ||||||
| 		return conf.DefaultConfig |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// return the conf |  | ||||||
| 	return c |  | ||||||
| } |  | ||||||
| @@ -12,7 +12,6 @@ import ( | |||||||
| 	"github.com/micro/go-micro/v2/errors" | 	"github.com/micro/go-micro/v2/errors" | ||||||
| 	"github.com/micro/go-micro/v2/metadata" | 	"github.com/micro/go-micro/v2/metadata" | ||||||
| 	"github.com/micro/go-micro/v2/server" | 	"github.com/micro/go-micro/v2/server" | ||||||
| 	"github.com/micro/go-micro/v2/util/config" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type fromServiceWrapper struct { | type fromServiceWrapper struct { | ||||||
| @@ -133,8 +132,6 @@ func TraceHandler(t trace.Tracer) server.HandlerWrapper { | |||||||
|  |  | ||||||
| type authWrapper struct { | type authWrapper struct { | ||||||
| 	client.Client | 	client.Client | ||||||
| 	name string |  | ||||||
| 	id   string |  | ||||||
| 	auth func() auth.Auth | 	auth func() auth.Auth | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -159,57 +156,20 @@ func (a *authWrapper) Call(ctx context.Context, req client.Request, rsp interfac | |||||||
| 		return a.Client.Call(ctx, req, rsp, opts...) | 		return a.Client.Call(ctx, req, rsp, opts...) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// performs the call with the authorization token provided |  | ||||||
| 	callWithToken := func(token string) error { |  | ||||||
| 		ctx := metadata.Set(ctx, "Authorization", auth.BearerScheme+token) |  | ||||||
| 		return a.Client.Call(ctx, req, rsp, opts...) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// check to see if we have a valid access token | 	// check to see if we have a valid access token | ||||||
| 	aaOpts := aa.Options() | 	aaOpts := aa.Options() | ||||||
| 	if aaOpts.Token != nil && aaOpts.Token.Expiry.Unix() > time.Now().Unix() { | 	if aaOpts.Token != nil && aaOpts.Token.Expiry.Unix() > time.Now().Unix() { | ||||||
| 		return callWithToken(aaOpts.Token.AccessToken) | 		ctx = metadata.Set(ctx, "Authorization", auth.BearerScheme+aaOpts.Token.AccessToken) | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// check to ensure we're not calling auth, since this will result in |  | ||||||
| 	// an endless loop |  | ||||||
| 	if req.Service() == "go.micro.auth" { |  | ||||||
| 		return a.Client.Call(ctx, req, rsp, opts...) | 		return a.Client.Call(ctx, req, rsp, opts...) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// if we have a refresh token we can use this to generate another access token |  | ||||||
| 	if aaOpts.Token != nil { |  | ||||||
| 		tok, err := aa.Token(auth.WithToken(aaOpts.Token.RefreshToken)) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		aa.Init(auth.ClientToken(tok)) |  | ||||||
| 		return callWithToken(tok.AccessToken) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// generate a new token if we have credentials |  | ||||||
| 	if len(aaOpts.ID) > 0 && len(aaOpts.Secret) > 0 { |  | ||||||
| 		tok, err := aa.Token(auth.WithCredentials(aaOpts.ID, aaOpts.Secret)) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		aa.Init(auth.ClientToken(tok)) |  | ||||||
| 		return callWithToken(tok.AccessToken) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// check to see if a token was provided in config, this is normally used for |  | ||||||
| 	// setting the token when calling via the cli |  | ||||||
| 	if token, err := config.Get("micro", "auth", "token"); err == nil && len(token) > 0 { |  | ||||||
| 		return callWithToken(token) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// call without an auth token | 	// call without an auth token | ||||||
| 	return a.Client.Call(ctx, req, rsp, opts...) | 	return a.Client.Call(ctx, req, rsp, opts...) | ||||||
| } | } | ||||||
|  |  | ||||||
| // AuthClient wraps requests with the auth header | // AuthClient wraps requests with the auth header | ||||||
| func AuthClient(name string, id string, auth func() auth.Auth, c client.Client) client.Client { | func AuthClient(auth func() auth.Auth, c client.Client) client.Client { | ||||||
| 	return &authWrapper{c, name, id, auth} | 	return &authWrapper{c, auth} | ||||||
| } | } | ||||||
|  |  | ||||||
| // AuthHandler wraps a server handler to perform auth | // AuthHandler wraps a server handler to perform auth | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user