authMiddleware is a CONNECT middleware that extracts the Coder token from the Proxy-Authorization header and stores it in a requestContext in ctx.UserData for use by downstream handlers. Requests without valid credentials receive a 407 Proxy Authentication Required response with a challenge header,
(host string, ctx *goproxy.ProxyCtx)
| 637 | // |
| 638 | // The token is extracted from the password field of basic auth. |
| 639 | func (s *Server) authMiddleware(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) { |
| 640 | // Generate a unique connect session ID for this CONNECT request. |
| 641 | // A UUID is used instead of goproxy's ctx.Session because ctx.Session is an |
| 642 | // incrementing int64 that resets on process restart and is not globally unique. |
| 643 | connectSessionID := uuid.New() |
| 644 | |
| 645 | logger := s.logger.With( |
| 646 | slog.F("connect_id", connectSessionID.String()), |
| 647 | slog.F("host", host), |
| 648 | ) |
| 649 | |
| 650 | // Determine the provider from the request hostname. |
| 651 | provider := s.loadProviderRouter().providerFromHost(ctx.Req.URL.Hostname()) |
| 652 | // A concurrent Reload can swap the router between CONNECT matching |
| 653 | // and provider lookup, so treat a missing mapping as a runtime miss. |
| 654 | if provider == "" { |
| 655 | logger.Warn(s.ctx, "rejecting CONNECT request with no provider mapping") |
| 656 | return goproxy.RejectConnect, host |
| 657 | } |
| 658 | |
| 659 | logger = logger.With( |
| 660 | slog.F("provider", provider), |
| 661 | ) |
| 662 | |
| 663 | proxyAuth := ctx.Req.Header.Get("Proxy-Authorization") |
| 664 | coderToken := extractCoderTokenFromProxyAuth(proxyAuth) |
| 665 | |
| 666 | // Reject requests for both missing and invalid credentials |
| 667 | if coderToken == "" { |
| 668 | hasAuth := proxyAuth != "" |
| 669 | logger.Warn(s.ctx, "rejecting CONNECT request", |
| 670 | slog.F("reason", map[bool]string{true: "invalid_credentials", false: "missing_credentials"}[hasAuth]), |
| 671 | ) |
| 672 | |
| 673 | // Send 407 challenge to allow clients to retry with credentials. |
| 674 | ctx.Resp = newProxyAuthRequiredResponse(ctx.Req) //nolint:bodyclose // Response body is written by goproxy to the client |
| 675 | return goproxy.RejectConnect, host |
| 676 | } |
| 677 | |
| 678 | // Store the request context in UserData for downstream handlers. |
| 679 | // goproxy propagates UserData to subsequent request/response contexts |
| 680 | // for decrypted requests within this MITM session. |
| 681 | ctx.UserData = &requestContext{ |
| 682 | ConnectSessionID: connectSessionID, |
| 683 | CoderToken: coderToken, |
| 684 | Provider: provider, |
| 685 | } |
| 686 | |
| 687 | logger.Debug(s.ctx, "request CONNECT authenticated") |
| 688 | |
| 689 | // Record successful MITM CONNECT session establishment. |
| 690 | if s.metrics != nil { |
| 691 | s.metrics.ConnectSessionsTotal.WithLabelValues(RequestTypeMITM).Inc() |
| 692 | } |
| 693 | |
| 694 | return goproxy.MitmConnect, host |
| 695 | } |
| 696 |
nothing calls this directly
no test coverage detected