Skip to content

Date header is only added during request signing if the header list is empty #7926

@jenni-okelly

Description

@jenni-okelly

Branch/Environment/Version

  • Branch/Version: Observed on 5.8.2, but I think this is the case for all versions
  • Environment: Observed in Hybrid

Describe the bug
When using upstream request signing with HMAC, the docs suggest that a Date header will be added to the request as it is necessary for compliance with the RFC. In my observation, this is only the case when the headerList configured for the API is empty. if a non-empty header list is defined, the date header will not be added. This is true even if "date" is included in the configured headerList.

Reproduction steps

  1. Enable request signing with a configuration like:
{
  "is_enabled": true,
  "secret": "shhhhh",
  "key_id": "tyk-key-id",
  "algorithm": "hmac-sha256",
  "header_list": [ "(request-target)", "x-example" , "date"],
  "certificate_id": "",
  "signature_header": "authorization"
},
  1. Call the API without including a Date header

Actual behavior
No date header is added (the backend receives a call with a signature, but the signature is not based on a date header and no date header is received by the backend)

Expected behavior
A date header is added to the request and used in generating the signature

Screenshots/Video
N/A

Logs (debug mode or log file):
N/A

Configuration (tyk config file):

Additional context
I believe this comes from generateHeaderList. I have done very little with Go before, but at a naive read I think it should be something like:

func generateHeaderList(r *http.Request, headerList []string) []string {
	var result []string

	// date header is must as per Signing HTTP Messages Draft
	if r.Header.Get("date") == "" {
		refDate := "Mon, 02 Jan 2006 15:04:05 MST"
		tim := time.Now().Format(refDate)

		r.Header.Set("date", tim)
	}

	if len(headerList) == 0 {
		result = make([]string, len(r.Header)+1)
		result[0] = "(request-target)"
		i := 1

		for k := range r.Header {
			loweredCaseHeader := strings.ToLower(k)
			result[i] = strings.TrimSpace(loweredCaseHeader)
			i++
		}
	} else {
		result = make([]string, 0, len(headerList))

		for _, v := range headerList {
			if r.Header.Get(v) != "" {
				result = append(result, v)
			}
		}

		if len(result) == 0 {
			headers := []string{"(request-target)", "date"}
			result = append(result, headers...)
		}
	}

	return result
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions