Skip to content

Verifying signatures basics

David Lievrouw edited this page Aug 31, 2022 · 12 revisions

This page describes the verify signatures basics.

Header

The receiving party (the server) needs to verify the signature of the received request. It does this by inspecting the Authorization header of the incoming request.

An example value:

Authorization: Signature keyId="e0e8dcd638334c409e1b88daf821d135",algorithm="hs2019",created=1584806516,expires=1584806576,headers="(request-target) dalion-app-id date digest",nonce="38brRy8BLUajMbUqWumXPg",signature="DUKQVjiirGMMaMOy9qIwKMro46R3BlLsvUQkw1/8sKQ="

Verification

The authorization header contains a KeyId, which the server can use to identity the client that is sending the request. In its configuration, it can query the configuration of the client, so that signature verification can occur.

Verification occurs by recalculating the signature, based on the incoming request and the signing settings of the client. When the calculated signature matches the one that is in the incoming request, the signature is considered to be verified.

Upon successful verification, a response is returned that contains a ClaimsPrincipal. The ClaimsPrincipal will contain a number of claims:

  • appId: The KeyId of the client for which the signature was verified.
  • name: The descriptive name of the client, as configured in the Client settings.
  • version: The version number of the signature verification library that performed the verification.
  • Any additional claims that you configured in the Client settings.

Upon failed verification, a response is returned that contains the cause of the failure. This is useful for logging purposes. Web applications should return a 401 - Unauthorized response code, including a WWW-Authenticate header.

We created authentication middleware for ASP.NET Core and OWIN.

URI escaping

By default, when creating the signature string to verify, the value of the (request-target) pseudo-header is escaped according to RFC 3986. You can configure this behavior, as it is an option of the Client class.

There are several escaping methods available:

  • RFC3986: The default option. The (request-target) will be escaped according to RFC 3986.
  • RFC2396: RFC 2396, obsoleted by RFC 3986.
  • Unescaped: Any escaping of the value of the (request-target) pseudo-header will be removed.
  • OriginalString: This library will not perform any escaping for you, you take matters into your own hands.

Using OriginalString can be useful when verifying signatures for 3rd party signers, that apply a specific form of escaping that is not covered by any of the other available options.

Digest header

This library has the ability to verify that the request body has not been tampered with. It uses a Digest header for this.

Digest: SHA-256=RA1E8y/pYWwNhV2Emk+DxFNr9m9P4N/SlMsEOBfgsGc=

When the client sends a Digest header with the request, and it is part of the verified Headers (according to the Authorization header value), this value will also be verified.

Logging

Several services have an optional dependency to ILogger<T>, of the Microsoft.Extensions.Logging package. When logging is configured in a consuming application, messages about the signing and verifying of requests will be logged.

This configuration is optional, signing and verifying will not throw an Exception when the logging configuration is missing.

You can wire up a logging framework of your choice in the consuming application.

More information about logging in .NET Core.

Nonce

A client has the option to specify a Nonce value.

nonce="38brRy8BLUajMbUqWumXPg"

This value is used by the server to prevent replay attacks. The server will accept a nonce value only once. When it is received again, the server will reject the signature.

The client is expected to make this value part of the signature string hash, so that it cannot be modified by a malicious party.

This is an optional feature. When the client does not specify a nonce value, this check does not occur.

The time span during which a nonce value is considered to be blocked, is configured when you configure a known Client.

Samples

Samples are available in the repository source:

Contribute.