Skip to content

Commit 7beac81

Browse files
authored
Respect oauth2.Config.RedirectURL if set (#263)
1 parent 1ee9ded commit 7beac81

File tree

2 files changed

+34
-27
lines changed

2 files changed

+34
-27
lines changed

oauth2cli.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,23 @@ const DefaultLocalServerSuccessHTML = `
5050
// Config represents a config for GetToken.
5151
type Config struct {
5252
// OAuth2 config.
53-
// RedirectURL will be automatically set to the local server.
53+
// If the RedirectURL field is not set, default to http://localhost with the allocated port and LocalServerCallbackPath.
54+
// If the RedirectURL field is set, make sure it matches the LocalServerBindAddress and LocalServerCallbackPath.
5455
OAuth2Config oauth2.Config
5556

5657
// Options for an authorization request.
5758
// You can set oauth2.AccessTypeOffline or oauth2.S256ChallengeOption.
5859
AuthCodeOptions []oauth2.AuthCodeOption
60+
5961
// Options for a token request.
6062
// You can set oauth2.VerifierOption.
6163
TokenRequestOptions []oauth2.AuthCodeOption
64+
6265
// State parameter in the authorization request.
6366
// Default to a string of random 32 bytes.
6467
State string
6568

66-
// Hostname of the redirect URL.
67-
// You can set this if your provider does not accept localhost.
68-
// Default to localhost.
69+
// DEPRECATED: Set OAuth2Config.RedirectURL instead.
6970
RedirectURLHostname string
7071

7172
// Candidates of hostname and port which the local server binds to.
@@ -79,24 +80,31 @@ type Config struct {
7980
// certificates. It's recommended that the public key's SANs contain
8081
// the loopback addresses - 'localhost', '127.0.0.1' and '::1'
8182
LocalServerCertFile string
83+
8284
// A PEM-encoded private key for the certificate.
8385
// This is required when LocalServerCertFile is set.
8486
LocalServerKeyFile string
8587

8688
// Callback path of the local server.
87-
// If your provider requires a specific path of the redirect URL, set it here.
89+
// If your provider requires a specific path of the redirect URL, set this field.
90+
// Default to none.
8891
LocalServerCallbackPath string
8992

9093
// Response HTML body on authorization completed.
9194
// Default to DefaultLocalServerSuccessHTML.
9295
LocalServerSuccessHTML string
93-
// Middleware for the local server. Default to none.
96+
97+
// Middleware for the local server.
98+
// Default to none.
9499
LocalServerMiddleware func(h http.Handler) http.Handler
95-
// A channel to send its URL when the local server is ready. Default to none.
100+
101+
// A channel to send the local server URL when it is ready.
102+
// Default to none.
96103
LocalServerReadyChan chan<- string
97104

98105
// Redirect URL upon successful login
99106
SuccessRedirectURL string
107+
100108
// Redirect URL upon failed login
101109
FailureRedirectURL string
102110

@@ -113,9 +121,6 @@ func (cfg *Config) validateAndSetDefaults() error {
113121
(cfg.LocalServerCertFile == "" && cfg.LocalServerKeyFile != "") {
114122
return fmt.Errorf("both LocalServerCertFile and LocalServerKeyFile must be set")
115123
}
116-
if cfg.RedirectURLHostname == "" {
117-
cfg.RedirectURLHostname = "localhost"
118-
}
119124
if cfg.State == "" {
120125
state, err := oauth2params.NewState()
121126
if err != nil {

server.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,29 @@ func receiveCodeViaLocalServer(ctx context.Context, cfg *Config) (string, error)
2121
}
2222
defer localServerListener.Close()
2323

24-
localServerPort := localServerListener.Addr().(*net.TCPAddr).Port
25-
localServerURL := constructLocalServerURL(cfg, localServerPort)
26-
localServerIndexURL, err := localServerURL.Parse("/")
24+
if cfg.OAuth2Config.RedirectURL == "" {
25+
var localServerURL url.URL
26+
localServerHostname := "localhost"
27+
if cfg.RedirectURLHostname != "" {
28+
localServerHostname = cfg.RedirectURLHostname
29+
}
30+
localServerURL.Host = fmt.Sprintf("%s:%d", localServerHostname, localServerListener.Addr().(*net.TCPAddr).Port)
31+
localServerURL.Scheme = "http"
32+
if cfg.isLocalServerHTTPS() {
33+
localServerURL.Scheme = "https"
34+
}
35+
localServerURL.Path = cfg.LocalServerCallbackPath
36+
cfg.OAuth2Config.RedirectURL = localServerURL.String()
37+
}
38+
39+
oauth2RedirectURL, err := url.Parse(cfg.OAuth2Config.RedirectURL)
2740
if err != nil {
28-
return "", fmt.Errorf("construct the index URL: %w", err)
41+
return "", fmt.Errorf("invalid OAuth2Config.RedirectURL: %w", err)
2942
}
30-
localServerCallbackURL, err := localServerURL.Parse(cfg.LocalServerCallbackPath)
43+
localServerIndexURL, err := oauth2RedirectURL.Parse("/")
3144
if err != nil {
32-
return "", fmt.Errorf("construct the callback URL: %w", err)
45+
return "", fmt.Errorf("construct the index URL: %w", err)
3346
}
34-
cfg.OAuth2Config.RedirectURL = localServerCallbackURL.String()
3547

3648
respCh := make(chan *authorizationResponse)
3749
server := http.Server{
@@ -108,16 +120,6 @@ func receiveCodeViaLocalServer(ctx context.Context, cfg *Config) (string, error)
108120
return resp.code, resp.err
109121
}
110122

111-
func constructLocalServerURL(cfg *Config, port int) url.URL {
112-
var localServer url.URL
113-
localServer.Host = fmt.Sprintf("%s:%d", cfg.RedirectURLHostname, port)
114-
localServer.Scheme = "http"
115-
if cfg.isLocalServerHTTPS() {
116-
localServer.Scheme = "https"
117-
}
118-
return localServer
119-
}
120-
121123
type authorizationResponse struct {
122124
code string // non-empty if a valid code is received
123125
err error // non-nil if an error is received or any error occurs

0 commit comments

Comments
 (0)