Browse Source

Move the NWebsec module from OpenIddict.Mvc to a new project and make security headers customizable

pull/60/head
David McCullough 10 years ago
committed by Kévin Chalet
parent
commit
dad1b307b8
  1. 7
      OpenIddict.sln
  2. 16
      samples/Mvc.Server/Startup.cs
  3. 2
      src/OpenIddict.Core/OpenIddictBuilder.cs
  4. 13
      src/OpenIddict.Core/OpenIddictExtensions.cs
  5. 28
      src/OpenIddict.Mvc/OpenIddictExtensions.cs
  6. 6
      src/OpenIddict.Mvc/project.json
  7. 25
      src/OpenIddict.Security/OpenIddict.Security.xproj
  8. 50
      src/OpenIddict.Security/OpenIddictExtensions.cs
  9. 22
      src/OpenIddict.Security/project.json
  10. 4
      src/OpenIddict/OpenIddictExtensions.cs
  11. 1
      src/OpenIddict/project.json

7
OpenIddict.sln

@ -27,6 +27,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "external", "external", "{DE
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NWebsec", "external\NWebsec\NWebsec.xproj", "{38C8E88F-1D01-466F-B47D-6D67F13C1594}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "OpenIddict.Security", "src\OpenIddict.Security\OpenIddict.Security.xproj", "{3744B1BC-3498-4958-B020-B2688A78B989}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -69,6 +71,10 @@ Global
{38C8E88F-1D01-466F-B47D-6D67F13C1594}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38C8E88F-1D01-466F-B47D-6D67F13C1594}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38C8E88F-1D01-466F-B47D-6D67F13C1594}.Release|Any CPU.Build.0 = Release|Any CPU
{3744B1BC-3498-4958-B020-B2688A78B989}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3744B1BC-3498-4958-B020-B2688A78B989}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3744B1BC-3498-4958-B020-B2688A78B989}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3744B1BC-3498-4958-B020-B2688A78B989}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -83,5 +89,6 @@ Global
{E60CF8CA-6313-4359-BE43-AFCBB927EA30} = {D544447C-D701-46BB-9A5B-C76C612A596B}
{7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84} = {D544447C-D701-46BB-9A5B-C76C612A596B}
{38C8E88F-1D01-466F-B47D-6D67F13C1594} = {DE26CC68-28BA-44BB-B28E-43B949C6C606}
{3744B1BC-3498-4958-B020-B2688A78B989} = {D544447C-D701-46BB-9A5B-C76C612A596B}
EndGlobalSection
EndGlobal

16
samples/Mvc.Server/Startup.cs

@ -10,9 +10,11 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Mvc.Server.Models;
using Mvc.Server.Services;
using NWebsec.Middleware;
using OpenIddict;
using OpenIddict.Models;
namespace Mvc.Server {
public class Startup {
public static void Main(string[] args) {
@ -92,7 +94,19 @@ namespace Mvc.Server {
// Note: OpenIddict must be added after
// ASP.NET Identity and the external providers.
app.UseOpenIddict();
app.UseOpenIddict(options => {
// You can customize the default Content Security Policy (CSP) by calling UseNWebsec explicitly.
// This can be useful to allow your HTML views to reference remote scripts/images/styles.
options.UseNWebsec(directives => {
directives.DefaultSources(directive => directive.Self())
.ImageSources(directive => directive.Self().CustomSources("*"))
.ScriptSources(directive => directive
.Self()
.UnsafeInline()
.CustomSources("https://my.custom.url"))
.StyleSources(directive => directive.Self().UnsafeInline());
});
});
app.UseMvcWithDefaultRoute();

2
src/OpenIddict.Core/OpenIddictBuilder.cs

@ -3,7 +3,7 @@ using OpenIddict;
namespace Microsoft.AspNet.Builder {
/// <summary>
/// Holds various properties allowing to configure OpenIddct.
/// Holds various properties allowing to configure OpenIddict.
/// </summary>
public class OpenIddictBuilder {
/// <summary>

13
src/OpenIddict.Core/OpenIddictExtensions.cs

@ -49,9 +49,10 @@ namespace Microsoft.AspNet.Builder {
[NotNull] this OpenIddictBuilder builder,
[NotNull] string name, int position,
[NotNull] Action<IApplicationBuilder> registration) {
// By default, prevent duplicate registrations.
if (builder.Modules.Any(module => string.Equals(module.Name, name))) {
return builder;
// Note: always call ToArray to make sure the foreach
// block doesn't iterate on the modified collection.
foreach (var module in builder.Modules.Where(module => string.Equals(module.Name, name)).ToArray()) {
builder.Modules.Remove(module);
}
builder.Modules.Add(new OpenIddictModule {
@ -81,12 +82,6 @@ namespace Microsoft.AspNet.Builder {
configuration(builder);
builder.AddModule("CORS", -10, map => map.UseCors(options => {
options.AllowAnyHeader();
options.AllowAnyMethod();
options.AllowAnyOrigin();
options.AllowCredentials();
}));
// Add OpenIdConnectServerMiddleware to the ASP.NET 5 pipeline.
builder.AddModule("ASOS", 0, map => map.UseOpenIdConnectServer(builder.Options));

28
src/OpenIddict.Mvc/OpenIddictExtensions.cs

@ -13,36 +13,14 @@ using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Mvc.ApplicationModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Internal;
using NWebsec.Middleware;
using OpenIddict;
using OpenIddict.Mvc;
namespace Microsoft.AspNet.Builder {
public static class OpenIddictExtensions {
public static OpenIddictBuilder UseMvc([NotNull] this OpenIddictBuilder builder) {
builder.AddModule("NWebsec", -20, app => {
// Insert a new middleware responsible of setting the Content-Security-Policy header.
// See https://nwebsec.codeplex.com/wikipage?title=Configuring%20Content%20Security%20Policy&referringTitle=NWebsec
app.UseCsp(options => options.DefaultSources(directive => directive.Self())
.ImageSources(directive => directive.Self().CustomSources("*"))
.ScriptSources(directive => directive.Self().UnsafeInline())
.StyleSources(directive => directive.Self().UnsafeInline()));
// Insert a new middleware responsible of setting the X-Content-Type-Options header.
// See https://nwebsec.codeplex.com/wikipage?title=Configuring%20security%20headers&referringTitle=NWebsec
app.UseXContentTypeOptions();
// Insert a new middleware responsible of setting the X-Frame-Options header.
// See https://nwebsec.codeplex.com/wikipage?title=Configuring%20security%20headers&referringTitle=NWebsec
app.UseXfo(options => options.Deny());
// Insert a new middleware responsible of setting the X-Xss-Protection header.
// See https://nwebsec.codeplex.com/wikipage?title=Configuring%20security%20headers&referringTitle=NWebsec
app.UseXXssProtection(options => options.EnabledWithBlockMode());
});
// Run the rest of the pipeline in an isolated environment.
builder.AddModule("MVC", 10, app => app.Isolate(map => map.UseMvc(routes => {
// Run MVC in an isolated environment.
return builder.AddModule("MVC", 10, app => app.Isolate(map => map.UseMvc(routes => {
// Register the actions corresponding to the authorization endpoint.
if (builder.Options.AuthorizationEndpointPath.HasValue) {
routes.MapRoute("{D97891B4}", builder.Options.AuthorizationEndpointPath.Value.Substring(1), new {
@ -110,8 +88,6 @@ namespace Microsoft.AspNet.Builder {
// Register the options in the isolated container.
services.AddScoped(provider => builder.Options);
}));
return builder;
}
private class OpenIddictConvention : IControllerModelConvention {

6
src/OpenIddict.Mvc/project.json

@ -17,12 +17,6 @@
"version": "1.0.0-*"
},
"NWebsec": {
"type": "build",
"version": "1.0.0-internal-*",
"target": "project"
},
"OpenIddict.Core": "1.0.0-*"
},

25
src/OpenIddict.Security/OpenIddict.Security.xproj

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>3744b1bc-3498-4958-b020-b2688a78b989</ProjectGuid>
<RootNamespace>OpenIddict.Security</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<DnxInvisibleContent Include="bower.json" />
<DnxInvisibleContent Include=".bowerrc" />
<DnxInvisibleContent Include="package.json" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

50
src/OpenIddict.Security/OpenIddictExtensions.cs

@ -0,0 +1,50 @@
using System;
using Microsoft.Extensions.Internal;
using NWebsec.Middleware;
namespace Microsoft.AspNet.Builder {
public static class OpenIddictExtensions {
public static OpenIddictBuilder UseNWebsec([NotNull] this OpenIddictBuilder builder) {
return builder.UseNWebsec(options => {
options.DefaultSources(directive => directive.Self())
.ImageSources(directive => directive.Self().CustomSources("*"))
.ScriptSources(directive => directive.Self().UnsafeInline())
.StyleSources(directive => directive.Self().UnsafeInline());
});
}
public static OpenIddictBuilder UseNWebsec(
[NotNull] this OpenIddictBuilder builder,
[NotNull] Action<IFluentCspOptions> configuration) {
return builder.AddModule("NWebsec", -20, app => {
// Insert a new middleware responsible of setting the Content-Security-Policy header.
// See https://nwebsec.codeplex.com/wikipage?title=Configuring%20Content%20Security%20Policy&referringTitle=NWebsec
app.UseCsp(configuration);
// Insert a new middleware responsible of setting the X-Content-Type-Options header.
// See https://nwebsec.codeplex.com/wikipage?title=Configuring%20security%20headers&referringTitle=NWebsec
app.UseXContentTypeOptions();
// Insert a new middleware responsible of setting the X-Frame-Options header.
// See https://nwebsec.codeplex.com/wikipage?title=Configuring%20security%20headers&referringTitle=NWebsec
app.UseXfo(options => options.Deny());
// Insert a new middleware responsible of setting the X-Xss-Protection header.
// See https://nwebsec.codeplex.com/wikipage?title=Configuring%20security%20headers&referringTitle=NWebsec
app.UseXXssProtection(options => options.EnabledWithBlockMode());
});
}
public static OpenIddictBuilder UseCors([NotNull] this OpenIddictBuilder builder) {
//Add CORS to the app
builder.AddModule("CORS", -10, map => map.UseCors(options => {
options.AllowAnyHeader();
options.AllowAnyMethod();
options.AllowAnyOrigin();
options.AllowCredentials();
}));
return builder;
}
}
}

22
src/OpenIddict.Security/project.json

@ -0,0 +1,22 @@
{
"version": "1.0.0-*",
"description": "Security headers module for OpenIddict.",
"dependencies": {
"OpenIddict.Core": "1.0.0-*",
"NWebsec": {
"type": "build",
"version": "1.0.0-internal-*"
},
"Microsoft.Extensions.NotNullAttribute.Sources": {
"type": "build",
"version": "1.0.0-*"
}
},
"frameworks": {
"dnx451": { },
"dnxcore50": { }
}
}

4
src/OpenIddict/OpenIddictExtensions.cs

@ -34,8 +34,8 @@ namespace Microsoft.AspNet.Builder {
[NotNull] this IApplicationBuilder app,
[NotNull] Action<OpenIddictBuilder> configuration) {
return app.UseOpenIddictCore(builder => {
// By default, both the assets
// and the MVC modules are enabled.
builder.UseNWebsec();
builder.UseCors();
builder.UseAssets();
builder.UseMvc();

1
src/OpenIddict/project.json

@ -7,6 +7,7 @@
"OpenIddict.Assets": "1.0.0-*",
"OpenIddict.EF": "1.0.0-*",
"OpenIddict.Mvc": "1.0.0-*",
"OpenIddict.Security": "1.0.0-*",
"Microsoft.Extensions.NotNullAttribute.Sources": {
"type": "build",

Loading…
Cancel
Save