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.