From 0f9173ecb0c301ffd05685a6637d1783aca2cb06 Mon Sep 17 00:00:00 2001 From: Praburaj Date: Thu, 15 Jan 2015 13:12:56 -0800 Subject: [PATCH] Adding a Start up class for OpenIdConnect authentication --- NuGet.Config | 1 + README.md | 5 +- .../Controllers/AccountController.cs | 11 ++ src/MusicStore/MusicStore.kproj | 7 +- src/MusicStore/StartupNtlmAuthentication.cs | 2 +- src/MusicStore/StartupOpenIdConnect.cs | 139 ++++++++++++++++++ src/MusicStore/project.json | 89 +++++------ 7 files changed, 207 insertions(+), 47 deletions(-) create mode 100644 src/MusicStore/StartupOpenIdConnect.cs diff --git a/NuGet.Config b/NuGet.Config index f41e9c631d..4ee105534c 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -3,5 +3,6 @@ + diff --git a/README.md b/README.md index 065fb8ae62..6649a116d3 100644 --- a/README.md +++ b/README.md @@ -28,4 +28,7 @@ This project is part of ASP.NET 5.0. You can find samples, documentation and get **NOTE: On Mono since SQL client is not available the sample uses an InMemoryStore to run the application. So the changes that you make will not be persisted. ###NTLM authentication -More information at src/MusicStore/StartupNtlmAuthentication.cs. \ No newline at end of file +More information at src/MusicStore/StartupNtlmAuthentication.cs. + +###OpenIdConnect authentication +More information at src/MusicStore/StartupOpenIdConnect.cs. \ No newline at end of file diff --git a/src/MusicStore/Controllers/AccountController.cs b/src/MusicStore/Controllers/AccountController.cs index a14fd5e6c1..903fe4dd7c 100644 --- a/src/MusicStore/Controllers/AccountController.cs +++ b/src/MusicStore/Controllers/AccountController.cs @@ -2,9 +2,11 @@ using System.Security.Claims; using System.Security.Principal; using System.Threading.Tasks; +using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.Rendering; +using Microsoft.Framework.DependencyInjection; using MusicStore.Models; namespace MusicStore.Controllers @@ -431,6 +433,15 @@ namespace MusicStore.Controllers public IActionResult LogOff() { SignInManager.SignOut(); + + // TODO: Currently SignInManager.SignOut does not sign out OpenIdc and does not have a way to pass in a specific + // AuthType to sign out. + var appEnv = Context.RequestServices.GetService(); + if (appEnv.EnvironmentName == "OpenIdConnect") + { + Response.SignOut("OpenIdConnect"); + } + return RedirectToAction("Index", "Home"); } diff --git a/src/MusicStore/MusicStore.kproj b/src/MusicStore/MusicStore.kproj index abf0b43234..695d969e10 100644 --- a/src/MusicStore/MusicStore.kproj +++ b/src/MusicStore/MusicStore.kproj @@ -15,4 +15,9 @@ 5001 - + + + + + + \ No newline at end of file diff --git a/src/MusicStore/StartupNtlmAuthentication.cs b/src/MusicStore/StartupNtlmAuthentication.cs index 474b845d5e..049ba79ee4 100644 --- a/src/MusicStore/StartupNtlmAuthentication.cs +++ b/src/MusicStore/StartupNtlmAuthentication.cs @@ -18,7 +18,7 @@ namespace MusicStore { /// /// To make runtime to load an environment based startup class, specify the environment by the following ways: - /// 1. Drop a Microsoft.AspNet.Hosting.ini file in the application folder + /// 1. Drop a Microsoft.AspNet.Hosting.ini file in the wwwroot folder /// 2. Add a setting in the ini file named 'ASPNET_ENV' with value of the format 'Startup[EnvironmentName]'. For example: To load a Startup class named /// 'StartupNtlmAuthentication' the value of the env should be 'NtlmAuthentication' (eg. ASPNET_ENV=NtlmAuthentication). Runtime adds a 'Startup' prefix to this and loads 'StartupNtlmAuthentication'. /// If no environment name is specified the default startup class loaded is 'Startup'. diff --git a/src/MusicStore/StartupOpenIdConnect.cs b/src/MusicStore/StartupOpenIdConnect.cs new file mode 100644 index 0000000000..1a365edfc6 --- /dev/null +++ b/src/MusicStore/StartupOpenIdConnect.cs @@ -0,0 +1,139 @@ +using System; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Diagnostics; +using Microsoft.AspNet.Diagnostics.Entity; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Routing; +using Microsoft.Framework.Cache.Memory; +using Microsoft.Framework.ConfigurationModel; +using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.Logging; +using Microsoft.Framework.Logging.Console; +using MusicStore.Models; + +namespace MusicStore +{ + /// + /// To make runtime to load an environment based startup class, specify the environment by the following ways: + /// 1. Drop a Microsoft.AspNet.Hosting.ini file in the wwwroot folder + /// 2. Add a setting in the ini file named 'ASPNET_ENV' with value of the format 'Startup[EnvironmentName]'. For example: To load a Startup class named + /// 'StartupOpenIdConnect' the value of the env should be 'OpenIdConnect' (eg. ASPNET_ENV=OpenIdConnect). Runtime adds a 'Startup' prefix to this and loads 'StartupOpenIdConnect'. + /// If no environment name is specified the default startup class loaded is 'Startup'. + /// Alternative ways to specify environment are: + /// 1. Set the environment variable named SET ASPNET_ENV=OpenIdConnect + /// 2. For selfhost based servers pass in a command line variable named --env with this value. Eg: + /// "commands": { + /// "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5002 --ASPNET_ENV OpenIdConnect", + /// }, + /// + public class StartupOpenIdConnect + { + public StartupOpenIdConnect() + { + //Below code demonstrates usage of multiple configuration sources. For instance a setting say 'setting1' is found in both the registered sources, + //then the later source will win. By this way a Local config can be overridden by a different setting while deployed remotely. + Configuration = new Configuration() + .AddJsonFile("config.json") + .AddEnvironmentVariables(); //All environment variables in the process's context flow in as configuration values. + } + + public IConfiguration Configuration { get; private set; } + + public void ConfigureServices(IServiceCollection services) + { + //Sql client not available on mono + var useInMemoryStore = Type.GetType("Mono.Runtime") != null; + + // Add EF services to the services container + if (useInMemoryStore) + { + services.AddEntityFramework(Configuration) + .AddInMemoryStore() + .AddDbContext(); + } + else + { + services.AddEntityFramework(Configuration) + .AddSqlServer() + .AddDbContext(); + } + + // Add Identity services to the services container + services.AddIdentity(Configuration) + .AddEntityFrameworkStores() + .AddDefaultTokenProviders() + .AddMessageProvider() + .AddMessageProvider(); + + // Add MVC services to the services container + services.AddMvc(); + + //Add all SignalR related services to IoC. + services.AddSignalR(); + + //Add InMemoryCache + services.AddSingleton(); + } + + //This method is invoked when ASPNET_ENV is 'Development' or is not defined + //The allowed values are Development,Staging and Production + public void ConfigureDevelopment(IApplicationBuilder app, ILoggerFactory loggerFactory) + { + loggerFactory.AddConsole(); + + //Display custom error page in production when error occurs + //During development use the ErrorPage middleware to display error information in the browser + app.UseErrorPage(ErrorPageOptions.ShowAll); + + app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll); + + // Add the runtime information page that can be used by developers + // to see what packages are used by the application + // default path is: /runtimeinfo + app.UseRuntimeInfoPage(); + + Configure(app); + } + + public void Configure(IApplicationBuilder app) + { + //Configure SignalR + app.UseSignalR(); + + // Add static files to the request pipeline + app.UseStaticFiles(); + + // Add cookie-based authentication to the request pipeline + app.UseIdentity(); + + // Create an Azure Active directory application and copy paste the following + // https://github.com/aspnet/Security/issues/113 + app.UseOpenIdConnectAuthentication(options => + { + options.Authority = "https://login.windows.net/[tenantName].onmicrosoft.com"; + options.ClientId = "[ClientId]"; + }); + + // Add MVC to the request pipeline + app.UseMvc(routes => + { + routes.MapRoute( + name: "areaRoute", + template: "{area:exists}/{controller}/{action}", + defaults: new { action = "Index" }); + + routes.MapRoute( + name: "default", + template: "{controller}/{action}/{id?}", + defaults: new { controller = "Home", action = "Index" }); + + routes.MapRoute( + name: "api", + template: "{controller}/{id?}"); + }); + + //Populates the MusicStore sample data + SampleData.InitializeMusicStoreDatabaseAsync(app.ApplicationServices).Wait(); + } + } +} \ No newline at end of file diff --git a/src/MusicStore/project.json b/src/MusicStore/project.json index 5ac5465ba7..52e0eb39dc 100644 --- a/src/MusicStore/project.json +++ b/src/MusicStore/project.json @@ -1,46 +1,47 @@ { - "authors": [ - "Microsoft" - ], - "description": "Music store application on ASP.NET 5", - "version": "1.0.0-*", - "compilationOptions": { "warningsAsErrors": true, "define": [ "DEMO", "TESTING" ] }, - "code": [ - "**/*.cs", - "../../test/E2ETests/compiler/shared/**/*.cs" // This code is for testing only. - ], - "packExclude": "*.cmd", - "webroot": "wwwroot", - "dependencies": { - "EntityFramework.SqlServer": "7.0.0-*", - "EntityFramework.InMemory": "7.0.0-*", // For Mono. - "Kestrel": "1.0.0-*", - "Microsoft.AspNet.Diagnostics": "1.0.0-*", - "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-*", - "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-*", - "Microsoft.AspNet.Mvc": "6.0.0-*", - "Microsoft.AspNet.Security.Cookies": "1.0.0-*", - "Microsoft.AspNet.Security.Facebook": "1.0.0-*", - "Microsoft.AspNet.Security.Google": "1.0.0-*", - "Microsoft.AspNet.Security.MicrosoftAccount": "1.0.0-*", - "Microsoft.AspNet.Security.Twitter": "1.0.0-*", - "Microsoft.AspNet.Server.IIS": "1.0.0-*", - "Microsoft.AspNet.Server.WebListener": "1.0.0-*", - "Microsoft.AspNet.SignalR.Server": "3.0.0-*", - "Microsoft.AspNet.StaticFiles": "1.0.0-*", - "Microsoft.Framework.Cache.Memory": "1.0.0-*", - "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-*", - "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*", - "Microsoft.Framework.Logging.Console": "1.0.0-*" - }, - "commands": { - "gen": "Microsoft.Framework.CodeGeneration", - "kestrel": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:5004", - "run": "run server.urls=http://localhost:5003", - "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5002" - }, - "frameworks": { - "aspnet50": { }, - "aspnetcore50": { } - } + "authors": [ + "Microsoft" + ], + "description": "Music store application on ASP.NET 5", + "version": "1.0.0-*", + "compilationOptions": { "warningsAsErrors": true, "define": [ "DEMO", "TESTING" ] }, + "code": [ + "**/*.cs", + "../../test/E2ETests/compiler/shared/**/*.cs" // This code is for testing only. + ], + "packExclude": "*.cmd", + "webroot": "wwwroot", + "dependencies": { + "EntityFramework.SqlServer": "7.0.0-*", + "EntityFramework.InMemory": "7.0.0-*", // For Mono. + "Kestrel": "1.0.0-*", + "Microsoft.AspNet.Diagnostics": "1.0.0-*", + "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-*", + "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-*", + "Microsoft.AspNet.Mvc": "6.0.0-*", + "Microsoft.AspNet.Security.Cookies": "1.0.0-*", + "Microsoft.AspNet.Security.Facebook": "1.0.0-*", + "Microsoft.AspNet.Security.Google": "1.0.0-*", + "Microsoft.AspNet.Security.MicrosoftAccount": "1.0.0-*", + "Microsoft.AspNet.Security.OpenIdConnect": "1.0.0-*", + "Microsoft.AspNet.Security.Twitter": "1.0.0-*", + "Microsoft.AspNet.Server.IIS": "1.0.0-*", + "Microsoft.AspNet.Server.WebListener": "1.0.0-*", + "Microsoft.AspNet.SignalR.Server": "3.0.0-*", + "Microsoft.AspNet.StaticFiles": "1.0.0-*", + "Microsoft.Framework.Cache.Memory": "1.0.0-*", + "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-*", + "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*", + "Microsoft.Framework.Logging.Console": "1.0.0-*" + }, + "commands": { + "gen": "Microsoft.Framework.CodeGeneration", + "kestrel": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:5004", + "run": "run server.urls=http://localhost:5003", + "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5002" + }, + "frameworks": { + "aspnet50": { }, + "aspnetcore50": { } + } } \ No newline at end of file