diff --git a/docs/en/latest/plugins/hmac-auth.md b/docs/en/latest/plugins/hmac-auth.md index 6319ce23f64f..df7cb4268432 100644 --- a/docs/en/latest/plugins/hmac-auth.md +++ b/docs/en/latest/plugins/hmac-auth.md @@ -887,6 +887,10 @@ body = '{"name": "world"}' # example request body # skew to prolong the validity within the advised security boundary gmt_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT') +# create the SHA-256 digest of the request body and base64 encode it +body_digest = hashlib.sha256(body.encode('utf-8')).digest() +body_digest_base64 = base64.b64encode(body_digest).decode('utf-8') + # construct the signing string (ordered) # the date and any subsequent custom headers should be lowercased and separated by a # single space character, i.e. `:` @@ -895,23 +899,20 @@ signing_string = ( f"{key_id}\n" f"{request_method} {request_path}\n" f"date: {gmt_time}\n" + f"digest: SHA-256={body_digest_base64}\n" ) # create signature signature = hmac.new(secret_key, signing_string.encode('utf-8'), hashlib.sha256).digest() signature_base64 = base64.b64encode(signature).decode('utf-8') -# create the SHA-256 digest of the request body and base64 encode it -body_digest = hashlib.sha256(body.encode('utf-8')).digest() -body_digest_base64 = base64.b64encode(body_digest).decode('utf-8') - # construct the request headers headers = { "Date": gmt_time, "Digest": f"SHA-256={body_digest_base64}", "Authorization": ( - f'Signature keyId="{key_id}",algorithm="hmac-sha256",' - f'headers="@request-target date",' + f'Signature keyId="{key_id}",algorithm="{algorithm}",' + f'headers="@request-target date digest",' f'signature="{signature_base64}"' ) } @@ -972,6 +973,10 @@ You should see an `HTTP/1.1 200 OK` response similar to the following: } ``` +:::note +`validate_request_body` only checks that the `Digest` header matches the request body. To bind the body integrity to the HMAC signature and ensure end-to-end protection, you must also include the `Digest` header in the signed headers list (as shown above) or enforce it via the route-level `signed_headers` configuration option. +::: + If you send a request without the digest or with an invalid digest: ```shell