github.com/sap/cf-mta-plugin@v2.6.3+incompatible/clients/csrf/default_csrf_token_manager.go (about)

     1  package csrf
     2  
     3  import (
     4  	"net/http"
     5  )
     6  
     7  const XCsrfHeader = "X-Csrf-Header"
     8  const XCsrfToken = "X-Csrf-Token"
     9  const CsrfTokenHeaderRequiredValue = "Required"
    10  
    11  type DefaultCsrfTokenManager struct {
    12  	request          *http.Request
    13  	transport        *Transport
    14  	csrfTokenFetcher CsrfTokenFetcher
    15  }
    16  
    17  func NewDefaultCsrfTokenManager(transport *Transport, request *http.Request) *DefaultCsrfTokenManager {
    18  	return &DefaultCsrfTokenManager{request: request, transport: transport, csrfTokenFetcher: NewDefaultCsrfTokenFetcher(transport)}
    19  }
    20  
    21  func NewDefaultCsrfTokenManagerWithFetcher(transport *Transport, request *http.Request, csrfTokenFetcher CsrfTokenFetcher) *DefaultCsrfTokenManager {
    22  	return &DefaultCsrfTokenManager{request: request, transport: transport, csrfTokenFetcher: csrfTokenFetcher}
    23  }
    24  
    25  func (c *DefaultCsrfTokenManager) updateToken() error {
    26  	if !c.shouldInitialize() {
    27  		return nil
    28  	}
    29  	err := c.initializeToken(false)
    30  	if err != nil {
    31  		return err
    32  	}
    33  
    34  	c.updateTokenInRequest()
    35  
    36  	return nil
    37  }
    38  
    39  func (c *DefaultCsrfTokenManager) initializeToken(forceInitializing bool) error {
    40  	if forceInitializing || !c.transport.Csrf.IsInitialized {
    41  		var err error
    42  		csrfToken, err := c.csrfTokenFetcher.FetchCsrfToken(getCsrfTokenUrl(c.request), c.request)
    43  		if csrfToken == nil {
    44  			return nil
    45  		}
    46  		c.transport.Csrf.Header, c.transport.Csrf.Token = csrfToken.CsrfTokenHeader, csrfToken.CsrfTokenValue
    47  		if err != nil {
    48  			return err
    49  		}
    50  		c.transport.Csrf.IsInitialized = true
    51  	}
    52  
    53  	return nil
    54  }
    55  
    56  func (c *DefaultCsrfTokenManager) refreshTokenIfNeeded(response *http.Response) (bool, error) {
    57  	if !c.isProtectionRequired(c.request, c.transport) {
    58  		return false, nil
    59  	}
    60  	if c.transport.Csrf.IsInitialized && (response.StatusCode == http.StatusForbidden) {
    61  		csrfToken := response.Header.Get(XCsrfToken)
    62  
    63  		if CsrfTokenHeaderRequiredValue == csrfToken {
    64  			err := c.initializeToken(true)
    65  			if err != nil {
    66  				return false, err
    67  			}
    68  			// the token was refreshed successfully so the client should retry the request
    69  			return c.transport.Csrf.Token != "", nil
    70  		}
    71  	}
    72  
    73  	return false, nil
    74  }
    75  
    76  func (c *DefaultCsrfTokenManager) updateTokenInRequest() {
    77  	if c.transport.Csrf.Token != "" && c.transport.Csrf.Header != "" {
    78  		c.request.Header.Set(XCsrfToken, c.transport.Csrf.Token)
    79  		c.request.Header.Set(XCsrfHeader, c.transport.Csrf.Header)
    80  	}
    81  }
    82  
    83  func (c *DefaultCsrfTokenManager) isProtectionRequired(req *http.Request, t *Transport) bool {
    84  	return !t.Csrf.NonProtectedMethods[req.Method]
    85  }
    86  
    87  func (c *DefaultCsrfTokenManager) shouldInitialize() bool {
    88  	return c.request != nil && c.isProtectionRequired(c.request, c.transport)
    89  }