@@ -180,7 +180,7 @@ type callbackServer struct {
180180 wait chan callbackPayload
181181 errs chan error
182182 server * http.Server
183- listener net.Listener
183+ listeners [] net.Listener
184184}
185185
186186type callbackPayload struct {
@@ -195,19 +195,24 @@ func waitForOAuthCallback(expectedState string, timeout time.Duration) (*callbac
195195 srv := & http.Server {
196196 Handler : mux ,
197197 // Set ReadHeaderTimeout to mitigate Slowloris attacks (gosec G112).
198- // Even though this listens only on 127.0.0.1 , we still bound it.
198+ // Even though this listens only on loopback interfaces , we still bound it.
199199 ReadHeaderTimeout : 10 * time .Second ,
200200 }
201- ln , err := net .Listen ("tcp " , "127.0.0.1:0" )
201+ ln4 , err := net .Listen ("tcp4 " , "127.0.0.1:0" )
202202 if err != nil {
203203 return nil , err
204204 }
205+ port := ln4 .Addr ().(* net.TCPAddr ).Port
206+ listeners := []net.Listener {ln4 }
207+ if ln6 , err := net .Listen ("tcp6" , fmt .Sprintf ("[::1]:%d" , port )); err == nil {
208+ listeners = append (listeners , ln6 )
209+ }
205210 cs := & callbackServer {
206- RedirectURI : fmt .Sprintf ("http://localhost:%d/oauth/callback" , ln . Addr ().( * net. TCPAddr ). Port ),
211+ RedirectURI : fmt .Sprintf ("http://localhost:%d/oauth/callback" , port ),
207212 wait : wait ,
208213 errs : errs ,
209214 server : srv ,
210- listener : ln ,
215+ listeners : listeners ,
211216 }
212217 mux .HandleFunc ("/oauth/callback" , func (w http.ResponseWriter , r * http.Request ) {
213218 code := r .URL .Query ().Get ("code" )
@@ -228,9 +233,11 @@ func waitForOAuthCallback(expectedState string, timeout time.Duration) (*callbac
228233 wait <- callbackPayload {Code : code , State : state }
229234 }
230235 })
231- go func () {
232- _ = srv .Serve (ln )
233- }()
236+ for _ , listener := range listeners {
237+ go func (ln net.Listener ) {
238+ _ = srv .Serve (ln )
239+ }(listener )
240+ }
234241 go func () {
235242 <- time .After (timeout )
236243 errs <- errors .New ("Timed out waiting for the OAuth callback. Re-run with --no-browser to copy the URL manually, or check that your browser completed the login flow." )
@@ -248,7 +255,16 @@ func (c *callbackServer) Wait() (callbackPayload, error) {
248255}
249256
250257func (c * callbackServer ) Close () error {
251- return c .server .Close ()
258+ var firstErr error
259+ if err := c .server .Close (); err != nil {
260+ firstErr = err
261+ }
262+ for _ , listener := range c .listeners {
263+ if err := listener .Close (); err != nil && ! errors .Is (err , net .ErrClosed ) && firstErr == nil {
264+ firstErr = err
265+ }
266+ }
267+ return firstErr
252268}
253269
254270type tokenResponse struct {
0 commit comments