github.com/minio/console@v1.4.1/pkg/auth/idp/oauth2/proxy.go (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2021 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package oauth2
    18  
    19  import (
    20  	"net/http"
    21  	"regexp"
    22  	"strings"
    23  )
    24  
    25  var (
    26  	// De-facto standard header keys.
    27  	xForwardedProto  = http.CanonicalHeaderKey("X-Forwarded-Proto")
    28  	xForwardedScheme = http.CanonicalHeaderKey("X-Forwarded-Scheme")
    29  )
    30  
    31  var (
    32  	// RFC7239 defines a new "Forwarded: " header designed to replace the
    33  	// existing use of X-Forwarded-* headers.
    34  	// e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43
    35  	forwarded = http.CanonicalHeaderKey("Forwarded")
    36  	// Allows for a sub-match of the first value after 'for=' to the next
    37  	// comma, semi-colon or space. The match is case-insensitive.
    38  	forRegex = regexp.MustCompile(`(?i)(?:for=)([^(;|,| )]+)(.*)`)
    39  	// Allows for a sub-match for the first instance of scheme (http|https)
    40  	// prefixed by 'proto='. The match is case-insensitive.
    41  	protoRegex = regexp.MustCompile(`(?i)^(;|,| )+(?:proto=)(https|http)`)
    42  )
    43  
    44  // getSourceScheme retrieves the scheme from the X-Forwarded-Proto and RFC7239
    45  // Forwarded headers (in that order).
    46  func getSourceScheme(r *http.Request) string {
    47  	var scheme string
    48  
    49  	// Retrieve the scheme from X-Forwarded-Proto.
    50  	if proto := r.Header.Get(xForwardedProto); proto != "" {
    51  		scheme = strings.ToLower(proto)
    52  	} else if proto = r.Header.Get(xForwardedScheme); proto != "" {
    53  		scheme = strings.ToLower(proto)
    54  	} else if proto := r.Header.Get(forwarded); proto != "" {
    55  		// match should contain at least two elements if the protocol was
    56  		// specified in the Forwarded header. The first element will always be
    57  		// the 'for=', which we ignore, subsequently we proceed to look for
    58  		// 'proto=' which should precede right after `for=` if not
    59  		// we simply ignore the values and return empty. This is in line
    60  		// with the approach we took for returning first ip from multiple
    61  		// params.
    62  		if match := forRegex.FindStringSubmatch(proto); len(match) > 1 {
    63  			if match = protoRegex.FindStringSubmatch(match[2]); len(match) > 1 {
    64  				scheme = strings.ToLower(match[2])
    65  			}
    66  		}
    67  	}
    68  
    69  	return scheme
    70  }