diff --git a/OpenIddict.sln b/OpenIddict.sln index d35800a1..c6de4b5a 100644 --- a/OpenIddict.sln +++ b/OpenIddict.sln @@ -21,6 +21,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "OpenIddict.EF", "src\OpenId EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "OpenIddict.Core", "src\OpenIddict.Core\OpenIddict.Core.xproj", "{E60CF8CA-6313-4359-BE43-AFCBB927EA30}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "OpenIddict.Mvc", "src\OpenIddict.Mvc\OpenIddict.Mvc.xproj", "{7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -55,6 +57,10 @@ Global {E60CF8CA-6313-4359-BE43-AFCBB927EA30}.Debug|Any CPU.Build.0 = Debug|Any CPU {E60CF8CA-6313-4359-BE43-AFCBB927EA30}.Release|Any CPU.ActiveCfg = Release|Any CPU {E60CF8CA-6313-4359-BE43-AFCBB927EA30}.Release|Any CPU.Build.0 = Release|Any CPU + {7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -67,5 +73,6 @@ Global {79AE02C3-2AB4-4495-BEDD-685A714EA51C} = {D544447C-D701-46BB-9A5B-C76C612A596B} {D2450929-ED0E-420D-B475-327924F9701C} = {D544447C-D701-46BB-9A5B-C76C612A596B} {E60CF8CA-6313-4359-BE43-AFCBB927EA30} = {D544447C-D701-46BB-9A5B-C76C612A596B} + {7AE46E2F-E93B-4FF9-B941-6CD7A3E1BF84} = {D544447C-D701-46BB-9A5B-C76C612A596B} EndGlobalSection EndGlobal diff --git a/src/OpenIddict.Assets/OpenIddictExtensions.cs b/src/OpenIddict.Assets/OpenIddictExtensions.cs new file mode 100644 index 00000000..adfd7431 --- /dev/null +++ b/src/OpenIddict.Assets/OpenIddictExtensions.cs @@ -0,0 +1,22 @@ +/* + * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) + * See https://github.com/openiddict/core for more information concerning + * the license and the contributors participating to this project. + */ + +using System.Reflection; +using Microsoft.AspNet.FileProviders; +using Microsoft.AspNet.StaticFiles; +using Microsoft.Extensions.Internal; + +namespace Microsoft.AspNet.Builder { + public static class OpenIddictExtensions { + public static OpenIddictBuilder UseAssets([NotNull] this OpenIddictBuilder builder) { + return builder.AddModule(-20, app => app.UseStaticFiles(new StaticFileOptions { + FileProvider = new EmbeddedFileProvider( + assembly: Assembly.Load(new AssemblyName("OpenIddict.Assets")), + baseNamespace: "OpenIddict.Assets") + })); + } + } +} \ No newline at end of file diff --git a/src/OpenIddict.Assets/project.json b/src/OpenIddict.Assets/project.json index 016d2525..29b25b7a 100644 --- a/src/OpenIddict.Assets/project.json +++ b/src/OpenIddict.Assets/project.json @@ -1,8 +1,22 @@ { "version": "1.0.0-alpha1-*", + "description": "Contains the default assets used by OpenIddict.", + "resource": [ "fonts/*", "scripts/*", "stylesheets/*" ], + "dependencies": { + "Microsoft.AspNet.FileProviders.Embedded": "1.0.0-*", + "Microsoft.AspNet.StaticFiles": "1.0.0-*", + + "Microsoft.Extensions.NotNullAttribute.Sources": { + "type": "build", + "version": "1.0.0-*" + }, + + "OpenIddict.Core": "1.0.0-*" + }, + "frameworks": { "dnx451": { }, diff --git a/src/OpenIddict.Core/OpenIddictBuilder.cs b/src/OpenIddict.Core/OpenIddictBuilder.cs index 9213149a..49a31ccf 100644 --- a/src/OpenIddict.Core/OpenIddictBuilder.cs +++ b/src/OpenIddict.Core/OpenIddictBuilder.cs @@ -1,4 +1,5 @@ -using OpenIddict; +using System.Collections.Generic; +using OpenIddict; namespace Microsoft.AspNet.Builder { /// @@ -10,6 +11,11 @@ namespace Microsoft.AspNet.Builder { Options = new OpenIddictOptions(); } + /// + /// Gets the list of the OpenIddict modules. + /// + public ICollection Modules { get; } = new List(); + /// /// Gets or sets the options used by OpenIddict. /// diff --git a/src/OpenIddict.Core/OpenIddictExtensions.cs b/src/OpenIddict.Core/OpenIddictExtensions.cs index 927b4161..704a8064 100644 --- a/src/OpenIddict.Core/OpenIddictExtensions.cs +++ b/src/OpenIddict.Core/OpenIddictExtensions.cs @@ -5,25 +5,19 @@ */ using System; -using System.Diagnostics; -using System.Reflection; +using System.Linq; using AspNet.Security.OpenIdConnect.Server; -using Microsoft.AspNet.FileProviders; using Microsoft.AspNet.Hosting; -using Microsoft.AspNet.Http; using Microsoft.AspNet.Identity; -using Microsoft.AspNet.StaticFiles; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Internal; using OpenIddict; -#if DNX451 -using NWebsec.Owin; -#endif - namespace Microsoft.AspNet.Builder { public static class OpenIddictExtensions { - public static OpenIddictServices AddOpenIddictCore([NotNull] this IdentityBuilder builder) + public static IdentityBuilder AddOpenIddictCore( + [NotNull] this IdentityBuilder builder, + [NotNull] Action configuration) where TApplication : class { builder.Services.AddAuthentication(); builder.Services.AddCaching(); @@ -45,14 +39,27 @@ namespace Microsoft.AspNet.Builder { builder.Services.AddInstance(services); - return services; + configuration(services); + + return builder; + } + + public static OpenIddictBuilder AddModule( + [NotNull] this OpenIddictBuilder builder, int position, + [NotNull] Action registration) { + builder.Modules.Add(new OpenIddictModule { + Position = position, + Registration = registration + }); + + return builder; } - public static IApplicationBuilder UseOpenIddict([NotNull] this IApplicationBuilder app) { - return app.UseOpenIddict(options => { }); + public static IApplicationBuilder UseOpenIddictCore([NotNull] this IApplicationBuilder app) { + return app.UseOpenIddictCore(options => { }); } - public static IApplicationBuilder UseOpenIddict( + public static IApplicationBuilder UseOpenIddictCore( [NotNull] this IApplicationBuilder app, [NotNull] Action configuration) { var builder = new OpenIddictBuilder(app); @@ -63,118 +70,29 @@ namespace Microsoft.AspNet.Builder { configuration(builder); - if (!builder.Options.UseCustomViews) { - app.UseStaticFiles(new StaticFileOptions { - FileProvider = new EmbeddedFileProvider( - assembly: Assembly.Load(new AssemblyName("OpenIddict.Assets")), - baseNamespace: "OpenIddict.Assets") - }); - } - - app.UseCors(options => { + builder.AddModule(-10, map => map.UseCors(options => { options.AllowAnyHeader(); options.AllowAnyMethod(); options.AllowAnyOrigin(); options.AllowCredentials(); - }); + })); // Add OpenIdConnectServerMiddleware to the ASP.NET 5 pipeline. - app.UseOpenIdConnectServer(options => { + builder.AddModule(0, map => map.UseOpenIdConnectServer(options => { options.Options = builder.Options; options.Provider = app.ApplicationServices.GetRequiredService(); - }); + })); -#if DNX451 - app.UseKatana(owin => { - // 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 - owin.UseCsp(options => options.DefaultSources(directive => directive.Self()) - .ImageSources(directive => directive.Self().CustomSources("*")) - .ScriptSources(directive => directive.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 - owin.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 - owin.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 - owin.UseXXssProtection(options => options.EnabledWithBlockMode()); - }); -#endif - - // Run the rest of the pipeline in an isolated environment. - return app.Isolate(container => container.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 { - controller = typeof(OpenIddictController<,>).Name, - action = nameof(OpenIddictController.Authorize) - }); - - routes.MapRoute("{7148DB83}", builder.Options.AuthorizationEndpointPath.Value.Substring(1) + "/accept", new { - controller = typeof(OpenIddictController<,>).Name, - action = nameof(OpenIddictController.Accept) - }); - - routes.MapRoute("{23438BCC}", builder.Options.AuthorizationEndpointPath.Value.Substring(1) + "/deny", new { - controller = typeof(OpenIddictController<,>).Name, - action = nameof(OpenIddictController.Deny) - }); + // Register the OpenIddict modules in the ASP.NET 5 pipeline. + foreach (var module in builder.Modules.OrderBy(module => module.Position)) { + if (module.Registration == null) { + throw new InvalidOperationException("The registration delegate cannot be null."); } - // Register the action corresponding to the logout endpoint. - if (builder.Options.LogoutEndpointPath.HasValue) { - routes.MapRoute("{C7DB102A}", builder.Options.LogoutEndpointPath.Value.Substring(1), new { - controller = typeof(OpenIddictController<,>).Name, - action = nameof(OpenIddictController.Logout) - }); - } - }), services => { - var instance = app.ApplicationServices.GetRequiredService(); - - services.AddMvc() - // Register the OpenIddict controller. - .AddControllersAsServices(new[] { - typeof(OpenIddictController<,>).MakeGenericType(instance.UserType, instance.ApplicationType) - }) - - // Update the Razor options to use an embedded provider - // extracting its views from the current assembly. - .AddRazorOptions(options => { - if (!builder.Options.UseCustomViews) { - options.FileProvider = new EmbeddedFileProvider( - assembly: typeof(OpenIddictOptions).GetTypeInfo().Assembly, - baseNamespace: "OpenIddict.Core"); - } - }); - - // Register the sign-in manager in the isolated container. - services.AddScoped(typeof(SignInManager<>).MakeGenericType(instance.UserType), provider => { - var accessor = provider.GetRequiredService(); - var container = (IServiceProvider) accessor.HttpContext.Items[typeof(IServiceProvider)]; - Debug.Assert(container != null); - - // Resolve the sign-in manager from the parent container. - return container.GetRequiredService(typeof(SignInManager<>).MakeGenericType(instance.UserType)); - }); - - // Register the user manager in the isolated container. - services.AddScoped(typeof(OpenIddictManager<,>).MakeGenericType(instance.UserType, instance.ApplicationType), provider => { - var accessor = provider.GetRequiredService(); - var container = (IServiceProvider) accessor.HttpContext.Items[typeof(IServiceProvider)]; - Debug.Assert(container != null); - - // Resolve the user manager from the parent container. - return container.GetRequiredService(typeof(OpenIddictManager<,>).MakeGenericType(instance.UserType, instance.ApplicationType)); - }); - - services.AddScoped(provider => builder.Options); - }); + module.Registration(app); + } + + return app; } } } \ No newline at end of file diff --git a/src/OpenIddict.Core/OpenIddictModule.cs b/src/OpenIddict.Core/OpenIddictModule.cs new file mode 100644 index 00000000..040e8ebf --- /dev/null +++ b/src/OpenIddict.Core/OpenIddictModule.cs @@ -0,0 +1,20 @@ +using System; +using Microsoft.AspNet.Builder; + +namespace OpenIddict { + /// + /// Defines an OpenIddict module. + /// + public class OpenIddictModule { + /// + /// Gets or sets the position of the module in the ASP.NET pipeline. + /// + public int Position { get; set; } + + /// + /// Gets or sets the delegate used to register + /// the OpenIddict module in the ASP.NET pipeline. + /// + public Action Registration { get; set; } + } +} diff --git a/src/OpenIddict.Core/OpenIddictOptions.cs b/src/OpenIddict.Core/OpenIddictOptions.cs index abafec80..0ca215bf 100644 --- a/src/OpenIddict.Core/OpenIddictOptions.cs +++ b/src/OpenIddict.Core/OpenIddictOptions.cs @@ -12,11 +12,5 @@ namespace OpenIddict { AuthenticationScheme = OpenIddictDefaults.AuthenticationScheme; ApplicationCanDisplayErrors = true; } - - /// - /// Set to true to allow you to use your own views/styles/scripts in your server. - /// When using custom views you MUST provide Razor views for Authorize, Logout, and SignIn actions. - /// - public bool UseCustomViews { get; set; } } } diff --git a/src/OpenIddict.Core/project.json b/src/OpenIddict.Core/project.json index 90b0bb9e..35d781d8 100644 --- a/src/OpenIddict.Core/project.json +++ b/src/OpenIddict.Core/project.json @@ -1,41 +1,26 @@ { "version": "1.0.0-alpha1-*", - "resource": "Views/**", + "description": "Core components of OpenIddict.", "dependencies": { "Microsoft.AspNet.Cors": "6.0.0-*", "Microsoft.AspNet.FileProviders.Embedded": "1.0.0-*", "Microsoft.AspNet.Identity": "3.0.0-*", - "Microsoft.AspNet.Mvc": "6.0.0-*", - "Microsoft.AspNet.StaticFiles": "1.0.0-*", - "Microsoft.Extensions.Configuration.Json": "1.0.0-*", + "Microsoft.Extensions.Configuration": "1.0.0-*", + "Microsoft.Extensions.Caching.Memory": "1.0.0-*", "Microsoft.Extensions.NotNullAttribute.Sources": { "type": "build", "version": "1.0.0-*" }, - "AspNet.Hosting.Extensions": "1.0.0-*", - "AspNet.Security.OpenIdConnect.Server": "1.0.0-*", - - "OpenIddict.Assets": "1.0.0-*" + "AspNet.Security.OpenIdConnect.Server": "1.0.0-*" }, "frameworks": { - "dnx451": { - "dependencies": { - "AspNet.Hosting.Katana.Extensions": "1.0.0-*", - "NWebsec.Owin": "1.0.0" - } - }, - - "dnxcore50": { - "dependencies": { - "System.Linq": "4.0.1-*", - "System.Runtime.Serialization.Primitives": "4.0.11-*" - } - } + "dnx451": { }, + "dnxcore50": { } } } \ No newline at end of file diff --git a/src/OpenIddict.EF/OpenIddictExtensions.cs b/src/OpenIddict.EF/OpenIddictExtensions.cs index 9a826e61..424bdb8b 100644 --- a/src/OpenIddict.EF/OpenIddictExtensions.cs +++ b/src/OpenIddict.EF/OpenIddictExtensions.cs @@ -16,7 +16,7 @@ using OpenIddict; namespace Microsoft.AspNet.Builder { public static class OpenIddictExtensions { - public static OpenIddictServices AddEntityFrameworkStore([NotNull] this OpenIddictServices services) { + public static OpenIddictServices UseEntityFramework([NotNull] this OpenIddictServices services) { services.Services.AddScoped( typeof(IOpenIddictStore<,>).MakeGenericType(services.UserType, services.ApplicationType), typeof(OpenIddictStore<,,,,>).MakeGenericType( diff --git a/src/OpenIddict.EF/project.json b/src/OpenIddict.EF/project.json index b045bb6f..6fcca593 100644 --- a/src/OpenIddict.EF/project.json +++ b/src/OpenIddict.EF/project.json @@ -1,6 +1,8 @@ { "version": "1.0.0-alpha1-*", + "description": "Entity Framework adapter for OpenIddict.", + "dependencies": { "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-*", diff --git a/src/OpenIddict.Models/project.json b/src/OpenIddict.Models/project.json index 70975b62..5f29b5dc 100644 --- a/src/OpenIddict.Models/project.json +++ b/src/OpenIddict.Models/project.json @@ -1,6 +1,8 @@ { "version": "1.0.0-alpha1-*", + "description": "Contains the default models used by OpenIddict.", + "frameworks": { "dnx451": { }, "dnxcore50": { diff --git a/src/OpenIddict.Mvc/OpenIddict.Mvc.xproj b/src/OpenIddict.Mvc/OpenIddict.Mvc.xproj new file mode 100644 index 00000000..f5836c31 --- /dev/null +++ b/src/OpenIddict.Mvc/OpenIddict.Mvc.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + 7ae46e2f-e93b-4ff9-b941-6cd7a3e1bf84 + OpenIddict.Mvc + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + diff --git a/src/OpenIddict.Core/OpenIddictController.cs b/src/OpenIddict.Mvc/OpenIddictController.cs similarity index 97% rename from src/OpenIddict.Core/OpenIddictController.cs rename to src/OpenIddict.Mvc/OpenIddictController.cs index 7c4ad440..ab602314 100644 --- a/src/OpenIddict.Core/OpenIddictController.cs +++ b/src/OpenIddict.Mvc/OpenIddictController.cs @@ -38,7 +38,7 @@ namespace OpenIddict { protected virtual OpenIddictOptions Options { get; } [HttpGet, HttpPost] - public async Task Authorize() { + public virtual async Task Authorize() { // Note: when a fatal error occurs during the request processing, an OpenID Connect response // is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler. // In this case, the OpenID Connect request is null and cannot be used. @@ -93,7 +93,7 @@ namespace OpenIddict { } [Authorize, HttpPost, ValidateAntiForgeryToken] - public async Task Accept() { + public virtual async Task Accept() { // Extract the authorization request from the cache, // the query string or the request form. var request = HttpContext.GetOpenIdConnectRequest(); @@ -175,7 +175,7 @@ namespace OpenIddict { } [Authorize, HttpPost, ValidateAntiForgeryToken] - public IActionResult Deny() { + public virtual IActionResult Deny() { // Extract the authorization request from the cache, // the query string or the request form. var request = HttpContext.GetOpenIdConnectRequest(); @@ -200,7 +200,7 @@ namespace OpenIddict { } [HttpGet] - public async Task Logout() { + public virtual async Task Logout() { // Note: when a fatal error occurs during the request processing, an OpenID Connect response // is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler. // In this case, the OpenID Connect request is null and cannot be used. @@ -231,7 +231,7 @@ namespace OpenIddict { } [HttpPost, ValidateAntiForgeryToken] - public async Task Logout(CancellationToken cancellationToken) { + public virtual async Task Logout(CancellationToken cancellationToken) { // Instruct the cookies middleware to delete the local cookie created // when the user agent is redirected from the external identity provider // after a successful authentication flow (e.g Google or Facebook). diff --git a/src/OpenIddict.Mvc/OpenIddictExtensions.cs b/src/OpenIddict.Mvc/OpenIddictExtensions.cs new file mode 100644 index 00000000..7af6c472 --- /dev/null +++ b/src/OpenIddict.Mvc/OpenIddictExtensions.cs @@ -0,0 +1,170 @@ +/* + * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) + * See https://github.com/openiddict/core for more information concerning + * the license and the contributors participating to this project. + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using Microsoft.AspNet.FileProviders; +using Microsoft.AspNet.Http; +using Microsoft.AspNet.Identity; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Internal; +using Microsoft.Extensions.Primitives; +using OpenIddict; + +#if DNX451 +using NWebsec.Owin; +#endif + +namespace Microsoft.AspNet.Builder { + public static class OpenIddictExtensions { + public static OpenIddictBuilder UseMvc([NotNull] this OpenIddictBuilder builder) { +#if DNX451 + builder.AddModule(-20, app => app.UseKatana(owin => { + // 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 + owin.UseCsp(options => options.DefaultSources(directive => directive.Self()) + .ImageSources(directive => directive.Self().CustomSources("*")) + .ScriptSources(directive => directive.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 + owin.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 + owin.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 + owin.UseXXssProtection(options => options.EnabledWithBlockMode()); + })); +#endif + + // Run the rest of the pipeline in an isolated environment. + builder.AddModule(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 { + controller = typeof(OpenIddictController<,>).Name, + action = nameof(OpenIddictController.Authorize) + }); + + routes.MapRoute("{7148DB83}", builder.Options.AuthorizationEndpointPath.Value.Substring(1) + "/accept", new { + controller = typeof(OpenIddictController<,>).Name, + action = nameof(OpenIddictController.Accept) + }); + + routes.MapRoute("{23438BCC}", builder.Options.AuthorizationEndpointPath.Value.Substring(1) + "/deny", new { + controller = typeof(OpenIddictController<,>).Name, + action = nameof(OpenIddictController.Deny) + }); + } + + // Register the action corresponding to the logout endpoint. + if (builder.Options.LogoutEndpointPath.HasValue) { + routes.MapRoute("{C7DB102A}", builder.Options.LogoutEndpointPath.Value.Substring(1), new { + controller = typeof(OpenIddictController<,>).Name, + action = nameof(OpenIddictController.Logout) + }); + } + }), services => { + var registration = builder.Builder.ApplicationServices.GetRequiredService(); + + services.AddMvc() + // Register the OpenIddict controller. + .AddControllersAsServices(new[] { + typeof(OpenIddictController<,>).MakeGenericType(registration.UserType, registration.ApplicationType) + }) + + .AddRazorOptions(options => { + // Update the Razor options to also use a combined provider that + // falls back to the current assembly when searching for views. + options.FileProvider = new CombinedFileSystemProvider(new[] { + options.FileProvider, + new EmbeddedFileProvider( + assembly: typeof(OpenIddictController<,>).GetTypeInfo().Assembly, + baseNamespace: "OpenIddict.Mvc") + }); + }); + + // Register the sign-in manager in the isolated container. + services.AddScoped(typeof(SignInManager<>).MakeGenericType(registration.UserType), provider => { + var accessor = provider.GetRequiredService(); + var container = (IServiceProvider) accessor.HttpContext.Items[typeof(IServiceProvider)]; + Debug.Assert(container != null); + + // Resolve the sign-in manager from the parent container. + return container.GetRequiredService(typeof(SignInManager<>).MakeGenericType(registration.UserType)); + }); + + // Register the user manager in the isolated container. + services.AddScoped(typeof(OpenIddictManager<,>).MakeGenericType(registration.UserType, registration.ApplicationType), provider => { + var accessor = provider.GetRequiredService(); + var container = (IServiceProvider) accessor.HttpContext.Items[typeof(IServiceProvider)]; + Debug.Assert(container != null); + + // Resolve the user manager from the parent container. + return container.GetRequiredService(typeof(OpenIddictManager<,>).MakeGenericType(registration.UserType, registration.ApplicationType)); + }); + + // Register the options in the isolated container. + services.AddScoped(provider => builder.Options); + })); + + return builder; + } + + private class CombinedFileSystemProvider : IFileProvider { + public CombinedFileSystemProvider(IList providers) { + Providers = providers; + } + + public IList Providers { get; } + + public IDirectoryContents GetDirectoryContents(string subpath) { + for (var index = 0; index < Providers.Count; index++) { + var provider = Providers[index]; + + var result = provider.GetDirectoryContents(subpath); + if (result != null && result.Exists) { + return result; + } + } + + return new NotFoundDirectoryContents(); + } + + public IFileInfo GetFileInfo(string subpath) { + for (var index = 0; index < Providers.Count; index++) { + var provider = Providers[index]; + + var result = provider.GetFileInfo(subpath); + if (result != null && result.Exists) { + return result; + } + } + + return new NotFoundFileInfo(subpath); + } + + public IChangeToken Watch(string filter) { + for (var index = 0; index < Providers.Count; index++) { + var provider = Providers[index]; + + var result = provider.Watch(filter); + if (result != null) { + return result; + } + } + + return NoopChangeToken.Singleton; + } + } + } +} \ No newline at end of file diff --git a/src/OpenIddict.Mvc/Properties/AssemblyInfo.cs b/src/OpenIddict.Mvc/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..e6bc65ac --- /dev/null +++ b/src/OpenIddict.Mvc/Properties/AssemblyInfo.cs @@ -0,0 +1,23 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenIddict.Mvc")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenIddict.Mvc")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7ae46e2f-e93b-4ff9-b941-6cd7a3e1bf84")] diff --git a/src/OpenIddict.Core/Views/Shared/Authorize.cshtml b/src/OpenIddict.Mvc/Views/Shared/Authorize.cshtml similarity index 100% rename from src/OpenIddict.Core/Views/Shared/Authorize.cshtml rename to src/OpenIddict.Mvc/Views/Shared/Authorize.cshtml diff --git a/src/OpenIddict.Core/Views/Shared/Error.cshtml b/src/OpenIddict.Mvc/Views/Shared/Error.cshtml similarity index 100% rename from src/OpenIddict.Core/Views/Shared/Error.cshtml rename to src/OpenIddict.Mvc/Views/Shared/Error.cshtml diff --git a/src/OpenIddict.Core/Views/Shared/Logout.cshtml b/src/OpenIddict.Mvc/Views/Shared/Logout.cshtml similarity index 100% rename from src/OpenIddict.Core/Views/Shared/Logout.cshtml rename to src/OpenIddict.Mvc/Views/Shared/Logout.cshtml diff --git a/src/OpenIddict.Core/Views/Shared/SignIn.cshtml b/src/OpenIddict.Mvc/Views/Shared/SignIn.cshtml similarity index 100% rename from src/OpenIddict.Core/Views/Shared/SignIn.cshtml rename to src/OpenIddict.Mvc/Views/Shared/SignIn.cshtml diff --git a/src/OpenIddict.Core/Views/Shared/_Layout.cshtml b/src/OpenIddict.Mvc/Views/Shared/_Layout.cshtml similarity index 100% rename from src/OpenIddict.Core/Views/Shared/_Layout.cshtml rename to src/OpenIddict.Mvc/Views/Shared/_Layout.cshtml diff --git a/src/OpenIddict.Core/Views/_ViewStart.cshtml b/src/OpenIddict.Mvc/Views/_ViewStart.cshtml similarity index 100% rename from src/OpenIddict.Core/Views/_ViewStart.cshtml rename to src/OpenIddict.Mvc/Views/_ViewStart.cshtml diff --git a/src/OpenIddict.Mvc/project.json b/src/OpenIddict.Mvc/project.json new file mode 100644 index 00000000..ecca78f5 --- /dev/null +++ b/src/OpenIddict.Mvc/project.json @@ -0,0 +1,37 @@ +{ + "version": "1.0.0-alpha1-*", + + "description": "MVC 6 module for OpenIddict.", + + "resource": "Views/**", + + "dependencies": { + "Microsoft.AspNet.FileProviders.Embedded": "1.0.0-*", + "Microsoft.AspNet.Mvc": "6.0.0-*", + + "Microsoft.AspNet.FileProviders.Sources": { + "type": "build", + "version": "1.0.0-*" + }, + + "Microsoft.Extensions.NotNullAttribute.Sources": { + "type": "build", + "version": "1.0.0-*" + }, + + "AspNet.Hosting.Extensions": "1.0.0-*", + + "OpenIddict.Core": "1.0.0-*" + }, + + "frameworks": { + "dnx451": { + "dependencies": { + "AspNet.Hosting.Katana.Extensions": "1.0.0-*", + "NWebsec.Owin": "1.0.0" + } + }, + + "dnxcore50": { } + } +} \ No newline at end of file diff --git a/src/OpenIddict/OpenIddictExtensions.cs b/src/OpenIddict/OpenIddictExtensions.cs index 2fd23d82..6d5167d7 100644 --- a/src/OpenIddict/OpenIddictExtensions.cs +++ b/src/OpenIddict/OpenIddictExtensions.cs @@ -7,20 +7,40 @@ using System; using Microsoft.AspNet.Identity; using Microsoft.Extensions.Internal; -using OpenIddict; using OpenIddict.Models; namespace Microsoft.AspNet.Builder { public static class OpenIddictExtensions { - public static OpenIddictServices AddOpenIddict([NotNull] this IdentityBuilder builder) { - return builder.AddOpenIddictCore() - .AddEntityFrameworkStore(); + public static IdentityBuilder AddOpenIddict([NotNull] this IdentityBuilder builder) { + return builder.AddOpenIddictCore(configuration => { + // Use the EF adapter by default. + configuration.UseEntityFramework(); + }); } - public static OpenIddictServices AddOpenIddict([NotNull] this IdentityBuilder builder) + public static IdentityBuilder AddOpenIddict([NotNull] this IdentityBuilder builder) where TApplication : Application { - return builder.AddOpenIddictCore() - .AddEntityFrameworkStore(); + return builder.AddOpenIddictCore(configuration => { + // Use the EF adapter by default. + configuration.UseEntityFramework(); + }); + } + + public static IApplicationBuilder UseOpenIddict([NotNull] this IApplicationBuilder app) { + return app.UseOpenIddict(options => { }); + } + + public static IApplicationBuilder UseOpenIddict( + [NotNull] this IApplicationBuilder app, + [NotNull] Action configuration) { + return app.UseOpenIddictCore(builder => { + // By default, both the assets + // and the MVC modules are enabled. + builder.UseAssets(); + builder.UseMvc(); + + configuration(builder); + }); } } } \ No newline at end of file diff --git a/src/OpenIddict/project.json b/src/OpenIddict/project.json index 8a2c2107..f3251859 100644 --- a/src/OpenIddict/project.json +++ b/src/OpenIddict/project.json @@ -1,8 +1,12 @@ { "version": "1.0.0-alpha1-*", + "description": "Easy-to-use OpenID Connect server for ASP.NET 5.", + "dependencies": { + "OpenIddict.Assets": "1.0.0-*", "OpenIddict.EF": "1.0.0-*", + "OpenIddict.Mvc": "1.0.0-*", "Microsoft.Extensions.NotNullAttribute.Sources": { "type": "build",