func()

in internal/auth/auth.go [218:332]


func (a *Auth) handleProxyingAuth(session *hostSession, w http.ResponseWriter, r *http.Request, domains source.Source) bool {
	// handle auth callback e.g. https://gitlab.io/auth?domain=domain&state=state
	if shouldProxyAuthToGitlab(r) {
		domain := r.URL.Query().Get("domain")
		state := r.URL.Query().Get("state")

		proxyurl, err := url.Parse(domain)
		if err != nil {
			logRequest(r).WithField("domain_query", domain).Error(queryParameterErrMsg)
			errortracking.CaptureErrWithReqAndStackTrace(err, r, errortracking.WithField("domain_query", domain))

			httperrors.Serve500(w)
			return true
		}

		// domain query param can only contain https or http URLs.
		if proxyurl.Scheme != "http" && proxyurl.Scheme != "https" {
			logRequest(r).WithField("domain_query", domain).Warn(domainQueryParameterErrMsg)

			httperrors.Serve401(w)
			return true
		}

		host, _, err := net.SplitHostPort(proxyurl.Host)
		if err != nil {
			host = proxyurl.Host
		}

		if !a.domainAllowed(r.Context(), host, domains) {
			logRequest(r).WithFields(logrus.Fields{
				"domain_query": domain,
				"domain_host":  host,
			}).Warn("Domain is not configured")
			httperrors.Serve401(w)
			return true
		}

		logRequest(r).WithField("domain_query", domain).Info("User is authenticating via domain")

		session.Values["proxy_auth_domain"] = domain

		session.appendPath(r.URL.Path)

		err = session.Save(r, w)
		if err != nil {
			logRequest(r).WithError(err).Error(saveSessionErrMsg)
			errortracking.CaptureErrWithReqAndStackTrace(err, r)

			httperrors.Serve500(w)
			return true
		}

		url := fmt.Sprintf(authorizeURLTemplate, a.publicGitlabServer, a.clientID, a.redirectURI, state, a.authScope)

		logRequest(r).WithFields(logrus.Fields{
			"public_gitlab_server": a.publicGitlabServer,
			"domain_query":         domain,
		}).Info("Redirecting user to gitlab for oauth")

		http.Redirect(w, r, url, http.StatusFound)

		return true
	}

	// If auth request callback should be proxied to custom domain
	// redirect to originating domain set in the cookie as proxy_auth_domain
	if shouldProxyCallbackToCustomDomain(session) {
		// Get domain started auth process
		proxyDomain := session.Values["proxy_auth_domain"].(string)

		logRequest(r).WithField("proxy_auth_domain", proxyDomain).Info("Redirecting auth callback to custom domain")

		// Clear proxying from session
		delete(session.Values, "proxy_auth_domain")

		session.appendPath(r.URL.Path)

		err := session.Save(r, w)
		if err != nil {
			logRequest(r).WithError(err).Error(saveSessionErrMsg)
			errortracking.CaptureErrWithReqAndStackTrace(err, r)

			httperrors.Serve500(w)
			return true
		}

		query := r.URL.Query()

		// prevent https://tools.ietf.org/html/rfc6749#section-10.6 and
		// https://gitlab.com/gitlab-org/gitlab-pages/-/issues/262 by encrypting
		// and signing the OAuth code
		signedCode, err := a.EncryptAndSignCode(proxyDomain, query.Get("code"))
		if err != nil {
			logRequest(r).WithError(err).Error(saveSessionErrMsg)
			errortracking.CaptureErrWithReqAndStackTrace(err, r)

			httperrors.Serve503(w)
			return true
		}

		// prevent forwarding access token, more context on the security issue
		// https://gitlab.com/gitlab-org/gitlab/-/issues/285244#note_451266051
		query.Del("token")

		// replace code with signed code
		query.Set("code", signedCode)

		// Redirect pages to originating domain with code and state to finish
		// authentication process
		http.Redirect(w, r, proxyDomain+r.URL.Path+"?"+query.Encode(), http.StatusFound)
		return true
	}

	return false
}