réactive oidc, définitivement.
This commit is contained in:
parent
d5bcfd19f6
commit
ebed4d2c50
7 changed files with 356 additions and 98 deletions
|
|
@ -1,17 +1,53 @@
|
||||||
|
|
||||||
@using Microsoft.AspNet.Http.Authentication
|
@using Microsoft.AspNet.Http.Authentication
|
||||||
@model IEnumerable<AuthenticationDescription>
|
@using Yavsc.ViewModels.Account
|
||||||
|
@model LoginViewModel
|
||||||
|
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
<h1>Authentication</h1>
|
<h1>Authentication</h1>
|
||||||
<p class="lead text-left">Sign in using one of these external providers:</p>
|
<hr/>
|
||||||
|
<h2 class="lead text-left">Use a local account to log in</h2>
|
||||||
|
<form action="/login" method="post" class="form-horizontal" role="form">
|
||||||
|
|
||||||
@foreach (var description in Model) {
|
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="UserName" class="col-md-2 control-label">User name</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input asp-for="UserName" class="form-control" />
|
||||||
|
<span asp-validation-for="UserName" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="Password" class="col-md-2 control-label">Password</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input asp-for="Password" class="form-control" />
|
||||||
|
<span asp-validation-for="Password" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-offset-2 col-md-10">
|
||||||
|
<button type="submit" class="btn btn-lg btn-success">Login</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a asp-action="Register">Register as a new user?</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a asp-action="ForgotPassword">Forgot your password?</a>
|
||||||
|
</p>
|
||||||
|
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
|
||||||
|
@Html.AntiForgeryToken()
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<h2 class="lead text-left">Sign in using one of these external providers:</h2>
|
||||||
|
@foreach (var description in Model.ExternalProviders) {
|
||||||
<form action="/signin" method="post">
|
<form action="/signin" method="post">
|
||||||
<input type="hidden" name="Provider" value="@description.AuthenticationScheme" />
|
<input type="hidden" name="Provider" value="@description.AuthenticationScheme" />
|
||||||
<input type="hidden" name="ReturnUrl" value="@ViewBag.ReturnUrl" />
|
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
|
||||||
|
|
||||||
<button class="btn btn-lg btn-success" type="submit">Connect using @description.DisplayName</button>
|
<button class="btn btn-lg btn-success" type="submit">Connect using @description.DisplayName</button>
|
||||||
|
@Html.AntiForgeryToken()
|
||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -44,9 +44,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-collapse collapse">
|
<div class="navbar-collapse collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li><a asp-controller="Home" asp-action="Index">@SR["Home"]</a></li>
|
<li><a asp-controller="Home" asp-action="Index" class="navbar-link">@SR["Home"]</a></li>
|
||||||
<li><a asp-controller="Home" asp-action="About">@SR["About"] @SiteSettings.Value.Title</a> </li>
|
<li><a asp-controller="Home" asp-action="About" class="navbar-link">@SR["About"] @SiteSettings.Value.Title</a> </li>
|
||||||
<li><a asp-controller="Home" asp-action="Contact">@SR["Contact"]</a></li>
|
<li><a asp-controller="Home" asp-action="Contact" class="navbar-link">@SR["Contact"]</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
@await Html.PartialAsync("_LoginPartial")
|
@await Html.PartialAsync("_LoginPartial")
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@
|
||||||
<language-layout>
|
<language-layout>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li>
|
<li>
|
||||||
<a asp-controller="Manage" asp-action="Index" title="Manage">@SR["Hello"] @User.GetUserName()!</a>
|
<a asp-controller="Manage" class="navbar-link" asp-action="Index" title="Manage">@SR["Hello"] @User.GetUserName()!</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button type="submit" class="btn btn-link navbar-btn navbar-link">@SR["Logout"]</button>
|
<button type="submit" class="navbar-link">@SR["Logout"]</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</language-layout>
|
</language-layout>
|
||||||
|
|
@ -18,8 +18,9 @@
|
||||||
else
|
else
|
||||||
{ <language-layout>
|
{ <language-layout>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li><a asp-controller="Account" asp-action="Register">@SR["Register"]</a></li>
|
<li><a class="navbar-link" asp-controller="Account" asp-action="Register">@SR["Register"]</a></li>
|
||||||
<li><a asp-controller="Account" asp-action="Login">@SR["Login"]</a></li>
|
<li><a class="navbar-link" asp-controller="Account" asp-action="SignIn">@SR["Login"]</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</language-layout>
|
</language-layout>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Authorization;
|
using Microsoft.AspNet.Authorization;
|
||||||
|
using Microsoft.AspNet.Http.Authentication;
|
||||||
using Microsoft.AspNet.Identity;
|
using Microsoft.AspNet.Identity;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
|
|
@ -50,14 +51,30 @@ namespace Yavsc.Controllers
|
||||||
_twilioSettings = twilioSettings.Value;
|
_twilioSettings = twilioSettings.Value;
|
||||||
_logger = loggerFactory.CreateLogger<AccountController>();
|
_logger = loggerFactory.CreateLogger<AccountController>();
|
||||||
}
|
}
|
||||||
|
[HttpGet("~/signin")]
|
||||||
//
|
public ActionResult SignIn(string returnUrl = "/")
|
||||||
// GET: /Account/Login
|
|
||||||
[HttpGet]
|
|
||||||
public IActionResult Login(string returnUrl = null)
|
|
||||||
{
|
{
|
||||||
ViewData["ReturnUrl"] = returnUrl;
|
return View("SignIn", new LoginViewModel
|
||||||
return View();
|
{
|
||||||
|
ReturnUrl = returnUrl,
|
||||||
|
ExternalProviders = _signInManager.GetExternalAuthenticationSchemes()
|
||||||
|
});
|
||||||
|
/* When using an external login provider :
|
||||||
|
// Request a redirect to the external login provider.
|
||||||
|
var redirectUrl = returnUrl ?? "/";
|
||||||
|
var properties = _signInManager.ConfigureExternalAuthenticationProperties(OpenIdConnectDefaults.AuthenticationScheme, redirectUrl);
|
||||||
|
return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme, properties);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("~/signout"), HttpPost("~/signout")]
|
||||||
|
public async Task<IActionResult> SignOut(string returnUrl = "/")
|
||||||
|
{
|
||||||
|
// Instruct the cookies middleware to delete the local cookie created when the user agent
|
||||||
|
// is redirected from the identity provider after a successful authorization flow and
|
||||||
|
// to redirect the user agent to the identity provider to sign out.
|
||||||
|
await _signInManager.SignOutAsync();
|
||||||
|
return Redirect(returnUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResult Forbidden()
|
public IActionResult Forbidden()
|
||||||
|
|
@ -65,15 +82,45 @@ namespace Yavsc.Controllers
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST: /Account/Login
|
[HttpPost("~/signin")]
|
||||||
[HttpPost]
|
public async Task<IActionResult> SignIn(string provider, string returnUrl)
|
||||||
[ValidateAntiForgeryToken]
|
|
||||||
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
|
|
||||||
{
|
|
||||||
ViewData["ReturnUrl"] = returnUrl;
|
|
||||||
if (ModelState.IsValid)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Note: the "provider" parameter corresponds to the external
|
||||||
|
// authentication provider choosen by the user agent.
|
||||||
|
if (string.IsNullOrEmpty(provider))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("null provider");
|
||||||
|
ModelState.AddModelError("provider", "provider cannot be null");
|
||||||
|
return new BadRequestObjectResult(ModelState);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Note: the "returnUrl" parameter corresponds to the endpoint the user agent
|
||||||
|
// will be redirected to after a successful authentication and not
|
||||||
|
// the redirect_uri of the requesting client application.
|
||||||
|
if (string.IsNullOrEmpty(returnUrl))
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"null returnUrl ({provider}) ");
|
||||||
|
ModelState.AddModelError("returnUrl", "returnUrl cannot be null");
|
||||||
|
return new BadRequestObjectResult(ModelState);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instruct the middleware corresponding to the requested external identity
|
||||||
|
// provider to redirect the user agent to its own authorization endpoint.
|
||||||
|
// Note: the authenticationScheme parameter must match the value configured in Startup.cs
|
||||||
|
// Request a redirect to the external login provider.
|
||||||
|
|
||||||
|
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
|
||||||
|
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
|
||||||
|
return new ChallengeResult(provider, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("~/login")]
|
||||||
|
public async Task<IActionResult> LocalLogin(LoginViewModel model)
|
||||||
|
{
|
||||||
|
if (ModelState.IsValid)
|
||||||
|
{
|
||||||
// This doesn't count login failures towards account lockout
|
// This doesn't count login failures towards account lockout
|
||||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
||||||
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);
|
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);
|
||||||
|
|
@ -81,11 +128,11 @@ namespace Yavsc.Controllers
|
||||||
{
|
{
|
||||||
_logger.LogInformation(1, "User logged in.");
|
_logger.LogInformation(1, "User logged in.");
|
||||||
|
|
||||||
return RedirectToLocal(returnUrl);
|
return RedirectToLocal(model.ReturnUrl);
|
||||||
}
|
}
|
||||||
if (result.RequiresTwoFactor)
|
if (result.RequiresTwoFactor)
|
||||||
{
|
{
|
||||||
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
|
return RedirectToAction(nameof(SendCode), new { ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe });
|
||||||
}
|
}
|
||||||
if (result.IsLockedOut)
|
if (result.IsLockedOut)
|
||||||
{
|
{
|
||||||
|
|
@ -98,11 +145,9 @@ namespace Yavsc.Controllers
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got this far, something failed, redisplay form
|
// If we got this far, something failed, redisplay form
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// GET: /Account/Register
|
// GET: /Account/Register
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|
@ -171,7 +216,7 @@ namespace Yavsc.Controllers
|
||||||
var info = await _signInManager.GetExternalLoginInfoAsync();
|
var info = await _signInManager.GetExternalLoginInfoAsync();
|
||||||
if (info == null)
|
if (info == null)
|
||||||
{
|
{
|
||||||
return RedirectToAction(nameof(Login));
|
return RedirectToAction(nameof(SignIn));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign in the user with this external login provider if the user already has a login.
|
// Sign in the user with this external login provider if the user already has a login.
|
||||||
|
|
@ -210,8 +255,11 @@ namespace Yavsc.Controllers
|
||||||
var token_type = info.ExternalPrincipal.FindFirstValue("token_type");
|
var token_type = info.ExternalPrincipal.FindFirstValue("token_type");
|
||||||
var expires_in = info.ExternalPrincipal.FindFirstValue("expires_in");
|
var expires_in = info.ExternalPrincipal.FindFirstValue("expires_in");
|
||||||
|
|
||||||
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email,
|
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel
|
||||||
Name = name });
|
{
|
||||||
|
Email = email,
|
||||||
|
Name = name
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
128
Yavsc/src/Providers/OAuthProvider.cs
Normal file
128
Yavsc/src/Providers/OAuthProvider.cs
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AspNet.Security.OpenIdConnect.Extensions;
|
||||||
|
using AspNet.Security.OpenIdConnect.Server;
|
||||||
|
using Microsoft.Data.Entity;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Yavsc.Models;
|
||||||
|
|
||||||
|
namespace Yavsc.Providers {
|
||||||
|
public sealed class AuthorizationProvider : OpenIdConnectServerProvider {
|
||||||
|
|
||||||
|
private ILogger _logger;
|
||||||
|
|
||||||
|
public AuthorizationProvider(ILoggerFactory loggerFactory) {
|
||||||
|
_logger = loggerFactory.CreateLogger<AuthorizationProvider>();
|
||||||
|
}
|
||||||
|
public override Task MatchEndpoint(MatchEndpointContext context) {
|
||||||
|
// Note: by default, OpenIdConnectServerHandler only handles authorization requests made to the authorization endpoint.
|
||||||
|
// This context handler uses a more relaxed policy that allows extracting authorization requests received at
|
||||||
|
// /connect/authorize/accept and /connect/authorize/deny (see AuthorizationController.cs for more information).
|
||||||
|
if (context.Options.AuthorizationEndpointPath.HasValue &&
|
||||||
|
context.Request.Path.StartsWithSegments(context.Options.AuthorizationEndpointPath)) {
|
||||||
|
context.MatchesAuthorizationEndpoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult<object>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) {
|
||||||
|
// Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows
|
||||||
|
// but this authorization provider only accepts response_type=code authorization/authentication requests.
|
||||||
|
// You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding
|
||||||
|
// checks rejecting implicit/hybrid authorization requests when the client is a confidential application.
|
||||||
|
if (!context.Request.IsAuthorizationCodeFlow()) {
|
||||||
|
context.Rejected(
|
||||||
|
error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
|
||||||
|
description: "Only the authorization code flow is supported by this authorization server");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var database = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
|
||||||
|
_logger.LogInformation($"Searching fo app id {context.ClientId}");
|
||||||
|
|
||||||
|
// Retrieve the application details corresponding to the requested client_id.
|
||||||
|
var application = await (from entity in database.Applications
|
||||||
|
where entity.ApplicationID == context.ClientId
|
||||||
|
select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted);
|
||||||
|
|
||||||
|
if (application == null) {
|
||||||
|
context.Rejected(
|
||||||
|
error: OpenIdConnectConstants.Errors.InvalidClient,
|
||||||
|
description: "Application not found in the database: ensure that your client_id is correct");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(context.Request.RedirectUri) &&
|
||||||
|
!string.Equals(context.Request.RedirectUri, application.RedirectUri, StringComparison.Ordinal)) {
|
||||||
|
context.Rejected(
|
||||||
|
error: OpenIdConnectConstants.Errors.InvalidClient,
|
||||||
|
description: "Invalid redirect_uri");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Validated();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) {
|
||||||
|
// Note: the OpenID Connect server middleware supports authorization code, refresh token, client credentials
|
||||||
|
// and resource owner password credentials grant types but this authorization provider uses a safer policy
|
||||||
|
// rejecting the last two ones. You may consider relaxing it to support the ROPC or client credentials grant types.
|
||||||
|
if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType()) {
|
||||||
|
context.Rejected(
|
||||||
|
error: OpenIdConnectConstants.Errors.UnsupportedGrantType,
|
||||||
|
description: "Only authorization code and refresh token grant types " +
|
||||||
|
"are accepted by this authorization server");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: client authentication is not mandatory for non-confidential client applications like mobile apps
|
||||||
|
// (except when using the client credentials grant type) but this authorization server uses a safer policy
|
||||||
|
// that makes client authentication mandatory and returns an error if client_id or client_secret is missing.
|
||||||
|
// You may consider relaxing it to support the resource owner password credentials grant type
|
||||||
|
// with JavaScript or desktop applications, where client credentials cannot be safely stored.
|
||||||
|
// In this case, call context.Skip() to inform the server middleware the client is not trusted.
|
||||||
|
if (string.IsNullOrEmpty(context.Request.ClientId) || string.IsNullOrEmpty(context.Request.ClientSecret)) {
|
||||||
|
context.Rejected(
|
||||||
|
error: OpenIdConnectConstants.Errors.InvalidRequest,
|
||||||
|
description: "Missing credentials: ensure that your credentials were correctly " +
|
||||||
|
"flowed in the request body or in the authorization header");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var database = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
|
||||||
|
|
||||||
|
// Retrieve the application details corresponding to the requested client_id.
|
||||||
|
var application = await (from entity in database.Applications
|
||||||
|
where entity.ApplicationID == context.ClientId
|
||||||
|
select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted);
|
||||||
|
|
||||||
|
if (application == null) {
|
||||||
|
context.Rejected(
|
||||||
|
error: OpenIdConnectConstants.Errors.InvalidClient,
|
||||||
|
description: "Application not found in the database: ensure that your client_id is correct");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.Equals(context.Request.ClientSecret, application.Secret, StringComparison.Ordinal)) {
|
||||||
|
context.Rejected(
|
||||||
|
error: OpenIdConnectConstants.Errors.InvalidClient,
|
||||||
|
description: "Invalid credentials: ensure that you specified a correct client_secret");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Validated();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -35,8 +35,10 @@ using Microsoft.Extensions.PlatformAbstractions;
|
||||||
using Microsoft.Extensions.WebEncoders;
|
using Microsoft.Extensions.WebEncoders;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Yavsc.Auth;
|
using Yavsc.Auth;
|
||||||
|
using Yavsc.Extensions;
|
||||||
using Yavsc.Formatters;
|
using Yavsc.Formatters;
|
||||||
using Yavsc.Models;
|
using Yavsc.Models;
|
||||||
|
using Yavsc.Providers;
|
||||||
using Yavsc.Services;
|
using Yavsc.Services;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -66,8 +68,6 @@ namespace Yavsc
|
||||||
"~/bower_components/dropzone/dist/min/basic.min.css",
|
"~/bower_components/dropzone/dist/min/basic.min.css",
|
||||||
"~/bower_components/dropzone/dist/min/dropzone.min.css"
|
"~/bower_components/dropzone/dist/min/dropzone.min.css"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,7 +155,8 @@ namespace Yavsc
|
||||||
RSAKeyUtils.GetKeyParameters(keyParamsFileInfo.Name) :
|
RSAKeyUtils.GetKeyParameters(keyParamsFileInfo.Name) :
|
||||||
RSAKeyUtils.GenerateKeyAndSave(keyParamsFileInfo.Name);
|
RSAKeyUtils.GenerateKeyAndSave(keyParamsFileInfo.Name);
|
||||||
key = new RsaSecurityKey(keyParams);
|
key = new RsaSecurityKey(keyParams);
|
||||||
services.Configure<SharedAuthenticationOptions>(options => {
|
services.Configure<SharedAuthenticationOptions>(options =>
|
||||||
|
{
|
||||||
options.SignInScheme = "ServerCookie";
|
options.SignInScheme = "ServerCookie";
|
||||||
});
|
});
|
||||||
services.Configure<TokenAuthOptions>(
|
services.Configure<TokenAuthOptions>(
|
||||||
|
|
@ -187,8 +188,10 @@ namespace Yavsc
|
||||||
configure.PersistKeysToFileSystem(
|
configure.PersistKeysToFileSystem(
|
||||||
new DirectoryInfo(Configuration["DataProtection:Keys:Dir"]));
|
new DirectoryInfo(Configuration["DataProtection:Keys:Dir"]));
|
||||||
});
|
});
|
||||||
services.AddAuthentication();
|
|
||||||
|
|
||||||
|
services.AddAuthentication(options => {
|
||||||
|
options.SignInScheme = "ServerCookie"; }
|
||||||
|
);
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddEntityFramework()
|
services.AddEntityFramework()
|
||||||
.AddNpgsql()
|
.AddNpgsql()
|
||||||
|
|
@ -232,7 +235,8 @@ namespace Yavsc
|
||||||
{
|
{
|
||||||
options.AddPolicy("AdministratorOnly", policy => policy.RequireRole(Constants.AdminGroupName));
|
options.AddPolicy("AdministratorOnly", policy => policy.RequireRole(Constants.AdminGroupName));
|
||||||
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));
|
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));
|
||||||
options.AddPolicy("API", policy => {
|
options.AddPolicy("API", policy =>
|
||||||
|
{
|
||||||
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
|
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
|
||||||
policy.RequireClaim(OpenIdConnectConstants.Claims.Scope, "api-resource-controller");
|
policy.RequireClaim(OpenIdConnectConstants.Claims.Scope, "api-resource-controller");
|
||||||
});
|
});
|
||||||
|
|
@ -340,12 +344,6 @@ namespace Yavsc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new branch where the registered middleware will be executed only for API calls.
|
|
||||||
/* MapWhenExtensions.MapWhen(app,(Func<Microsoft.AspNet.Http.HttpContext, bool>)(context =>
|
|
||||||
context.Request.Path.StartsWithSegments((PathString)new PathString((string)"/api"))),
|
|
||||||
(Action<IApplicationBuilder>)( branch => { }));
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
var googleOptions = new GoogleOptions
|
var googleOptions = new GoogleOptions
|
||||||
{
|
{
|
||||||
|
|
@ -376,6 +374,80 @@ namespace Yavsc
|
||||||
|
|
||||||
googleOptions.Scope.Add("https://www.googleapis.com/auth/calendar");
|
googleOptions.Scope.Add("https://www.googleapis.com/auth/calendar");
|
||||||
|
|
||||||
|
app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());
|
||||||
|
|
||||||
|
app.UseStaticFiles().UseWebSockets();
|
||||||
|
|
||||||
|
app.UseRequestLocalization(localizationOptions.Value, (RequestCulture)new RequestCulture((string)"fr"));
|
||||||
|
|
||||||
|
app.UseIdentity();
|
||||||
|
|
||||||
|
app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>
|
||||||
|
{
|
||||||
|
branch.UseJwtBearerAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.AutomaticAuthenticate = true;
|
||||||
|
options.AutomaticChallenge = true;
|
||||||
|
options.RequireHttpsMetadata = false;
|
||||||
|
options.Audience = siteSettings.Value.Audience;
|
||||||
|
options.Authority = siteSettings.Value.Authority;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a new branch where the registered middleware will be executed only for API calls.
|
||||||
|
app.UseWhen(context => !context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>
|
||||||
|
{
|
||||||
|
// Create a new branch where the registered middleware will be executed only for non API calls.
|
||||||
|
branch.UseCookieAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.AutomaticAuthenticate = true;
|
||||||
|
options.AutomaticChallenge = true;
|
||||||
|
options.AuthenticationScheme = "ServerCookie";
|
||||||
|
options.CookieName = CookieAuthenticationDefaults.CookiePrefix + "ServerCookie";
|
||||||
|
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||||
|
options.LoginPath = new PathString("/signin");
|
||||||
|
options.LogoutPath = new PathString("/signout");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
branch.UseMiddleware<GoogleMiddleware>(googleOptions);
|
||||||
|
|
||||||
|
// Facebook
|
||||||
|
branch.UseFacebookAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.AppId = Configuration["Authentication:Facebook:AppId"];
|
||||||
|
options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
|
||||||
|
options.Scope.Add("email");
|
||||||
|
options.UserInformationEndpoint = "https://graph.facebook.com/v2.5/me?fields=id,name,email,first_name,last_name";
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
app.UseOpenIdConnectServer(options =>
|
||||||
|
{
|
||||||
|
options.Provider = new AuthorizationProvider(loggerFactory);
|
||||||
|
|
||||||
|
// Register the certificate used to sign the JWT tokens.
|
||||||
|
/* options.SigningCredentials.AddCertificate(
|
||||||
|
assembly: typeof(Startup).GetTypeInfo().Assembly,
|
||||||
|
resource: "Mvc.Server.Certificate.pfx",
|
||||||
|
password: "Owin.Security.OpenIdConnect.Server"); */
|
||||||
|
|
||||||
|
// options.SigningCredentials.AddKey(key);
|
||||||
|
// Note: see AuthorizationController.cs for more
|
||||||
|
// information concerning ApplicationCanDisplayErrors.
|
||||||
|
options.ApplicationCanDisplayErrors = true;
|
||||||
|
options.AllowInsecureHttp = true;
|
||||||
|
options.AutomaticChallenge = true;
|
||||||
|
options.AuthorizationEndpointPath = new PathString("/connect/authorize");
|
||||||
|
options.TokenEndpointPath = new PathString("/connect/authorize/accept");
|
||||||
|
options.UseSlidingExpiration = true;
|
||||||
|
options.AllowInsecureHttp = true;
|
||||||
|
options.AuthenticationScheme = "oidc"; // was = OpenIdConnectDefaults.AuthenticationScheme;
|
||||||
|
options.LogoutEndpointPath = new PathString("/connect/logout");
|
||||||
|
/* options.ValidationEndpointPath = new PathString("/connect/introspect"); */
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
var udirinfo = new DirectoryInfo(Configuration["Site:UserFiles:RootDir"]);
|
var udirinfo = new DirectoryInfo(Configuration["Site:UserFiles:RootDir"]);
|
||||||
if (!udirinfo.Exists)
|
if (!udirinfo.Exists)
|
||||||
throw new Exception($"Configuration value for Site:UserFiles:RootDir : {udirinfo.FullName}");
|
throw new Exception($"Configuration value for Site:UserFiles:RootDir : {udirinfo.FullName}");
|
||||||
|
|
@ -389,38 +461,6 @@ namespace Yavsc
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());
|
|
||||||
|
|
||||||
app.UseStaticFiles().UseWebSockets();
|
|
||||||
|
|
||||||
app.UseRequestLocalization(localizationOptions.Value, (RequestCulture)new RequestCulture((string)"fr"));
|
|
||||||
|
|
||||||
app.UseIdentity();
|
|
||||||
|
|
||||||
// Create a new branch where the registered middleware will be executed only for non API calls.
|
|
||||||
app.UseCookieAuthentication(options => {
|
|
||||||
options.AutomaticAuthenticate = true;
|
|
||||||
options.AutomaticChallenge = true;
|
|
||||||
options.AuthenticationScheme = "ServerCookie";
|
|
||||||
options.CookieName = CookieAuthenticationDefaults.CookiePrefix + "ServerCookie";
|
|
||||||
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
|
||||||
options.LoginPath = new PathString("/Account/Login");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
app.UseMiddleware<GoogleMiddleware>(googleOptions);
|
|
||||||
|
|
||||||
// Facebook
|
|
||||||
app.UseFacebookAuthentication(options =>
|
|
||||||
{
|
|
||||||
options.AppId = Configuration["Authentication:Facebook:AppId"];
|
|
||||||
options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
|
|
||||||
options.Scope.Add("email");
|
|
||||||
options.UserInformationEndpoint = "https://graph.facebook.com/v2.5/me?fields=id,name,email,first_name,last_name";
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Generic OAuth (here GitHub): options.Notifications = new OAuthAuthenticationNotifications
|
/* Generic OAuth (here GitHub): options.Notifications = new OAuthAuthenticationNotifications
|
||||||
{
|
{
|
||||||
OnGetUserInformationAsync = async context =>
|
OnGetUserInformationAsync = async context =>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.AspNet.Http.Authentication;
|
||||||
|
|
||||||
namespace Yavsc.ViewModels.Account
|
namespace Yavsc.ViewModels.Account
|
||||||
{
|
{
|
||||||
|
|
@ -14,5 +16,8 @@ namespace Yavsc.ViewModels.Account
|
||||||
|
|
||||||
[Display(Name = "Remember me?")]
|
[Display(Name = "Remember me?")]
|
||||||
public bool RememberMe { get; set; }
|
public bool RememberMe { get; set; }
|
||||||
|
public string ReturnUrl { get; set; }
|
||||||
|
|
||||||
|
public IEnumerable<AuthenticationDescription> ExternalProviders { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue