diff --git a/e2e_test/context_test.go b/e2e_test/context_test.go index 914aad9..6a93070 100644 --- a/e2e_test/context_test.go +++ b/e2e_test/context_test.go @@ -36,7 +36,6 @@ func TestContextCancelOnWaitingForBrowser(t *testing.T) { TokenURL: testServer.URL + "/token", }, }, - Logf: t.Logf, } _, err := oauth2cli.GetToken(ctx, cfg) if err == nil { @@ -73,9 +72,7 @@ func TestContextCancelOnLocalServerReadyChan(t *testing.T) { TokenURL: testServer.URL + "/token", }, }, - LocalServerReadyChan: openBrowserCh, - Logf: t.Logf, - } + LocalServerReadyChan: openBrowserCh} _, err := oauth2cli.GetToken(ctx, cfg) if err == nil { t.Errorf("GetToken wants error but was nil") diff --git a/e2e_test/e2e_test.go b/e2e_test/e2e_test.go index 2dd9490..4d29550 100644 --- a/e2e_test/e2e_test.go +++ b/e2e_test/e2e_test.go @@ -62,7 +62,6 @@ func TestHappyPath(t *testing.T) { }, LocalServerReadyChan: openBrowserCh, LocalServerMiddleware: loggingMiddleware(t), - Logf: t.Logf, } token, err := oauth2cli.GetToken(ctx, cfg) if err != nil { @@ -132,9 +131,7 @@ func TestRedirectURLHostname(t *testing.T) { }, RedirectURLHostname: "127.0.0.1", LocalServerReadyChan: openBrowserCh, - LocalServerMiddleware: loggingMiddleware(t), - Logf: t.Logf, - } + LocalServerMiddleware: loggingMiddleware(t)} token, err := oauth2cli.GetToken(ctx, cfg) if err != nil { t.Errorf("could not get a token: %s", err) @@ -214,9 +211,7 @@ func TestSuccessRedirect(t *testing.T) { LocalServerReadyChan: openBrowserCh, LocalServerMiddleware: loggingMiddleware(t), SuccessRedirectURL: sr.URL + "/success", - FailureRedirectURL: sr.URL + "/failure", - Logf: t.Logf, - } + FailureRedirectURL: sr.URL + "/failure"} token, err := oauth2cli.GetToken(ctx, cfg) if err != nil { t.Errorf("could not get a token: %s", err) diff --git a/e2e_test/error_test.go b/e2e_test/error_test.go index f5e288f..d0e07a2 100644 --- a/e2e_test/error_test.go +++ b/e2e_test/error_test.go @@ -46,7 +46,6 @@ func TestErrorAuthorizationResponse(t *testing.T) { }, }, LocalServerReadyChan: openBrowserCh, - Logf: t.Logf, } _, err := oauth2cli.GetToken(ctx, cfg) if err == nil { @@ -113,9 +112,7 @@ func TestFailureRedirect(t *testing.T) { }, LocalServerReadyChan: openBrowserCh, SuccessRedirectURL: pageServer.URL + "/success", - FailureRedirectURL: pageServer.URL + "/failure", - Logf: t.Logf, - } + FailureRedirectURL: pageServer.URL + "/failure"} _, err := oauth2cli.GetToken(ctx, cfg) if err == nil { t.Errorf("GetToken wants error but was nil") @@ -166,9 +163,7 @@ func TestErrorTokenResponse(t *testing.T) { TokenURL: testServer.URL + "/token", }, }, - LocalServerReadyChan: openBrowserCh, - Logf: t.Logf, - } + LocalServerReadyChan: openBrowserCh} _, err := oauth2cli.GetToken(ctx, cfg) if err == nil { t.Errorf("GetToken wants error but nil") diff --git a/e2e_test/localserveropts_test.go b/e2e_test/localserveropts_test.go index 5afe7a6..fdf029b 100644 --- a/e2e_test/localserveropts_test.go +++ b/e2e_test/localserveropts_test.go @@ -58,7 +58,6 @@ func TestLocalServerCallbackPath(t *testing.T) { LocalServerCallbackPath: "/callback", LocalServerReadyChan: openBrowserCh, LocalServerMiddleware: loggingMiddleware(t), - Logf: t.Logf, } token, err := oauth2cli.GetToken(ctx, cfg) if err != nil { diff --git a/e2e_test/pkce_test.go b/e2e_test/pkce_test.go index bf2e70e..978b1cd 100644 --- a/e2e_test/pkce_test.go +++ b/e2e_test/pkce_test.go @@ -76,7 +76,6 @@ func TestPKCE(t *testing.T) { }, LocalServerReadyChan: openBrowserCh, LocalServerMiddleware: loggingMiddleware(t), - Logf: t.Logf, } token, err := oauth2cli.GetToken(ctx, cfg) if err != nil { diff --git a/e2e_test/tls_test.go b/e2e_test/tls_test.go index 376d98e..1a47fc1 100644 --- a/e2e_test/tls_test.go +++ b/e2e_test/tls_test.go @@ -59,7 +59,6 @@ func TestTLS(t *testing.T) { LocalServerKeyFile: "testdata/server.key", LocalServerReadyChan: openBrowserCh, LocalServerMiddleware: loggingMiddleware(t), - Logf: t.Logf, } token, err := oauth2cli.GetToken(ctx, cfg) if err != nil { diff --git a/example/main.go b/example/main.go index e49d792..c92c26b 100644 --- a/example/main.go +++ b/example/main.go @@ -5,6 +5,7 @@ import ( "flag" "fmt" "log" + "log/slog" "os" "strings" @@ -17,6 +18,7 @@ import ( func init() { log.SetFlags(log.Lshortfile | log.Lmicroseconds) + slog.SetLogLoggerLevel(slog.LevelDebug) } type cmdOptions struct { @@ -40,7 +42,7 @@ func main() { flag.StringVar(&o.localServerKey, "local-server-key", "", "Path to a key file for the local server (optional)") flag.Parse() if o.clientID == "" { - log.Printf(`You need to set oauth2 credentials. + slog.Error(`You need to set oauth2 credentials. Open https://console.cloud.google.com/apis/credentials and create a client. Then set the following options:`) flag.PrintDefaults() @@ -48,7 +50,7 @@ Then set the following options:`) return } if o.localServerCert != "" { - log.Printf("Using the TLS certificate: %s", o.localServerCert) + slog.Debug(`Using the TLS certificate`, "path", o.localServerCert) } pkce, err := oauth2params.NewPKCE() @@ -72,7 +74,6 @@ Then set the following options:`) LocalServerReadyChan: ready, LocalServerCertFile: o.localServerCert, LocalServerKeyFile: o.localServerKey, - Logf: log.Printf, } ctx := context.Background() @@ -80,9 +81,9 @@ Then set the following options:`) eg.Go(func() error { select { case url := <-ready: - log.Printf("Open %s", url) + slog.Info("Open", "url", url) if err := browser.OpenURL(url); err != nil { - log.Printf("could not open the browser: %s", err) + slog.Error("could not open the browser", "error", err) } return nil case <-ctx.Done(): diff --git a/go.work.sum b/go.work.sum index 1a6b87e..eaf13f1 100644 --- a/go.work.sum +++ b/go.work.sum @@ -3,7 +3,9 @@ cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/ai v0.8.0/go.mod h1:t3Dfk4cM61sytiggo2UyGsDVW3RF1qGZaUKDrZFyqkE= cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= +cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= cloud.google.com/go/compute v1.6.1 h1:2sMmt8prCn7DPaG4Pmh0N3Inmc8cT8ae5k1M6VJ9Wqc= cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= @@ -35,6 +37,7 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er github.com/golangci/modinfo v0.3.3/go.mod h1:wytF1M5xl9u0ij8YSvhkEVPP3M5Mc7XLl1pxH3B2aUM= github.com/google/generative-ai-go v0.19.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= @@ -64,6 +67,7 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= +github.com/shirou/gopsutil/v4 v4.25.2/go.mod h1:34gBYJzyqCDT11b6bMHP0XCvWeU3J61XRT7a2EmCRTA= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -75,22 +79,33 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3 go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/detectors/gcp v1.29.0/go.mod h1:GW2aWZNwR2ZxDLdv8OyC2G8zkRoQBuURgV7RPQgcPoU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.215.0/go.mod h1:fta3CVtuJYOEdugLNWm6WodzOS8KdFckABwN4I40hzY= +google.golang.org/api v0.223.0/go.mod h1:C+RS7Z+dDwds2b+zoAk5hN/eSfsiCn0UDrYof/M4d2M= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= diff --git a/oauth2cli.go b/oauth2cli.go index 03370c2..c9a3530 100644 --- a/oauth2cli.go +++ b/oauth2cli.go @@ -5,6 +5,7 @@ package oauth2cli import ( "context" "fmt" + "log/slog" "net/http" "github.com/int128/oauth2cli/oauth2params" @@ -99,9 +100,6 @@ type Config struct { SuccessRedirectURL string // Redirect URL upon failed login FailureRedirectURL string - - // Logger function for debug. - Logf func(format string, args ...interface{}) } func (cfg *Config) isLocalServerHTTPS() bool { @@ -133,9 +131,6 @@ func (cfg *Config) validateAndSetDefaults() error { (cfg.SuccessRedirectURL == "" && cfg.FailureRedirectURL != "") { return fmt.Errorf("when using success and failure redirect URLs, set both URLs") } - if cfg.Logf == nil { - cfg.Logf = func(string, ...interface{}) {} - } return nil } @@ -158,7 +153,7 @@ func GetToken(ctx context.Context, cfg Config) (*oauth2.Token, error) { if err != nil { return nil, fmt.Errorf("authorization error: %w", err) } - cfg.Logf("oauth2cli: exchanging the code and token") + slog.DebugContext(ctx, "oauth2cli: exchanging the code and token") token, err := cfg.OAuth2Config.Exchange(ctx, code, cfg.TokenRequestOptions...) if err != nil { return nil, fmt.Errorf("could not exchange the code and token: %w", err) diff --git a/server.go b/server.go index 0ffc8f7..10e8e12 100644 --- a/server.go +++ b/server.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "log/slog" "net" "net/http" "net/url" @@ -39,14 +40,17 @@ func receiveCodeViaLocalServer(ctx context.Context, cfg *Config) (string, error) config: cfg, respCh: respCh, }), + BaseContext: func(net.Listener) context.Context { + return ctx + }, } shutdownCh := make(chan struct{}) var resp *authorizationResponse var eg errgroup.Group eg.Go(func() error { defer close(respCh) - cfg.Logf("oauth2cli: starting a server at %s", localServerListener.Addr()) - defer cfg.Logf("oauth2cli: stopped the server") + slog.DebugContext(ctx, "oauth2cli: starting a server", "address", localServerListener.Addr()) + defer slog.DebugContext(ctx, "oauth2cli: stopped the server") if cfg.isLocalServerHTTPS() { if err := server.ServeTLS(localServerListener, cfg.LocalServerCertFile, cfg.LocalServerKeyFile); err != nil { if errors.Is(err, http.ErrServerClosed) { @@ -78,11 +82,11 @@ func receiveCodeViaLocalServer(ctx context.Context, cfg *Config) (string, error) // Gracefully shutdown the server in the timeout. // If the server has not started, Shutdown returns nil and this returns immediately. // If Shutdown has failed, force-close the server. - cfg.Logf("oauth2cli: shutting down the server") + slog.DebugContext(ctx, "oauth2cli: shutting down the server") ctx, cancel := context.WithTimeout(ctx, 500*time.Millisecond) defer cancel() if err := server.Shutdown(ctx); err != nil { - cfg.Logf("oauth2cli: force-closing the server: shutdown failed: %s", err) + slog.DebugContext(ctx, "oauth2cli: force-closing the server", "error", err) _ = server.Close() return nil } @@ -153,7 +157,7 @@ func (h *localServerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *localServerHandler) handleIndex(w http.ResponseWriter, r *http.Request) { authCodeURL := h.config.OAuth2Config.AuthCodeURL(h.config.State, h.config.AuthCodeOptions...) - h.config.Logf("oauth2cli: sending redirect to %s", authCodeURL) + slog.DebugContext(r.Context(), "oauth2cli: sending redirect", "url", authCodeURL) http.Redirect(w, r, authCodeURL, http.StatusFound) }