diff --git a/OpenIddict.sln b/OpenIddict.sln
index d9c82fb6..49bf3dab 100644
--- a/OpenIddict.sln
+++ b/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
diff --git a/samples/Mvc.Server/Startup.cs b/samples/Mvc.Server/Startup.cs
index 6fe79697..256798bb 100644
--- a/samples/Mvc.Server/Startup.cs
+++ b/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();
diff --git a/src/OpenIddict.Core/OpenIddictBuilder.cs b/src/OpenIddict.Core/OpenIddictBuilder.cs
index 02b3b543..87e42042 100644
--- a/src/OpenIddict.Core/OpenIddictBuilder.cs
+++ b/src/OpenIddict.Core/OpenIddictBuilder.cs
@@ -3,7 +3,7 @@ using OpenIddict;
namespace Microsoft.AspNet.Builder {
///
- /// Holds various properties allowing to configure OpenIddct.
+ /// Holds various properties allowing to configure OpenIddict.
///
public class OpenIddictBuilder {
///
diff --git a/src/OpenIddict.Core/OpenIddictExtensions.cs b/src/OpenIddict.Core/OpenIddictExtensions.cs
index b7846519..ce930ef4 100644
--- a/src/OpenIddict.Core/OpenIddictExtensions.cs
+++ b/src/OpenIddict.Core/OpenIddictExtensions.cs
@@ -49,9 +49,10 @@ namespace Microsoft.AspNet.Builder {
[NotNull] this OpenIddictBuilder builder,
[NotNull] string name, int position,
[NotNull] Action 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));
diff --git a/src/OpenIddict.Mvc/OpenIddictExtensions.cs b/src/OpenIddict.Mvc/OpenIddictExtensions.cs
index 696ecce7..cf5f751d 100644
--- a/src/OpenIddict.Mvc/OpenIddictExtensions.cs
+++ b/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 {
diff --git a/src/OpenIddict.Mvc/project.json b/src/OpenIddict.Mvc/project.json
index 1c117790..5168cbe2 100644
--- a/src/OpenIddict.Mvc/project.json
+++ b/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-*"
},
diff --git a/src/OpenIddict.Security/OpenIddict.Security.xproj b/src/OpenIddict.Security/OpenIddict.Security.xproj
new file mode 100644
index 00000000..ef5bd5ca
--- /dev/null
+++ b/src/OpenIddict.Security/OpenIddict.Security.xproj
@@ -0,0 +1,25 @@
+
+
+
+ 14.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+
+
+ 3744b1bc-3498-4958-b020-b2688a78b989
+ OpenIddict.Security
+ ..\..\artifacts\obj\$(MSBuildProjectName)
+ ..\..\artifacts\bin\$(MSBuildProjectName)\
+
+
+
+ 2.0
+
+
+
+
+
+
+
+
diff --git a/src/OpenIddict.Security/OpenIddictExtensions.cs b/src/OpenIddict.Security/OpenIddictExtensions.cs
new file mode 100644
index 00000000..bda7d6e6
--- /dev/null
+++ b/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 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;
+ }
+ }
+}
diff --git a/src/OpenIddict.Security/project.json b/src/OpenIddict.Security/project.json
new file mode 100644
index 00000000..32fa44fa
--- /dev/null
+++ b/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": { }
+ }
+}
diff --git a/src/OpenIddict/OpenIddictExtensions.cs b/src/OpenIddict/OpenIddictExtensions.cs
index 6d5167d7..52ab7e86 100644
--- a/src/OpenIddict/OpenIddictExtensions.cs
+++ b/src/OpenIddict/OpenIddictExtensions.cs
@@ -34,8 +34,8 @@ namespace Microsoft.AspNet.Builder {
[NotNull] this IApplicationBuilder app,
[NotNull] Action configuration) {
return app.UseOpenIddictCore(builder => {
- // By default, both the assets
- // and the MVC modules are enabled.
+ builder.UseNWebsec();
+ builder.UseCors();
builder.UseAssets();
builder.UseMvc();
diff --git a/src/OpenIddict/project.json b/src/OpenIddict/project.json
index a2d6756f..6380531a 100644
--- a/src/OpenIddict/project.json
+++ b/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",