Skip to content

Super Duper Happy Paths

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

This page describes the Super-Duper-Happy-Paths.

(Credits to NancyFx for coining the term)

Signing

Add the Dalion.HttpMessageSigning.Signing package to your project:

dotnet add package Dalion.HttpMessageSigning.Signing

Register the package in your IoC container. This example uses Microsoft.Extensions.DependencyInjection:

var services = new ServiceCollection()
    .AddHttpMessageSigning()
    ...

Instantiate an IRequestSigner by using the registered IRequestSignerFactory:

var signerFactory = provider.GetRequiredService<IRequestSignerFactory>();

var signer = signerFactory.Create(keyId, new SigningSettings {
    SignatureAlgorithm = SignatureAlgorithm.CreateForSigning(hmacSecret: "s3cr3t")
});

Sign a HttpRequestMessage using the created IRequestSigner:

var httpRequest = new HttpRequestMessage(HttpMethod.Get, "https://www.dalion.eu");
await signer.Sign(httpRequest);

Here is the complete sample:

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Dalion.HttpMessageSigning;
using Dalion.HttpMessageSigning.Signing;
using Microsoft.Extensions.DependencyInjection;

namespace SuperDuperHappySigner {
    internal class Program {
        private static async Task Main(string[] args) {
            var keyId = "91533c57807640579af1482d94faafe3";
            
            var services = new ServiceCollection()
                .AddHttpMessageSigning().Services;

            using (var provider = services.BuildServiceProvider()) {
                var signerFactory = provider.GetRequiredService<IRequestSignerFactory>();
                var signer = signerFactory.Create(keyId, new SigningSettings {
                    SignatureAlgorithm = SignatureAlgorithm.CreateForSigning(hmacSecret: "s3cr3t")
                });
                
                var httpRequest = new HttpRequestMessage(HttpMethod.Get, "https://www.dalion.eu");
                await signer.Sign(httpRequest);

                var authorizationHeader = httpRequest.Headers.Authorization;
                Console.WriteLine("{0} {1}", authorizationHeader!.Scheme, authorizationHeader!.Parameter);
            }
        }
    }
}

See the Super-Duper-Happy-Signer sample project.

Verifying signatures in an ASP.NET Core application

Add the Dalion.HttpMessageSigning.Verification.AspNetCore package to your project:

dotnet add package Dalion.HttpMessageSigning.Verification.AspNetCore

Add the following to your IoC container. It enables ASP.NET Core support, and registers a single Client with default ClientOptions. There should be at least one Client. Otherwise, there is nothing to verify for.

This example uses Microsoft.Extensions.DependencyInjection:

public static void ConfigureServices(IServiceCollection services) {
    services
        ...
        // Register required services
        .AddHttpMessageSignatureVerification()
        .UseAspNetCoreSignatureVerification()
        .UseClient(
            Client.Create(
                new KeyId("e0e8dcd638334c409e1b88daf821d135"),
                "Sample client",
                SignatureAlgorithm.CreateForVerification(hmacSecret: "yumACY64r%hm"))
        )
	      // Add registrations for authentication middleware
        .AddAuthentication(SignedHttpRequestDefaults.AuthenticationScheme)
        .AddSignedRequests(options => {
            options.Realm = "Sample web application";
        });
}

Don't forget to add the authentication and authorization middleware in your application:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    app
        ...
        // Very important that the following is added to the pipeline, before any middleware that requires authentication.
        .UseAuthentication()
        .UseAuthorization()
        ...
        .UseEndpoints(endpoints => { endpoints.MapControllers(); });
}

You can now use the AuthorizeAttribute on your controllers and endpoints:

[Route("api")]
[Authorize]
public class ApiController : Controller {
    [HttpGet("")]
    [Produces(MediaTypeNames.Text.Plain)]
    public IActionResult Home() {
        return Ok("Hi!");
    }
}

This is basically the contents of the ASP.NET Core web application sample.

Verifying signatures in an Owin application

Add the Dalion.HttpMessageSigning.Verification.Owin package to your project:

dotnet add package Dalion.HttpMessageSigning.Verification.Owin

Add the following to your IoC container. It enables Owin support, and registers a single Client with default ClientOptions. There should be at least one Client. Otherwise, there is nothing to verify for.

This example uses Microsoft.Extensions.DependencyInjection:

public static IServiceCollection ConfigureServices(this IServiceCollection services) {
    return services
        ...
        .AddHttpMessageSignatureVerification()
        .UseOwinSignatureVerification()
        .UseClient(
            Client.Create(
                new KeyId("e0e8dcd638334c409e1b88daf821d135"),
                "Sample client",
                SignatureAlgorithm.CreateForVerification(hmacSecret: "yumACY64r%hm"))
        );
}

Register the authentication middleware in the OWIN pipeline:

public void Configuration(IAppBuilder app) {
    var provider = new ServiceCollection().ConfigureServices().BuildServiceProvider();
    
    app
        .UseHttpRequestSignatureAuthentication(new SignedHttpRequestAuthenticationOptions {
            Realm = "Sample OWIN application",
            RequestSignatureVerifier = provider.GetRequiredService<IRequestSignatureVerifier>()
        })
        ...
}

You can now use the AuthorizeAttribute on your controllers and endpoints:

[Authorize]
public class UserInfoController : ApiController {
    public IHttpActionResult Home() {
        return Ok("Hi!");
    }
}

This is basically the contents of the OWIN web application (.NET Framework 4.8) sample.

Clone this wiki locally