Permalink
Browse files

Added AspNetMvcAuthSample to demonstrate issue with auth middleware i…

…n multi-tenant scenarios.
  • Loading branch information...
Ben Foster
Ben Foster committed Feb 29, 2016
1 parent ccdef50 commit 38a88c368d9dec716d1f3f11b8722800e1d71566
Showing with 763 additions and 1 deletion.
  1. +4 −1 .gitignore
  2. +7 −0 SaasKit.sln
  3. +3 −0 samples/AspNetMvcAuthDemo/.bowerrc
  4. +8 −0 samples/AspNetMvcAuthDemo/AppTenant.cs
  5. +48 −0 samples/AspNetMvcAuthDemo/AppTenantResolver.cs
  6. +23 −0 samples/AspNetMvcAuthDemo/AspNetMvcAuthSample.xproj
  7. +39 −0 samples/AspNetMvcAuthDemo/Controllers/AccountController.cs
  8. +33 −0 samples/AspNetMvcAuthDemo/Controllers/HomeController.cs
  9. +9 −0 samples/AspNetMvcAuthDemo/MultitenancyOptions.cs
  10. +25 −0 samples/AspNetMvcAuthDemo/Properties/launchSettings.json
  11. +97 −0 samples/AspNetMvcAuthDemo/Startup.cs
  12. +7 −0 samples/AspNetMvcAuthDemo/Views/Account/LogIn.cshtml
  13. +17 −0 samples/AspNetMvcAuthDemo/Views/Home/About.cshtml
  14. +17 −0 samples/AspNetMvcAuthDemo/Views/Home/Contact.cshtml
  15. +110 −0 samples/AspNetMvcAuthDemo/Views/Home/Index.cshtml
  16. +6 −0 samples/AspNetMvcAuthDemo/Views/Shared/Error.cshtml
  17. +68 −0 samples/AspNetMvcAuthDemo/Views/Shared/_Layout.cshtml
  18. +21 −0 samples/AspNetMvcAuthDemo/Views/Shared/_LoginPartial.cshtml
  19. +7 −0 samples/AspNetMvcAuthDemo/Views/_ViewImports.cshtml
  20. +3 −0 samples/AspNetMvcAuthDemo/Views/_ViewStart.cshtml
  21. +26 −0 samples/AspNetMvcAuthDemo/appsettings.json
  22. +10 −0 samples/AspNetMvcAuthDemo/bower.json
  23. +48 −0 samples/AspNetMvcAuthDemo/gulpfile.js
  24. +11 −0 samples/AspNetMvcAuthDemo/package.json
  25. +62 −0 samples/AspNetMvcAuthDemo/project.json
  26. +9 −0 samples/AspNetMvcAuthDemo/wwwroot/_references.js
  27. +34 −0 samples/AspNetMvcAuthDemo/wwwroot/css/site.css
  28. +1 −0 samples/AspNetMvcAuthDemo/wwwroot/css/site.min.css
  29. BIN samples/AspNetMvcAuthDemo/wwwroot/favicon.ico
  30. BIN samples/AspNetMvcAuthDemo/wwwroot/images/ASP-NET-Banners-01.png
  31. BIN samples/AspNetMvcAuthDemo/wwwroot/images/ASP-NET-Banners-02.png
  32. BIN samples/AspNetMvcAuthDemo/wwwroot/images/Banner-01-Azure.png
  33. BIN samples/AspNetMvcAuthDemo/wwwroot/images/Banner-02-VS.png
  34. +1 −0 samples/AspNetMvcAuthDemo/wwwroot/js/site.js
  35. 0 samples/AspNetMvcAuthDemo/wwwroot/js/site.min.js
  36. +9 −0 samples/AspNetMvcAuthDemo/wwwroot/web.config
View
@@ -212,4 +212,7 @@ _Pvt_Extensions/
ModelManifest.xml
.DS_store
._.DS_Store
._.DS_Store
# Visual Studio Bower Packages
**/wwwroot/lib/
View
@@ -24,6 +24,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SaasKit.Multitenancy.Tests"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SaasKit.Multitenancy.StructureMap", "src\SaasKit.Multitenancy.StructureMap\SaasKit.Multitenancy.StructureMap.xproj", "{B279D429-8CE4-458E-A3CB-355C5E7502B8}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AspNetMvcAuthSample", "samples\AspNetMvcAuthDemo\AspNetMvcAuthSample.xproj", "{FE7C68EC-5A31-4C31-A4EC-2E041C20483C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -50,6 +52,10 @@ Global
{B279D429-8CE4-458E-A3CB-355C5E7502B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B279D429-8CE4-458E-A3CB-355C5E7502B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B279D429-8CE4-458E-A3CB-355C5E7502B8}.Release|Any CPU.Build.0 = Release|Any CPU
{FE7C68EC-5A31-4C31-A4EC-2E041C20483C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE7C68EC-5A31-4C31-A4EC-2E041C20483C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE7C68EC-5A31-4C31-A4EC-2E041C20483C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE7C68EC-5A31-4C31-A4EC-2E041C20483C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -58,5 +64,6 @@ Global
{A4ECD7AC-2007-4BDE-A8D9-E122CAE6EDAC} = {3BF6E052-C932-4DD5-B5C6-3A014282CDF3}
{66DE6E51-4668-4DBE-81A8-F6033C30F7CF} = {3BF6E052-C932-4DD5-B5C6-3A014282CDF3}
{2BD23575-488B-44DB-8966-C45FDBF0E2EF} = {485AA823-29AD-4346-8857-331F81A3713C}
{FE7C68EC-5A31-4C31-A4EC-2E041C20483C} = {3BF6E052-C932-4DD5-B5C6-3A014282CDF3}
EndGlobalSection
EndGlobal
@@ -0,0 +1,3 @@
{
"directory": "wwwroot/lib"
}
@@ -0,0 +1,8 @@
namespace AspNetMvcAuthSample
{
public class AppTenant
{
public string Name { get; set; }
public string[] Hostnames { get; set; }
}
}
@@ -0,0 +1,48 @@
using Microsoft.AspNet.Http;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel;
using SaasKit.Multitenancy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AspNetMvcAuthSample
{
public class CachingAppTenantResolver : MemoryCacheTenantResolver<AppTenant>
{
private readonly IEnumerable<AppTenant> tenants;
public CachingAppTenantResolver(IMemoryCache cache, ILoggerFactory loggerFactory, IOptions<MultitenancyOptions> options)
: base(cache, loggerFactory)
{
this.tenants = options.Value.Tenants;
}
protected override string GetContextIdentifier(HttpContext context)
{
return context.Request.Host.Value.ToLower();
}
protected override IEnumerable<string> GetTenantIdentifiers(TenantContext<AppTenant> context)
{
return context.Tenant.Hostnames;
}
protected override Task<TenantContext<AppTenant>> ResolveAsync(HttpContext context)
{
TenantContext<AppTenant> tenantContext = null;
var tenant = tenants.FirstOrDefault(t =>
t.Hostnames.Any(h => h.Equals(context.Request.Host.Value.ToLower())));
if (tenant != null)
{
tenantContext = new TenantContext<AppTenant>(tenant);
}
return Task.FromResult(tenantContext);
}
}
}
@@ -0,0 +1,23 @@
<?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>fe7c68ec-5a31-4c31-a4ec-2e041c20483c</ProjectGuid>
<RootNamespace>AspNetMvcAuthSample</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>
@@ -0,0 +1,39 @@
using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.Mvc;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace AspNetMvcAuthSample.Controllers
{
public class AccountController : Controller
{
ILogger<AccountController> logger;
public AccountController(ILogger<AccountController> logger)
{
this.logger = logger;
}
public IActionResult LogIn()
{
return View();
}
public IActionResult Google()
{
var props = new AuthenticationProperties
{
RedirectUri = "/home/about"
};
return new ChallengeResult("Google", props);
}
public async Task<IActionResult> LogOut()
{
await HttpContext.Authentication.SignOutAsync("Cookies");
return RedirectToAction("index", "home");
}
}
}
@@ -0,0 +1,33 @@
using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Mvc;
namespace AspNetMvcAuthSample.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[Authorize]
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
public IActionResult Error()
{
return View();
}
}
}
@@ -0,0 +1,9 @@
using System.Collections.ObjectModel;
namespace AspNetMvcAuthSample
{
public class MultitenancyOptions
{
public Collection<AppTenant> Tenants { get; set; }
}
}
@@ -0,0 +1,25 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52911/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"Hosting:Environment": "Development"
}
},
"web": {
"commandName": "web",
"environmentVariables": {
"Hosting:Environment": "Development"
}
}
}
}
@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Authentication.Google;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace AspNetMvcAuthSample
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
builder.AddUserSecrets();
}
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMultitenancy<AppTenant, CachingAppTenantResolver>();
// Add framework services.
services.AddMvc();
services.Configure<MultitenancyOptions>(Configuration.GetSection("Multitenancy"));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseDeveloperExceptionPage();
app.UseIISPlatformHandler();
app.UseCookieAuthentication(options =>
{
options.AuthenticationScheme = "Cookies";
options.LoginPath = new PathString("/account/login");
options.AccessDeniedPath = new PathString("/account/forbidden");
options.AutomaticAuthenticate = true;
options.AutomaticChallenge = true;
});
app.UseGoogleAuthentication(options =>
{
options.AuthenticationScheme = "Google";
options.SignInScheme = "Cookies";
options.ClientId = Configuration["Tenant1:GoogleClientId"];
options.ClientSecret = Configuration["Tenant1:GoogleClientSecret"];
});
app.UseStaticFiles();
app.UseMultitenancy<AppTenant>();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
// Entry point for the application.
public static void Main(string[] args) => Microsoft.AspNet.Hosting.WebApplication.Run<Startup>(args);
}
}
@@ -0,0 +1,7 @@
@{
ViewData["Title"] = "Log In";
}
<h1>Log In</h1>
<p>
<a href="~/account/google">Log in with Google</a>
</p>
@@ -0,0 +1,17 @@
@{
ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<p>Use this area to provide additional information.</p>
<table class="table">
@foreach (var claim in User.Claims)
{
<tr>
<td>@claim.Type</td>
<td>@claim.Value</td>
</tr>
}
</table>
@@ -0,0 +1,17 @@
@{
ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<address>
One Microsoft Way<br />
Redmond, WA 98052-6399<br />
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br />
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>
Oops, something went wrong.

0 comments on commit 38a88c3

Please sign in to comment.