Related Documentation
Made by
Kong Inc.
Supported Gateway Topologies
hybrid db-less traditional
Supported Konnect Deployments
hybrid cloud-gateways serverless
Compatible Protocols
grpc grpcs http https ws wss

This plugin adds HMAC Signature authentication to a Gateway Service or a Route to establish the integrity of incoming requests. The plugin validates the digital signature sent in the Proxy-Authorization or Authorization header (in that order). This plugin implementation is based off the draft-cavage-http-signatures draft with a slightly different signature scheme.

Important: Once the plugin is enabled, any user with a valid credential can access the Service or Route. To restrict usage to only some of the authenticated users, also add the ACL plugin (not covered here) and create allowed or denied groups of users.

Consumer authentication

Consumers are required for HMAC authentication. Once you create a Consumer, you can configure the Consumer’s credentials using one of the following methods:

  • With a database: Send a POST request to the /consumers/{consumer}/hmac-auth endpoint.
  • Without a database: Add a username and secret for authentication in your declarative config file in a hmacauth_credentials entry.

For both methods, you’ll add a username and optionally a secret used for authentication. If you don’t add a secret, Kong Gateway will generate one for you.

Signature authentication scheme

The client is expected to send an Authorization or Proxy-Authorization header with the following:

credentials := "hmac" params
params := keyId "," algorithm ", " headers ", " signature
keyId := "username" "=" plain-string
algorithm := "algorithm" "=" DQUOTE (hmac-sha1|hmac-sha256|hmac-sha384|hmac-sha512) DQUOTE
headers := "headers" "=" plain-string
signature := "signature" "=" plain-string
plain-string   = DQUOTE *( %x20-21 / %x23-5B / %x5D-7E ) DQUOTE

The following table describes the signature authentication parameters:

Parameter

Description

username Username of the credential
algorithm Digital signature algorithm used to create the signature
headers List of HTTP header names, separated by a single space character, used to sign the request
signature Base64-encoded digital signature generated by the client

Signature string construction

To generate the string that is signed with a key, the client must take the values of each HTTP header specified by headers in the order they appear.

  1. If the header name is not request-line or @request-target, append the lowercase header name followed with an ASCII colon : and an ASCII space.

  2. If the header name is request-line, append the HTTP request line (in ASCII format). We recommend using @request-target instead of request-line.

  3. If the header name is @request-target, append the lowercase request method, followed by a ASCII space and the request URI including any query strings. Otherwise append the header value.

  4. If value isn’t the last value, then append an ASCII newline \n. The string must not include a trailing ASCII newline.

Clock skew

The HMAC Authentication plugin also implements a clock skew check as described in the specification to prevent replay attacks. By default, a minimum lag of 300s in either direction (past/future) is allowed. Any request with a higher or lower date value will be rejected. The length of the clock skew can be edited through the plugin’s configuration by setting the clock_skew property.

The server and requesting client should be synchronized with NTP and a valid date (using GMT format) should be sent with either the X-Date or Date header.

Body validation

You can set config.validate_request_body as true to validate the request body. If it’s enabled, the plugin will calculate the SHA-256 HMAC digest of the request body and match it against the value of the Digest header. The Digest header needs to be in following format:

Digest: SHA-256=base64(sha256(<body>))

If there is no request body, the Digest should be set to the digest of a body of 0 length.

Note: To create the digest of a request body, the plugin needs to retain it in memory, which may cause pressure on the worker’s Lua VM when dealing with large bodies (several MB) or during high request concurrency.

Enforcing headers

You can use config.enforce_headers to enforce any of the headers to be part of the signature creation. By default, the plugin doesn’t enforce which header needs to be used for the signature creation. The minimum recommended data to sign is the @request-target, host, and date. A strong signature would include all of the headers and a digest of the body.

Upstream Headers

When a client has been authenticated, the plugin appends some headers to the request before proxying it to the upstream service, so that you can identify the Consumer in your code:

  • X-Consumer-ID: The ID of the Consumer in Kong Gateway.
  • X-Consumer-Custom-ID: The custom_id of the Consumer (if set).
  • X-Consumer-Username: The username of the Consumer (if set).
  • X-Credential-Identifier: The identifier of the credential (only if the Consumer is not the anonymous Consumer).
  • X-Anonymous-Consumer: Is set to true if authentication fails, and the anonymous Consumer is set instead.

You can use this information on your side to implement additional logic. You can use the X-Consumer-ID value to query the Admin API and retrieve more information about the Consumer.

Use the API with the HMAC Authentication plugin

The following table describes how you can send GET requests to the API endpoints to get information about Consumers associated with the HMAC Authentication plugin:

Use

Endpoint

Paginate through the hmac-auth credentials for all Consumers /hmac-auths
Filter the list by Consumer /consumers/{usernameOrId}/hmac-auth
Retrieve a Consumer associated with an HMAC credential /hmac-auths/{hmacUsernameOrId}/consumer
Something wrong?

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!