1
votes

I am implementing a custom owin middleware to add CSP header (content security policy) in response header. For CSP to work, the middleware needs to create a unique nonce value per request. So i have NonceService which creates nonce value. The custom OWIN middleware has dependency on NonceService.

However my problem is i'm not able to register custom middleware per request.

When i debug i noticed OWIN is NOT creating new instance of custom middleware per request and because of that same nonce value is being used for all the requests.

Below is my code

Nonce Service

public interface INonceService
{
    string GetNonce();
}

public class NonceService : INonceService
{
     private static readonly RNGCryptoServiceProvider _rng = new RNGCryptoServiceProvider();
    private readonly string _nonce;

    public NonceService(int nonceByteAmount = 32)
    {
        var nonceBytes = new byte[nonceByteAmount];
        _rng.GetBytes(nonceBytes);
        _nonce = Convert.ToBase64String(nonceBytes);
    }

    public string GetNonce()
    {
        return _nonce;
    }
}

OWIN Middleware & Extension

public class SecurityHeaderMiddleware : OwinMiddleware
{
    private readonly INonceService _nonceService = null;
    public SecurityHeaderMiddleware(OwinMiddleware next, INonceService nonceService) : base(next)
    {
        _nonceService = nonceService;
    }

    public override async Task Invoke(IOwinContext context)
    {
        await Next.Invoke(context);

        var nonce = _nonceService.GetNonce();
        var csp = BuildCSPHeader(nonce);
        context.Response.Headers.Add(key, csp);
    }
}

public static class OwinExtensions
{
    private const string SecurityHeaderRegistrationKey = "SecurityHeaders";

    public static IAppBuilder UseSecurityHeader(this IAppBuilder app, INonceService nonceService)
    {
        if (app == null)
            throw new ArgumentNullException("app");

        if (app.Properties.ContainsKey(SecurityHeaderRegistrationKey))
            return app;

        app.Use<SecurityHeaderMiddleware>(nonceService);
        app.Properties.Add(SecurityHeaderRegistrationKey, true);
        return app;
    }
}

I am using Unity as conatiner, so i register INonceService using PerRequestLifetimeManager

container.RegisterType<INonceService, NonceService>(new PerRequestLifetimeManager(), new InjectionConstructor(32));

and i register my custom middleware with OWIN in startup.cs

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    { 
        var nonceService = ServiceLocator.Current.GetInstance<INonceService>();
        app.UseSecurityHeader(nonceService);
    }
}

Note If creating per request OWIN middleware is not possible then at least how should i pass per request new instance of NonceService to middleware.

1

1 Answers

0
votes

Looking at the stack trace upon a null reference exception for HttpContext that I received, it seems that middleware is constructed in BuildWebHost from Main.

I'm using Unity too, so I changed my constructor dependency from...

IUserRepository userRepository

to

Func<IUserRepository> userRepositoryFactory

and my method call from...

userRepository.FetchLoggedInUser(userIdentifier);

to

userRepositoryFactory().FetchLoggedInUser(userIdentifier);

Conveniently, Unity automatically generates a factory, so there's no need to edit the registrations.