Browse Source

Remove the authorization endpoint resolution logic and update the sample to use FormValueRequiredAttribute

pull/261/head
Kévin Chalet 9 years ago
parent
commit
2cc29a8d92
  1. 13
      samples/Mvc.Server/Controllers/AuthorizationController.cs
  2. 33
      samples/Mvc.Server/Helpers/FormValueRequiredAttribute.cs
  3. 4
      samples/Mvc.Server/Views/Authorization/Authorize.cshtml
  4. 14
      src/OpenIddict.Core/Infrastructure/OpenIddictProvider.cs

13
samples/Mvc.Server/Controllers/AuthorizationController.cs

@ -5,7 +5,6 @@
*/
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Extensions;
using AspNet.Security.OpenIdConnect.Server;
@ -14,6 +13,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Mvc.Server.Helpers;
using Mvc.Server.Models;
using Mvc.Server.ViewModels.Authorization;
using Mvc.Server.ViewModels.Shared;
@ -37,7 +37,7 @@ namespace Mvc.Server {
// Note: to support interactive flows like the code flow,
// you must provide your own authorization endpoint action:
[Authorize, HttpGet, Route("~/connect/authorize")]
[Authorize, HttpGet("~/connect/authorize")]
public async Task<IActionResult> Authorize(OpenIdConnectRequest request) {
// Retrieve the application details from the database.
var application = await _applicationManager.FindByClientIdAsync(request.ClientId);
@ -57,7 +57,8 @@ namespace Mvc.Server {
});
}
[Authorize, HttpPost("~/connect/authorize/accept"), ValidateAntiForgeryToken]
[Authorize, FormValueRequired("submit.Accept")]
[HttpPost("~/connect/authorize"), ValidateAntiForgeryToken]
public async Task<IActionResult> Accept(OpenIdConnectRequest request) {
// Retrieve the profile of the logged in user.
var user = await _userManager.GetUserAsync(User);
@ -75,7 +76,8 @@ namespace Mvc.Server {
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
[Authorize, HttpPost("~/connect/authorize/deny"), ValidateAntiForgeryToken]
[Authorize, FormValueRequired("submit.Deny")]
[HttpPost("~/connect/authorize"), ValidateAntiForgeryToken]
public IActionResult Deny() {
// Notify OpenIddict that the authorization grant has been denied by the resource owner
// to redirect the user agent to the client application using the appropriate response_mode.
@ -109,8 +111,7 @@ namespace Mvc.Server {
// Note: to support non-interactive flows like password,
// you must provide your own token endpoint action:
[HttpPost("~/connect/token")]
[Produces("application/json")]
[HttpPost("~/connect/token"), Produces("application/json")]
public async Task<IActionResult> Exchange(OpenIdConnectRequest request) {
if (request.IsPasswordGrantType()) {
var user = await _userManager.FindByNameAsync(request.Username);

33
samples/Mvc.Server/Helpers/FormValueRequiredAttribute.cs

@ -0,0 +1,33 @@
using System;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Routing;
namespace Mvc.Server.Helpers {
public sealed class FormValueRequiredAttribute : ActionMethodSelectorAttribute {
private readonly string _name;
public FormValueRequiredAttribute(string name) {
_name = name;
}
public override bool IsValidForRequest(RouteContext context, ActionDescriptor action) {
if (string.Equals(context.HttpContext.Request.Method, "GET", StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.HttpContext.Request.Method, "HEAD", StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.HttpContext.Request.Method, "DELETE", StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.HttpContext.Request.Method, "TRACE", StringComparison.OrdinalIgnoreCase)) {
return false;
}
if (string.IsNullOrEmpty(context.HttpContext.Request.ContentType)) {
return false;
}
if (!context.HttpContext.Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) {
return false;
}
return !string.IsNullOrEmpty(context.HttpContext.Request.Form[_name]);
}
}
}

4
samples/Mvc.Server/Views/Authorization/Authorize.cshtml

@ -10,7 +10,7 @@
<input type="hidden" name="request_id" value="@Model.RequestId" />
<input formaction="@Url.Action("Accept")" class="btn btn-lg btn-success" name="Authorize" type="submit" value="Yes" />
<input formaction="@Url.Action("Deny")" class="btn btn-lg btn-danger" name="Deny" type="submit" value="No" />
<input class="btn btn-lg btn-success" name="submit.Accept" type="submit" value="Yes" />
<input class="btn btn-lg btn-danger" name="submit.Deny" type="submit" value="No" />
</form>
</div>

14
src/OpenIddict.Core/Infrastructure/OpenIddictProvider.cs

@ -4,23 +4,11 @@
* the license and the contributors participating to this project.
*/
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Server;
using JetBrains.Annotations;
namespace OpenIddict.Infrastructure {
public partial class OpenIddictProvider<TApplication, TAuthorization, TScope, TToken> : OpenIdConnectServerProvider
where TApplication : class where TAuthorization : class where TScope : class where TToken : class {
public override Task MatchEndpoint([NotNull] MatchEndpointContext context) {
// Note: by default, OpenIdConnectServerHandler only handles authorization requests made to AuthorizationEndpointPath.
// This context handler uses a more relaxed policy that allows extracting authorization requests received at
// /connect/authorize/accept and /connect/authorize/deny (see OpenIddictController.cs for more information).
if (context.Options.AuthorizationEndpointPath.HasValue &&
context.Request.Path.StartsWithSegments(context.Options.AuthorizationEndpointPath)) {
context.MatchesAuthorizationEndpoint();
}
return Task.FromResult<object>(null);
}
// Note: this class is split into specialized partial classes.
}
}
Loading…
Cancel
Save