Skip to content

Verifying signatures in an OWIN application

David Lievrouw edited this page Feb 6, 2024 · 10 revisions

This page describes the configuration required to verify signatures in an OWIN application.

Installation

dotnet add package Dalion.HttpMessageSigning.Verification.Owin

or

PM> Install-Package Dalion.HttpMessageSigning.Verification.Owin

Configuration

Create a class that builds an IoC container, using the Microsoft.Extensions.DependencyInjection package. An example:

public static class IocStartup {
    public static IServiceProvider BuildServiceProvider() {
        var services = new ServiceCollection();

        services
            ...
            .AddHttpMessageSignatureVerification()
            .UseOwinSignatureVerification()
            .UseClient(
                Client.Create(
                    new KeyId("e0e8dcd638334c409e1b88daf821d135"),
                    "Sample client",
                    SignatureAlgorithm.CreateForVerification(hmacSecret: "yumACY64r%hm"))
            );

        return services.BuildServiceProvider();
    }
}

This code sample performs the minimum registrations in order to get things working:

  • It registers the Client using the default options.
  • It uses an in-memory IClientStore instance.

There are several implementations of the IClientStore. The InMemoryClientStore in included in the Verification core package. Call the .UseClientStore method during composition, to select another IClientStore implementation. You can also roll your own, by implementing the interface. Contributions are appreciated.

There are several convenience overloads of the Client.Create factory method. Use the one that suits your needs best.

The following example registers the authentication middleware in the OWIN pipeline, and adds some callbacks for logging:

public void Configuration(IAppBuilder app) {
    var iocContainer = IocStartup.BuildServiceProvider();
    
    app
        .UseHttpRequestSignatureAuthentication(new SignedHttpRequestAuthenticationOptions {
            Realm = "Sample OWIN application",
            RequestSignatureVerifier = iocContainer.GetRequiredService<IRequestSignatureVerifier>(),
            OnIdentityVerified = successResult => {
                var identity = (ClaimsIdentity) successResult.Principal.Identity;
                Console.WriteLine("Identity '{0}' was authenticated by the request signature.", identity.Name ?? "[NULL]");
                return Task.CompletedTask;
            },
            OnIdentityVerificationFailed = failure => {
                Console.WriteLine("The request signature could not be verified. Authentication failed: {0}", failure.SignatureVerificationException.Message);
                return Task.CompletedTask;
            }
        })
		...
}

The Realm and RequestSignatureVerifier properties are required. The registered callbacks are optional.

Usage

The above configuration enables custom authentication middleware in the OWIN pipeline.

In this example, we use ASP.NET WebApi to define our endpoints. Because of the Authorize attribute, access is only granted for requests that have a valid signature.

[Authorize]
public class UserInfoController : ApiController {
    public IHttpActionResult Get() {
        var authenticatedUser = User as ClaimsPrincipal;		
        return Ok(authenticatedUser.Claims.Select(c => new {c.Type, c.Value}));
    }
}

When the signature verification succeeds, an AuthenticationTicket with an authenticated ClaimsPrincipal is produced.

When the signature verification fails, a 401 - Unauthorized response code is returned, including a WWW-Authenticate header.

Samples

A sample is available in the repository source: OWIN web application (.NET Framework 4.8)

Clone this wiki locally