...

Source file src/edge-infra.dev/pkg/edge/auth-proxy/handlers/session_user_details.go

Documentation: edge-infra.dev/pkg/edge/auth-proxy/handlers

     1  package handlers
     2  
     3  import (
     4  	"errors"
     5  	"net/http"
     6  	"time"
     7  
     8  	"edge-infra.dev/pkg/edge/auth-proxy/types"
     9  
    10  	"github.com/gin-contrib/sessions"
    11  )
    12  
    13  const (
    14  	headerKeyUsername      = "X-Auth-Username"
    15  	headerKeyEmail         = "X-Auth-Email"
    16  	headerKeyRoles         = "X-Auth-Roles"
    17  	headerKeyBannerEdgeIDs = "X-Auth-Banners"
    18  )
    19  
    20  func validSession(session sessions.Session) bool {
    21  	expiresAt := session.Get(types.SessionExpirationField)
    22  	if expiresAt != nil {
    23  		expirationTime := expiresAt.(time.Time)
    24  		return !expirationTime.Before(time.Now().UTC()) && session.Get(types.SessionIDField) != nil
    25  	}
    26  	return false
    27  }
    28  
    29  // SessionUserDetails handler that adds user details to the incoming request header.
    30  //
    31  // If any error occurs this handler MUST NOT return the error. If the error is
    32  // returned the default incoming request is used in the proxy to all upstream
    33  // servers. This incoming request might contain auth headers that an attacker
    34  // can use to gain unauthorized access to the emergencyaccess solution.
    35  // If an error occurs the handler MUST log the error, and return a nil error. It
    36  // also MUST make sure the returned http.Request does not contain any auth headers.
    37  func (h ProxyHandler) SessionUserDetails(req *http.Request, body []byte) (*http.Request, []byte, error) {
    38  	// Make sure any connecting user cannot inject any auth headers into the
    39  	// request.
    40  	req.Header.Del(headerKeyUsername)
    41  	req.Header.Del(headerKeyEmail)
    42  	req.Header.Del(headerKeyRoles)
    43  	req.Header.Del(headerKeyBannerEdgeIDs)
    44  
    45  	if !validSession(h.session) {
    46  		// MUST NOT return non-nil error
    47  		h.log.Error(errors.New("invalid session"), "invalid session")
    48  		return req, body, nil
    49  	}
    50  
    51  	var err error
    52  	username, ok := h.session.Get(types.SessionUsernameField).(string)
    53  	if !ok {
    54  		err = errors.Join(err, errors.New("unable to get username from session"))
    55  	}
    56  	email, ok := h.session.Get(types.SessionEmailField).(string)
    57  	if !ok {
    58  		err = errors.Join(err, errors.New("unable to get email from session"))
    59  	}
    60  	roles, ok := h.session.Get(types.SessionRolesField).([]string)
    61  	if !ok {
    62  		err = errors.Join(err, errors.New("unable to get roles from session"))
    63  	}
    64  	bannerEdgeIDs, ok := h.session.Get(types.SessionBannerEdgeIDs).([]string)
    65  	if !ok {
    66  		err = errors.Join(err, errors.New("unable to get assigned banners from session"))
    67  	}
    68  	if err != nil {
    69  		// MUST NOT return non-nil error
    70  		h.log.Error(err, "failed to extract user details")
    71  		return req, body, nil
    72  	}
    73  
    74  	req.Header.Set(headerKeyUsername, username)
    75  	req.Header.Set(headerKeyEmail, email)
    76  	for _, role := range roles {
    77  		req.Header.Add(headerKeyRoles, role)
    78  	}
    79  	for _, bannerEdgeID := range bannerEdgeIDs {
    80  		req.Header.Add(headerKeyBannerEdgeIDs, bannerEdgeID)
    81  	}
    82  	return req, body, nil
    83  }
    84  

View as plain text