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
}