...

Source file src/edge-infra.dev/pkg/sds/emergencyaccess/middleware/auth.go

Documentation: edge-infra.dev/pkg/sds/emergencyaccess/middleware

     1  package middleware
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/gin-gonic/gin"
     8  
     9  	"edge-infra.dev/pkg/sds/emergencyaccess/apierror"
    10  	errorhandler "edge-infra.dev/pkg/sds/emergencyaccess/apierror/handler"
    11  	"edge-infra.dev/pkg/sds/emergencyaccess/eaconst"
    12  	"edge-infra.dev/pkg/sds/emergencyaccess/types"
    13  )
    14  
    15  // SaveAuthToContext returns a gin middleware function that creates a
    16  // [types.User] struct from any incoming `X-Auth-XXX` headers, and saves the
    17  // struct into the context. Incoming `X-Auth-XXXX` headers must be
    18  // pre-authenticated as the middleware does not verify the authenticity of the
    19  // data. If no incoming headers are present, an empty user is saved to the
    20  // context.
    21  //
    22  // Requires enabling the [gin.Engine.ContextWithFallback] option.
    23  func SaveAuthToContext() gin.HandlerFunc {
    24  	return func(c *gin.Context) {
    25  		ctx := c.Request.Context()
    26  		username := c.Request.Header.Get(eaconst.HeaderAuthKeyUsername)
    27  		email := c.Request.Header.Get(eaconst.HeaderAuthKeyEmail)
    28  		roles := c.Request.Header.Values(eaconst.HeaderAuthKeyRoles)
    29  		banners := c.Request.Header.Values(eaconst.HeaderAuthKeyBanners)
    30  
    31  		user := types.User{
    32  			Username: username,
    33  			Email:    email,
    34  			Roles:    roles,
    35  			Banners:  banners,
    36  		}
    37  
    38  		ctx = types.UserIntoContext(ctx, user)
    39  
    40  		c.Request = c.Request.Clone(ctx)
    41  
    42  		c.Next()
    43  	}
    44  }
    45  
    46  // VerifyUserDetailsInContext returns a gin middleware function that verifies the
    47  // [types.User] struct stored in the context. It makes sure that the Username
    48  // and Email fields are valid. If there is no [types.User] in context or the
    49  // fields are invalid, it fails with an error.
    50  //
    51  // Requires enabling the [gin.Engine.ContextWithFallback] option.
    52  func VerifyUserDetailsInContext() gin.HandlerFunc {
    53  	return func(c *gin.Context) {
    54  		user, ok := types.UserFromContext(c)
    55  		if !ok {
    56  			errorhandler.ErrorHandler(c, apierror.E(apierror.ErrUserNotFound, fmt.Errorf("user details not found in authservice request")))
    57  			return
    58  		}
    59  
    60  		var err error
    61  		if user.Username == "" {
    62  			err = errors.Join(err, fmt.Errorf("username not found in authservice request"))
    63  		}
    64  		if user.Email == "" {
    65  			err = errors.Join(err, fmt.Errorf("email not found in authservice request"))
    66  		}
    67  		if err != nil {
    68  			errorhandler.ErrorHandler(c, apierror.E(apierror.ErrUserNotFound, err))
    69  			return
    70  		}
    71  
    72  		c.Next()
    73  	}
    74  }
    75  

View as plain text