Skip to content

Port new options auth sample #6363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;

namespace AuthSamples.Options.MultiTenant.Controllers
{
public class AuthController : Controller
{
private readonly IAuthenticationSchemeProvider _schemeProvider;
private readonly TenantOptionsCache _cache;
private readonly TenantResolver _resolver;

public AuthController(IAuthenticationSchemeProvider schemeProvider, TenantOptionsCache optionsCache, TenantResolver resolver)
{
_schemeProvider = schemeProvider;
_cache = optionsCache;
_resolver = resolver;
}

public IActionResult Remove(string scheme)
{
_schemeProvider.RemoveScheme(scheme);
_cache.Remove(scheme);
return Redirect($"/?tenant={_resolver.ResolveTenant()}");
}

[HttpPost]
public async Task<IActionResult> AddOrUpdate(string scheme, string clientId, string clientSecret)
{
if (await _schemeProvider.GetSchemeAsync(scheme) == null)
{
_schemeProvider.AddScheme(new AuthenticationScheme(scheme, scheme, typeof(SimpleAuthHandler)));
}
_cache.Update(scheme, new SimpleOptions { ClientId = clientId, ClientSecret = clientSecret });
return Redirect($"/?tenant={_resolver.ResolveTenant()}");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="$(MicrosoftAspNetCoreAuthenticationGooglePackageVersion)" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@natemcmaster what's the new process to update the dependencies.props for AuthSamples? We are using the google reference to pull in the dependency right now, we just need the MicrosoftAspNetCoreAuthenticationPackageVersion

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update manually, or wait for @jkotalik who is starting on #4246 for auth samples soon.

<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="$(MicrosoftAspNetCoreAuthorizationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Extensions" Version="$(MicrosoftAspNetCoreDataProtectionExtensionsPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(MicrosoftAspNetCoreDiagnosticsPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="$(MicrosoftAspNetCoreDiagnosticsEntityFrameworkCorePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(MicrosoftAspNetCoreMvcPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="$(MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftExtensionsConfigurationUserSecretsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsLoggingDebugPackageVersion)" />
<PackageReference Include="Microsoft.NET.Sdk.Razor" Version="$(MicrosoftNETSdkRazorPackageVersion)" PrivateAssets="All" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@page
@model AboutModel
@{
ViewData["Title"] = "About";
}
<h2>@ViewData["Title"]</h2>
<h3>@Model.Message</h3>

<p>Use this area to provide additional information.</p>
18 changes: 18 additions & 0 deletions src/AuthSamples/samples/Options.MultiTenant/Pages/About.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Options.MultiTenant.Pages
{
public class AboutModel : PageModel
{
public string Message { get; set; }

public void OnGet()
{
Message = "Your application description page.";
}
}
}
19 changes: 19 additions & 0 deletions src/AuthSamples/samples/Options.MultiTenant/Pages/Contact.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@page
@model ContactModel
@{
ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"]</h2>
<h3>@Model.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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Options.MultiTenant.Pages
{
public class ContactModel : PageModel
{
public string Message { get; set; }

public void OnGet()
{
Message = "Your contact page.";
}
}
}
23 changes: 23 additions & 0 deletions src/AuthSamples/samples/Options.MultiTenant/Pages/Error.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}

<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
</p>
21 changes: 21 additions & 0 deletions src/AuthSamples/samples/Options.MultiTenant/Pages/Error.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Options.MultiTenant.Pages
{
public class ErrorModel : PageModel
{
public string RequestId { get; set; }

public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
}
}
53 changes: 53 additions & 0 deletions src/AuthSamples/samples/Options.MultiTenant/Pages/Index.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
@page
@using Microsoft.AspNetCore.Authentication
@using Microsoft.Extensions.Options
@inject IAuthenticationSchemeProvider SchemeProvider
@inject IOptionsMonitor<SimpleOptions> Options
@inject TenantResolver Tenants
@model IndexModel
@{
ViewData["Title"] = "Home page";
}

<div class="row">
<h2>Current Authentication Schemes for Tenant: @Tenants.ResolveTenant()</h2>
<ul>
@{
var schemes = await SchemeProvider.GetAllSchemesAsync();
foreach (var scheme in schemes)
{
<li><b>Scheme:</b> @scheme.Name -- <b>Client Id:Secret=</b> {@Options.Get(scheme.Name).ClientId}:{@Options.Get(scheme.Name).ClientSecret} <a asp-area="" asp-controller="Auth" asp-action="Remove" asp-route-scheme="@scheme.Name" asp-route-tenant="@Tenants.ResolveTenant()">Remove</a></li>
}
}
</ul>
</div>
<div class="row">
<h2>Add or update a scheme:</h2>
<form asp-controller="Auth" asp-action="AddOrUpdate" asp-route-tenant="@Tenants.ResolveTenant()" method="post" class="form-horizontal" role="form">
<div class="form-group">
<label class="col-md-2 control-label">Scheme</label>
<div class="col-md-10">
<input type="text" name="scheme" />
</div>
</div>

<div class="form-group">
<label class="col-md-2 control-label">ClientId</label>
<div class="col-md-10">
<input type="text" name="ClientId" />
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">ClientSecret</label>
<div class="col-md-10">
<input type="text" name="ClientSecret" />
</div>
</div>

<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Add/Update</button>
</div>
</div>
</form>
</div>
17 changes: 17 additions & 0 deletions src/AuthSamples/samples/Options.MultiTenant/Pages/Index.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Options.MultiTenant.Pages
{
public class IndexModel : PageModel
{
public void OnGet()
{

}
}
}
71 changes: 71 additions & 0 deletions src/AuthSamples/samples/Options.MultiTenant/Pages/_Layout.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Options.MultiTenant</title>

<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-page="/Index" class="navbar-brand">Options.MultiTenant</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-page="/Index">Home</a></li>
<li><a asp-page="/About">About</a></li>
<li><a asp-page="/Contact">Contact</a></li>
</ul>
</div>
</div>
</nav>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>&copy; 2017 - Options.MultiTenant</p>
</footer>
</div>

<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>

@RenderSection("Scripts", required: false)
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<environment include="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-Fnqn3nxp3506LP/7Y3j/25BlWeA3PXTyT1l78LjECcPaKCV12TsZP7yyMxOe/G/k">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-JrXK+k53HACyavUKOsL+NkmSesD2P+73eDMrbTtTk0h4RmOF8hF8apPlkp26JlyH">
</script>
</environment>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@using AuthSamples.Options.MultiTenant
@namespace Options.MultiTenant.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}
26 changes: 26 additions & 0 deletions src/AuthSamples/samples/Options.MultiTenant/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace AuthSamples.Options.MultiTenant
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args)
.Build()
.Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
14 changes: 14 additions & 0 deletions src/AuthSamples/samples/Options.MultiTenant/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
AuthSamples.Options.MultiTenant

Sample demonstrating dynamic authentication schemes and options with multiple tenants each having their own schemes and credentials:

1. Run the app, the Home page will show all the authentication schemes.
2. You can add new schemes via the form at the bottom, and remove any via the Remove button.
3. You can also update any of the scheme options message via the add/update form.
4. Tenant id is specified via query string ?tenant=id, each tenant should have its own set of schemes/creditials.

The dynamic scheme code very similar to the dynamic scheme sample, the relevant multitenant code is:
- TenantResolver: resolves the tenant from the request.
- TenantSchemeResolver: maintains the set of authentication schemes per tenant.
- TenantOptionsMonitor: resolves the appropriate set of authentication options for the tenant.
- TenantOptionsCache: allows the app to invalidate/update the options for a particular scheme.
Loading