class

Kemal::Hmac::Handler

Inherits Kemal::Handler / HTTP::Handler / Reference / Object

This middleware adds hmac support to your application. Returns 401 "Unauthorized" with wrong credentials.

hmac_auth({"my_client" => ["my_secret"]})

HTTP::Server::Context#authorized_hmac_client? is set when the client is authorized.

Constructors

new(hmac_secrets : Hash(String, Array(String)) = {} of String => Array(String), hmac_client_header : String | Nil = nil, hmac_timestamp_header : String | Nil = nil, hmac_token_header : String | Nil = nil, timestamp_second_window : Int32 | Nil = nil, rejected_code : Int32 | Nil = nil, rejected_message_prefix : String | Nil = nil, hmac_key_suffix_list : Array(String) | Nil = nil, hmac_key_delimiter : String | Nil = nil, hmac_algorithm : String | Nil = nil, enable_env_lookup : Bool = false)

initialize the Kemal::Hmac::Handler note: "BLUE" and "GREEN" in this context are two different secrets for the same client. This is a common pattern to allow for key rotation without downtime. examples: hmac_secrets: {"cool-client-service" => ["BLUE_SECRET", "GREEN_SECRET"]} - explicitly set secrets for one or many clients hmac_client_header: "HTTP_X_HMAC_CLIENT" hmac_timestamp_header: "HTTP_X_HMAC_TIMESTAMP" hmac_token_header: "HTTP_X_HMAC_TOKEN" timestamp_second_window: 30 rejected_code: 401 rejected_message_prefix: "Unauthorized:" hmac_key_suffix_list: ["HMAC_SECRET_BLUE", "HMAC_SECRET_GREEN"] - only used for env variable lookups hmac_key_delimiter: "_" - only used for env variable lookups hmac_algorithm: "SHA256" enable_env_lookup: true (this value is set to false by default)

Source

Instance methods

call(context)
Source
fetch_hmac_algorithm(algorithm : String | Nil) : OpenSSL::Algorithm
Source
load_hmac_headers(context) : Hash(String, String | Nil)

Load the required headers from the request for hmac authentication

Source
load_secrets(client : String) : Array(String)

Load the secrets for the given client Returns an array of strings (secrets) with all posible secrets for the given client (BLUE + GREEN)

Source
normalize_client_hash(dict : Hash(String, Array(String))) : Hash(String, Array(String))

A helper method to upcase all the keys in a dictionary This ensures that client names passed in via headers exactly match the keys in the secrets cache

Source
recent_timestamp?(timestamp : String, seconds : Int32) : NamedTuple(valid: Bool, message: String)

Check if the timestamp is within the last seconds seconds and not in the future Timestamps should only be in UTC iso8601 format: 2022-09-27 18:00:00.000 Used to protect against replay attacks

Source
valid_token?(request_token, secret, client, path, timestamp)

Check the request token by building our own with our known metadata and secret request_token token provided in request secret secret used to build token client client name used to build token path path used to build token timestamp timestamp used to build token returns True if token matches, False otherwise

Source
validate_hmac_headers(headers : Hash(String, String | Nil)) : Array(Array(String))

If any of the required headers are missing or empty, return the missing or empty headers

Source