Browse Source

Reject authorization requests using the implicit/hybrid flow when the client is a confidential application

pull/27/merge
Kévin Chalet 10 years ago
parent
commit
50eb0c94bd
  1. 61
      src/OpenIddict.Core/OpenIddictProvider.cs

61
src/OpenIddict.Core/OpenIddictProvider.cs

@ -7,7 +7,6 @@
using System;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Extensions;
@ -101,9 +100,9 @@ namespace OpenIddict {
return;
}
// Retrieve the application details corresponding to the requested client_id.
var manager = context.HttpContext.RequestServices.GetRequiredService<OpenIddictManager<TUser, TApplication>>();
// Retrieve the application details corresponding to the requested client_id.
var application = await manager.FindApplicationByIdAsync(context.ClientId);
if (application == null) {
context.Rejected(
@ -138,40 +137,52 @@ namespace OpenIddict {
}
public override async Task ValidateAuthorizationRequest([NotNull] ValidateAuthorizationRequestContext context) {
// Only validate prompt=none requests at this stage.
if (!string.Equals(context.Request.Prompt, "none", StringComparison.Ordinal)) {
return;
}
var manager = context.HttpContext.RequestServices.GetRequiredService<OpenIddictManager<TUser, TApplication>>();
// Extract the principal contained in the id_token_hint parameter.
// If no principal can be extracted, an error is returned to the client application.
var principal = await context.HttpContext.Authentication.AuthenticateAsync(context.Options.AuthenticationScheme);
if (principal == null) {
// Retrieve the application details corresponding to the requested client_id.
var application = await manager.FindApplicationByIdAsync(context.ClientContext.ClientId);
Debug.Assert(application != null);
// To prevent downgrade attacks, ensure that authorization requests using the hybrid/implicit
// flow are rejected if the client identifier corresponds to a confidential application.
var type = await manager.GetApplicationTypeAsync(application);
if (type == OpenIddictConstants.ApplicationTypes.Confidential && !context.Request.IsAuthorizationCodeFlow()) {
context.Rejected(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The required id_token_hint parameter is missing");
description: "Confidential clients can only use response_type=code.");
return;
}
if (!string.Equals(principal.FindFirstValue(JwtRegisteredClaimNames.Aud), context.Request.ClientId)) {
context.Rejected(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The id_token_hint parameter is invalid");
if (string.Equals(context.Request.Prompt, "none", StringComparison.Ordinal)) {
// Extract the principal contained in the id_token_hint parameter.
// If no principal can be extracted, an error is returned to the client application.
var principal = await context.HttpContext.Authentication.AuthenticateAsync(context.Options.AuthenticationScheme);
if (principal == null) {
context.Rejected(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The required id_token_hint parameter is missing");
return;
}
return;
}
var manager = context.HttpContext.RequestServices.GetRequiredService<OpenIddictManager<TUser, TApplication>>();
if (!string.Equals(principal.FindFirstValue(JwtRegisteredClaimNames.Aud), context.Request.ClientId)) {
context.Rejected(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The id_token_hint parameter is invalid");
// Ensure the user still exists.
var user = await manager.FindByIdAsync(principal.GetUserId());
if (user == null) {
context.Rejected(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The id_token_hint parameter is invalid");
return;
}
return;
// Ensure the user still exists.
var user = await manager.FindByIdAsync(principal.GetUserId());
if (user == null) {
context.Rejected(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The id_token_hint parameter is invalid");
return;
}
}
}

Loading…
Cancel
Save