Browse Source

Update the authorization/logout endpoints to automatically validate id_token_hint and refactor HandleAuthenticateAsync()/AuthenticateCoreAsync()

pull/779/head
Kévin Chalet 7 years ago
committed by GitHub
parent
commit
37e08b20d9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 170
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs
  2. 172
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs
  3. 2
      src/OpenIddict.Server/OpenIddictServerConstants.cs
  4. 37
      src/OpenIddict.Server/OpenIddictServerEvents.cs
  5. 16
      src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs
  6. 136
      src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
  7. 28
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  8. 44
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  9. 74
      src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs
  10. 15
      src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs
  11. 154
      src/OpenIddict.Server/OpenIddictServerHandlers.cs

170
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs

@ -114,157 +114,57 @@ namespace OpenIddict.Server.AspNetCore
throw new InvalidOperationException("An identity cannot be extracted from this request.");
}
switch (transaction.EndpointType)
{
case OpenIddictServerEndpointType.Authorization:
case OpenIddictServerEndpointType.Logout:
{
if (string.IsNullOrEmpty(transaction.Request.IdTokenHint))
{
return AuthenticateResult.NoResult();
}
var notification = new DeserializeIdentityTokenContext(transaction)
{
Token = transaction.Request.IdTokenHint
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The identity token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating identity tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
return AuthenticateResult.Fail("The identity token is not valid.");
}
var context = new ProcessAuthenticationContext(transaction);
await _provider.DispatchAsync(context);
// Note: tickets are returned even if they are considered invalid (e.g expired).
if (context.Principal == null || context.IsRequestHandled || context.IsRequestSkipped)
{
return AuthenticateResult.NoResult();
}
return AuthenticateResult.Success(new AuthenticationTicket(
notification.Principal,
OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
}
else if (context.IsRejected)
{
var builder = new StringBuilder();
case OpenIddictServerEndpointType.Token when transaction.Request.IsAuthorizationCodeGrantType():
if (!string.IsNullOrEmpty(context.Error))
{
// Note: this method can be called from the ApplyTokenResponse event,
// which may be invoked for a missing authorization code/refresh token.
if (string.IsNullOrEmpty(transaction.Request.Code))
{
return AuthenticateResult.NoResult();
}
builder.AppendLine("An error occurred while authenticating the current request:");
builder.AppendFormat("Error code: ", context.Error);
var notification = new DeserializeAuthorizationCodeContext(transaction)
if (!string.IsNullOrEmpty(context.ErrorDescription))
{
Token = transaction.Request.Code
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The authorization code was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating authorization codes ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
builder.AppendLine();
builder.AppendFormat("Error description: ", context.ErrorDescription);
}
if (notification.Principal == null)
if (!string.IsNullOrEmpty(context.ErrorUri))
{
return AuthenticateResult.Fail("The authorization code is not valid.");
builder.AppendLine();
builder.AppendFormat("Error URI: ", context.ErrorUri);
}
// Note: tickets are returned even if they are considered invalid (e.g expired).
return AuthenticateResult.Success(new AuthenticationTicket(
notification.Principal,
OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
}
case OpenIddictServerEndpointType.Token when transaction.Request.IsRefreshTokenGrantType():
else
{
if (string.IsNullOrEmpty(transaction.Request.RefreshToken))
{
return AuthenticateResult.NoResult();
}
var notification = new DeserializeRefreshTokenContext(transaction)
{
Token = transaction.Request.RefreshToken
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The refresh token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating refresh tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
return AuthenticateResult.Fail("The refresh token is not valid.");
}
// Note: tickets are returned even if they are considered invalid (e.g expired).
return AuthenticateResult.Success(new AuthenticationTicket(
notification.Principal,
OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
builder.Append("An unknown error occurred while authenticating the current request.");
}
case OpenIddictServerEndpointType.Userinfo:
return AuthenticateResult.Fail(new Exception(builder.ToString())
{
if (string.IsNullOrEmpty(transaction.Request.AccessToken))
// Note: the error details are stored as additional exception properties,
// which is similar to what other ASP.NET Core security handlers do.
Data =
{
return AuthenticateResult.NoResult();
[Parameters.Error] = context.Error,
[Parameters.ErrorDescription] = context.ErrorDescription,
[Parameters.ErrorUri] = context.ErrorUri
}
var notification = new DeserializeAccessTokenContext(transaction)
{
Token = transaction.Request.AccessToken
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The access token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating access tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
return AuthenticateResult.Fail("The access token is not valid.");
}
var date = notification.Principal.GetExpirationDate();
if (date.HasValue && date.Value < DateTimeOffset.UtcNow)
{
return AuthenticateResult.Fail("The access token is no longer valid.");
}
return AuthenticateResult.Success(new AuthenticationTicket(
notification.Principal,
OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
}
default: throw new InvalidOperationException("An identity cannot be extracted from this request.");
});
}
return AuthenticateResult.Success(new AuthenticationTicket(
context.Principal,
OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
}
protected override async Task HandleChallengeAsync([CanBeNull] AuthenticationProperties properties)
@ -275,7 +175,7 @@ namespace OpenIddict.Server.AspNetCore
throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint.");
}
var context = new ProcessChallengeResponseContext(transaction)
var context = new ProcessChallengeContext(transaction)
{
Response = new OpenIddictResponse
{
@ -338,7 +238,7 @@ namespace OpenIddict.Server.AspNetCore
throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint.");
}
var context = new ProcessSigninResponseContext(transaction)
var context = new ProcessSigninContext(transaction)
{
Principal = user,
Response = new OpenIddictResponse()
@ -386,7 +286,7 @@ namespace OpenIddict.Server.AspNetCore
throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint.");
}
var context = new ProcessSignoutResponseContext(transaction)
var context = new ProcessSignoutContext(transaction)
{
Response = new OpenIddictResponse()
};

172
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs

@ -112,160 +112,32 @@ namespace OpenIddict.Server.Owin
throw new InvalidOperationException("An identity cannot be extracted from this request.");
}
switch (transaction.EndpointType)
{
case OpenIddictServerEndpointType.Authorization:
case OpenIddictServerEndpointType.Logout:
{
if (string.IsNullOrEmpty(transaction.Request.IdTokenHint))
{
return null;
}
var notification = new DeserializeIdentityTokenContext(transaction)
{
Token = transaction.Request.IdTokenHint
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The identity token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating identity tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
_logger.LogWarning("The identity token extracted from the 'id_token_hint' " +
"parameter was invalid or malformed and was ignored.");
return null;
}
// Tickets are returned even if they are considered invalid (e.g expired).
return new AuthenticationTicket((ClaimsIdentity) notification.Principal.Identity, new AuthenticationProperties());
}
case OpenIddictServerEndpointType.Token when transaction.Request.IsAuthorizationCodeGrantType():
{
// Note: this method can be called from the ApplyTokenResponse event,
// which may be invoked for a missing authorization code/refresh token.
if (string.IsNullOrEmpty(transaction.Request.Code))
{
return null;
}
var notification = new DeserializeAuthorizationCodeContext(transaction)
{
Token = transaction.Request.Code
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The authorization code was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating authorization codes ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
_logger.LogWarning("The authorization code extracted from the token request was invalid and was ignored.");
return null;
}
// Tickets are returned even if they are considered invalid (e.g expired).
return new AuthenticationTicket((ClaimsIdentity) notification.Principal.Identity, new AuthenticationProperties());
}
case OpenIddictServerEndpointType.Token when transaction.Request.IsRefreshTokenGrantType():
{
if (string.IsNullOrEmpty(transaction.Request.RefreshToken))
{
return null;
}
var notification = new DeserializeRefreshTokenContext(transaction)
{
Token = transaction.Request.RefreshToken
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The refresh token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating refresh tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
_logger.LogWarning("The refresh token extracted from the token request was invalid and was ignored.");
return null;
}
var context = new ProcessAuthenticationContext(transaction);
await _provider.DispatchAsync(context);
// Tickets are returned even if they are considered invalid (e.g expired).
if (context.Principal == null || context.IsRequestHandled || context.IsRequestSkipped)
{
return null;
}
return new AuthenticationTicket((ClaimsIdentity) notification.Principal.Identity, new AuthenticationProperties());
}
else if (context.IsRejected)
{
_logger.LogError("An error occurred while authenticating the current request: {Error} ; {Description}",
/* Error: */ context.Error ?? Errors.InvalidToken,
/* Description: */ context.ErrorDescription);
case OpenIddictServerEndpointType.Userinfo:
return new AuthenticationTicket(identity: null, new AuthenticationProperties
{
if (string.IsNullOrEmpty(transaction.Request.AccessToken))
Dictionary =
{
return null;
[Parameters.Error] = context.Error,
[Parameters.ErrorDescription] = context.ErrorDescription,
[Parameters.ErrorUri] = context.ErrorUri
}
var notification = new DeserializeAccessTokenContext(transaction)
{
Token = transaction.Request.AccessToken
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The access token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating access tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
_logger.LogWarning("The access token extracted from the userinfo request was invalid and was ignored.");
return null;
}
var date = notification.Principal.GetExpirationDate();
if (date.HasValue && date.Value < DateTimeOffset.UtcNow)
{
_logger.LogError("The access token extracted from the userinfo request was expired.");
return null;
}
return new AuthenticationTicket((ClaimsIdentity) notification.Principal.Identity, new AuthenticationProperties());
}
default: throw new InvalidOperationException("An identity cannot be extracted from this request.");
});
}
return new AuthenticationTicket((ClaimsIdentity) context.Principal.Identity, new AuthenticationProperties());
}
protected override async Task TeardownCoreAsync()
@ -291,7 +163,7 @@ namespace OpenIddict.Server.Owin
throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint.");
}
var context = new ProcessChallengeResponseContext(transaction)
var context = new ProcessChallengeContext(transaction)
{
Response = new OpenIddictResponse
{
@ -347,7 +219,7 @@ namespace OpenIddict.Server.Owin
throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint.");
}
var context = new ProcessSigninResponseContext(transaction)
var context = new ProcessSigninContext(transaction)
{
Principal = signin.Principal,
Response = new OpenIddictResponse()
@ -396,7 +268,7 @@ namespace OpenIddict.Server.Owin
throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint.");
}
var context = new ProcessSignoutResponseContext(transaction)
var context = new ProcessSignoutContext(transaction)
{
Response = new OpenIddictResponse()
};

2
src/OpenIddict.Server/OpenIddictServerConstants.cs

@ -10,7 +10,7 @@ namespace OpenIddict.Server
{
public static class Properties
{
public const string Principal = ".principal";
public const string AmbientPrincipal = ".ambient_principal";
public const string ValidatedPostLogoutRedirectUri = ".validated_post_logout_redirect_uri";
public const string ValidatedRedirectUri = ".validated_redirect_uri";
}

37
src/OpenIddict.Server/OpenIddictServerEvents.cs

@ -285,15 +285,34 @@ namespace OpenIddict.Server
}
}
/// <summary>
/// Represents an event called when processing an authentication operation.
/// </summary>
public class ProcessAuthenticationContext : BaseValidatingContext
{
/// <summary>
/// Creates a new instance of the <see cref="ProcessAuthenticationContext"/> class.
/// </summary>
public ProcessAuthenticationContext([NotNull] OpenIddictServerTransaction transaction)
: base(transaction)
{
}
/// <summary>
/// Gets or sets the security principal.
/// </summary>
public ClaimsPrincipal Principal { get; set; }
}
/// <summary>
/// Represents an event called when processing a challenge response.
/// </summary>
public class ProcessChallengeResponseContext : BaseValidatingContext
public class ProcessChallengeContext : BaseValidatingContext
{
/// <summary>
/// Creates a new instance of the <see cref="ProcessChallengeResponseContext"/> class.
/// Creates a new instance of the <see cref="ProcessChallengeContext"/> class.
/// </summary>
public ProcessChallengeResponseContext([NotNull] OpenIddictServerTransaction transaction)
public ProcessChallengeContext([NotNull] OpenIddictServerTransaction transaction)
: base(transaction)
{
}
@ -302,12 +321,12 @@ namespace OpenIddict.Server
/// <summary>
/// Represents an event called when processing a sign-in response.
/// </summary>
public class ProcessSigninResponseContext : BaseValidatingTicketContext
public class ProcessSigninContext : BaseValidatingTicketContext
{
/// <summary>
/// Creates a new instance of the <see cref="ProcessSigninResponseContext"/> class.
/// Creates a new instance of the <see cref="ProcessSigninContext"/> class.
/// </summary>
public ProcessSigninResponseContext([NotNull] OpenIddictServerTransaction transaction)
public ProcessSigninContext([NotNull] OpenIddictServerTransaction transaction)
: base(transaction)
{
}
@ -348,12 +367,12 @@ namespace OpenIddict.Server
/// <summary>
/// Represents an event called when processing a sign-out response.
/// </summary>
public class ProcessSignoutResponseContext : BaseValidatingContext
public class ProcessSignoutContext : BaseValidatingContext
{
/// <summary>
/// Creates a new instance of the <see cref="ProcessSignoutResponseContext"/> class.
/// Creates a new instance of the <see cref="ProcessSignoutContext"/> class.
/// </summary>
public ProcessSignoutResponseContext([NotNull] OpenIddictServerTransaction transaction)
public ProcessSignoutContext([NotNull] OpenIddictServerTransaction transaction)
: base(transaction)
{
}

16
src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs

@ -18,9 +18,9 @@ namespace OpenIddict.Server
/// <summary>
/// Represents a filter that excludes the associated handlers if no access token is returned.
/// </summary>
public class RequireAccessTokenIncluded : IOpenIddictServerHandlerFilter<ProcessSigninResponseContext>
public class RequireAccessTokenIncluded : IOpenIddictServerHandlerFilter<ProcessSigninContext>
{
public ValueTask<bool> IsActiveAsync([NotNull] ProcessSigninResponseContext context)
public ValueTask<bool> IsActiveAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -34,9 +34,9 @@ namespace OpenIddict.Server
/// <summary>
/// Represents a filter that excludes the associated handlers if no authorization code is returned.
/// </summary>
public class RequireAuthorizationCodeIncluded : IOpenIddictServerHandlerFilter<ProcessSigninResponseContext>
public class RequireAuthorizationCodeIncluded : IOpenIddictServerHandlerFilter<ProcessSigninContext>
{
public ValueTask<bool> IsActiveAsync([NotNull] ProcessSigninResponseContext context)
public ValueTask<bool> IsActiveAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -114,9 +114,9 @@ namespace OpenIddict.Server
/// <summary>
/// Represents a filter that excludes the associated handlers if no identity token is returned.
/// </summary>
public class RequireIdentityTokenIncluded : IOpenIddictServerHandlerFilter<ProcessSigninResponseContext>
public class RequireIdentityTokenIncluded : IOpenIddictServerHandlerFilter<ProcessSigninContext>
{
public ValueTask<bool> IsActiveAsync([NotNull] ProcessSigninResponseContext context)
public ValueTask<bool> IsActiveAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -146,9 +146,9 @@ namespace OpenIddict.Server
/// <summary>
/// Represents a filter that excludes the associated handlers if no refresh token is returned.
/// </summary>
public class RequireRefreshTokenIncluded : IOpenIddictServerHandlerFilter<ProcessSigninResponseContext>
public class RequireRefreshTokenIncluded : IOpenIddictServerHandlerFilter<ProcessSigninContext>
{
public ValueTask<bool> IsActiveAsync([NotNull] ProcessSigninResponseContext context)
public ValueTask<bool> IsActiveAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{

136
src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs

@ -29,10 +29,10 @@ namespace OpenIddict.Server
ExtractAuthorizationRequest.Descriptor,
ValidateAuthorizationRequest.Descriptor,
HandleAuthorizationRequest.Descriptor,
ApplyAuthorizationResponse<ProcessChallengeResponseContext>.Descriptor,
ApplyAuthorizationResponse<ProcessChallengeContext>.Descriptor,
ApplyAuthorizationResponse<ProcessErrorResponseContext>.Descriptor,
ApplyAuthorizationResponse<ProcessRequestContext>.Descriptor,
ApplyAuthorizationResponse<ProcessSigninResponseContext>.Descriptor,
ApplyAuthorizationResponse<ProcessSigninContext>.Descriptor,
/*
* Authorization request validation:
@ -46,6 +46,7 @@ namespace OpenIddict.Server
ValidateNonceParameter.Descriptor,
ValidatePromptParameter.Descriptor,
ValidateCodeChallengeParameters.Descriptor,
ValidateIdTokenHint.Descriptor,
ValidateClientId.Descriptor,
ValidateClientType.Descriptor,
ValidateClientRedirectUri.Descriptor,
@ -274,7 +275,7 @@ namespace OpenIddict.Server
if (notification.Principal != null)
{
var @event = new ProcessSigninResponseContext(context.Transaction)
var @event = new ProcessSigninContext(context.Transaction)
{
Principal = notification.Principal,
Response = new OpenIddictResponse()
@ -971,32 +972,21 @@ namespace OpenIddict.Server
}
/// <summary>
/// Contains the logic responsible of rejecting authorization requests that use unregistered scopes.
/// Note: this handler is not used when the degraded mode is enabled or when scope validation is disabled.
/// Contains the logic responsible of rejecting authorization requests that don't specify a valid id_token_hint.
/// </summary>
public class ValidateScopes : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
public class ValidateIdTokenHint : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictScopeManager _scopeManager;
public ValidateScopes() => throw new InvalidOperationException(new StringBuilder()
.AppendLine("The core services must be registered when enabling the OpenIddict server feature.")
.Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ")
.AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.")
.Append("Alternatively, you can disable the built-in database-based server features by enabling ")
.Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.")
.ToString());
private readonly IOpenIddictServerProvider _provider;
public ValidateScopes([NotNull] IOpenIddictScopeManager scopeManager)
=> _scopeManager = scopeManager;
public ValidateIdTokenHint([NotNull] IOpenIddictServerProvider provider)
=> _provider = provider;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireScopeValidationEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateScopes>()
.UseScopedHandler<ValidateIdTokenHint>()
.SetOrder(ValidateCodeChallengeParameters.Descriptor.Order + 1_000)
.Build();
@ -1014,28 +1004,31 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
// If all the specified scopes are registered in the options, avoid making a database lookup.
var scopes = context.Request.GetScopes().Except(context.Options.Scopes);
if (scopes.Count != 0)
if (string.IsNullOrEmpty(context.Request.IdTokenHint))
{
await foreach (var scope in _scopeManager.FindByNamesAsync(scopes.ToImmutableArray()))
{
scopes = scopes.Remove(await _scopeManager.GetNameAsync(scope));
}
return;
}
// If at least one scope was not recognized, return an error.
if (scopes.Count != 0)
var notification = new DeserializeIdentityTokenContext(context.Transaction)
{
context.Logger.LogError("The authentication request was rejected because " +
"invalid scopes were specified: {Scopes}.", scopes);
Token = context.Request.IdTokenHint
};
await _provider.DispatchAsync(notification);
if (notification.Principal == null)
{
context.Reject(
error: Errors.InvalidScope,
description: "The specified 'scope' parameter is not valid.");
error: Errors.InvalidRequest,
description: "The specified 'id_token_hint' parameter is invalid or malformed.");
return;
}
// Note: the expiration date associated with an identity token used as an id_token_hint is deliberately ignored.
// Store the security principal extracted from the identity token as an environment property.
context.Transaction.Properties[Properties.AmbientPrincipal] = notification.Principal;
}
}
@ -1065,7 +1058,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateClientId>()
.SetOrder(ValidateScopes.Descriptor.Order + 1_000)
.SetOrder(ValidateIdTokenHint.Descriptor.Order + 1_000)
.Build();
/// <summary>
@ -1229,6 +1222,75 @@ namespace OpenIddict.Server
}
}
/// <summary>
/// Contains the logic responsible of rejecting authorization requests that use unregistered scopes.
/// Note: this handler is not used when the degraded mode is enabled or when scope validation is disabled.
/// </summary>
public class ValidateScopes : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictScopeManager _scopeManager;
public ValidateScopes() => throw new InvalidOperationException(new StringBuilder()
.AppendLine("The core services must be registered when enabling the OpenIddict server feature.")
.Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ")
.AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.")
.Append("Alternatively, you can disable the built-in database-based server features by enabling ")
.Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.")
.ToString());
public ValidateScopes([NotNull] IOpenIddictScopeManager scopeManager)
=> _scopeManager = scopeManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireScopeValidationEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateScopes>()
.SetOrder(ValidateClientRedirectUri.Descriptor.Order + 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ValidateAuthorizationRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// If all the specified scopes are registered in the options, avoid making a database lookup.
var scopes = context.Request.GetScopes().Except(context.Options.Scopes);
if (scopes.Count != 0)
{
await foreach (var scope in _scopeManager.FindByNamesAsync(scopes.ToImmutableArray()))
{
scopes = scopes.Remove(await _scopeManager.GetNameAsync(scope));
}
}
// If at least one scope was not recognized, return an error.
if (scopes.Count != 0)
{
context.Logger.LogError("The authentication request was rejected because " +
"invalid scopes were specified: {Scopes}.", scopes);
context.Reject(
error: Errors.InvalidScope,
description: "The specified 'scope' parameter is not valid.");
return;
}
}
}
/// <summary>
/// Contains the logic responsible of rejecting authorization requests made by unauthorized applications.
/// Note: this handler is not used when the degraded mode is enabled or when endpoint permissions are disabled.
@ -1256,7 +1318,7 @@ namespace OpenIddict.Server
.AddFilter<RequireEndpointPermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateEndpointPermissions>()
.SetOrder(ValidateClientRedirectUri.Descriptor.Order + 1_000)
.SetOrder(ValidateScopes.Descriptor.Order + 1_000)
.Build();
/// <summary>
@ -1515,9 +1577,9 @@ namespace OpenIddict.Server
// Note: at this stage, the validated redirect URI property may be null (e.g if an error
// is returned from the ExtractAuthorizationRequest/ValidateAuthorizationRequest events).
if (context.Transaction.Properties.TryGetValue(Properties.ValidatedRedirectUri, out var property))
if (context.Transaction.Properties.TryGetValue(Properties.ValidatedRedirectUri, out var address))
{
context.RedirectUri = (string) property;
context.RedirectUri = (string) address;
}
return default;

28
src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs

@ -33,10 +33,10 @@ namespace OpenIddict.Server
ExtractTokenRequest.Descriptor,
ValidateTokenRequest.Descriptor,
HandleTokenRequest.Descriptor,
ApplyTokenResponse<ProcessChallengeResponseContext>.Descriptor,
ApplyTokenResponse<ProcessChallengeContext>.Descriptor,
ApplyTokenResponse<ProcessErrorResponseContext>.Descriptor,
ApplyTokenResponse<ProcessRequestContext>.Descriptor,
ApplyTokenResponse<ProcessSigninResponseContext>.Descriptor,
ApplyTokenResponse<ProcessSigninContext>.Descriptor,
/*
* Token request validation:
@ -204,7 +204,7 @@ namespace OpenIddict.Server
}
// Store the security principal extracted from the authorization code/refresh token as an environment property.
context.Transaction.Properties[Properties.Principal] = notification.Principal;
context.Transaction.Properties[Properties.AmbientPrincipal] = notification.Principal;
context.Logger.LogInformation("The token request was successfully validated.");
}
@ -274,7 +274,7 @@ namespace OpenIddict.Server
if (notification.Principal != null)
{
var @event = new ProcessSigninResponseContext(context.Transaction)
var @event = new ProcessSigninContext(context.Transaction)
{
Principal = notification.Principal,
Response = new OpenIddictResponse()
@ -1233,15 +1233,6 @@ namespace OpenIddict.Server
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The authorization code was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating authorization codes ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
context.Logger.LogError("The token request was rejected because the authorization code was invalid.");
@ -1315,15 +1306,6 @@ namespace OpenIddict.Server
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The refresh token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating refresh tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
context.Logger.LogError("The token request was rejected because the refresh token was invalid.");
@ -1739,7 +1721,7 @@ namespace OpenIddict.Server
return default;
}
if (context.Transaction.Properties.TryGetValue(Properties.Principal, out var principal))
if (context.Transaction.Properties.TryGetValue(Properties.AmbientPrincipal, out var principal))
{
context.Principal ??= (ClaimsPrincipal) principal;
}

44
src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs

@ -199,7 +199,7 @@ namespace OpenIddict.Server
}
// Store the security principal extracted from the introspected token as an environment property.
context.Transaction.Properties[Properties.Principal] = notification.Principal;
context.Transaction.Properties[Properties.AmbientPrincipal] = notification.Principal;
context.Logger.LogInformation("The introspection request was successfully validated.");
}
@ -767,16 +767,6 @@ namespace OpenIddict.Server
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The access token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating access tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
return notification.Principal;
}
@ -788,16 +778,6 @@ namespace OpenIddict.Server
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The authorization code was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating authorization codes ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
return notification.Principal;
}
@ -809,16 +789,6 @@ namespace OpenIddict.Server
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The identity token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating identity token ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
return notification.Principal;
}
@ -830,16 +800,6 @@ namespace OpenIddict.Server
};
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The refresh token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating refresh tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
return notification.Principal;
}
}
@ -987,7 +947,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (context.Transaction.Properties.TryGetValue(Properties.Principal, out var principal))
if (context.Transaction.Properties.TryGetValue(Properties.AmbientPrincipal, out var principal))
{
context.Principal ??= (ClaimsPrincipal) principal;
}

74
src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs

@ -31,12 +31,13 @@ namespace OpenIddict.Server
HandleLogoutRequest.Descriptor,
ApplyLogoutResponse<ProcessErrorResponseContext>.Descriptor,
ApplyLogoutResponse<ProcessRequestContext>.Descriptor,
ApplyLogoutResponse<ProcessSignoutResponseContext>.Descriptor,
ApplyLogoutResponse<ProcessSignoutContext>.Descriptor,
/*
* Logout request validation:
*/
ValidatePostLogoutRedirectUriParameter.Descriptor,
ValidateIdTokenHint.Descriptor,
ValidateClientPostLogoutRedirectUri.Descriptor,
/*
@ -256,7 +257,7 @@ namespace OpenIddict.Server
if (notification.IsLogoutAllowed)
{
var @event = new ProcessSignoutResponseContext(context.Transaction)
var @event = new ProcessSignoutContext(context.Transaction)
{
Response = new OpenIddictResponse()
};
@ -402,6 +403,67 @@ namespace OpenIddict.Server
}
}
/// <summary>
/// Contains the logic responsible of rejecting logout requests that don't specify a valid id_token_hint.
/// </summary>
public class ValidateIdTokenHint : IOpenIddictServerHandler<ValidateLogoutRequestContext>
{
private readonly IOpenIddictServerProvider _provider;
public ValidateIdTokenHint([NotNull] IOpenIddictServerProvider provider)
=> _provider = provider;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateLogoutRequestContext>()
.UseScopedHandler<ValidateIdTokenHint>()
.SetOrder(ValidatePostLogoutRedirectUriParameter.Descriptor.Order + 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ValidateLogoutRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (string.IsNullOrEmpty(context.Request.IdTokenHint))
{
return;
}
var notification = new DeserializeIdentityTokenContext(context.Transaction)
{
Token = context.Request.IdTokenHint
};
await _provider.DispatchAsync(notification);
if (notification.Principal == null)
{
context.Reject(
error: Errors.InvalidRequest,
description: "The specified 'id_token_hint' parameter is invalid or malformed.");
return;
}
// Note: the expiration date associated with an identity token used as an id_token_hint is deliberately ignored.
// Store the security principal extracted from the identity token as an environment property.
context.Transaction.Properties[Properties.AmbientPrincipal] = notification.Principal;
}
}
/// <summary>
/// Contains the logic responsible of rejecting logout requests that use an invalid redirect_uri.
/// Note: this handler is not used when the degraded mode is enabled.
@ -521,11 +583,11 @@ namespace OpenIddict.Server
return default;
}
// Note: at this stage, the validated redirect URI property may be null (e.g if an error
// is returned from the ExtractLogoutRequest/ValidateLogoutRequest events).
if (context.Transaction.Properties.TryGetValue(Properties.ValidatedPostLogoutRedirectUri, out var property))
// Note: at this stage, the validated redirect URI property may be null (e.g if
// an error is returned from the ExtractLogoutRequest/ValidateLogoutRequest events).
if (context.Transaction.Properties.TryGetValue(Properties.ValidatedPostLogoutRedirectUri, out var address))
{
context.PostLogoutRedirectUri = (string) property;
context.PostLogoutRedirectUri = (string) address;
}
return default;

15
src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs

@ -31,7 +31,7 @@ namespace OpenIddict.Server
ExtractUserinfoRequest.Descriptor,
ValidateUserinfoRequest.Descriptor,
HandleUserinfoRequest.Descriptor,
ApplyUserinfoResponse<ProcessChallengeResponseContext>.Descriptor,
ApplyUserinfoResponse<ProcessChallengeContext>.Descriptor,
ApplyUserinfoResponse<ProcessErrorResponseContext>.Descriptor,
ApplyUserinfoResponse<ProcessRequestContext>.Descriptor,
@ -187,7 +187,7 @@ namespace OpenIddict.Server
}
// Store the security principal extracted from the authorization code/refresh token as an environment property.
context.Transaction.Properties[Properties.Principal] = notification.Principal;
context.Transaction.Properties[Properties.AmbientPrincipal] = notification.Principal;
context.Logger.LogInformation("The userinfo request was successfully validated.");
}
@ -432,15 +432,6 @@ namespace OpenIddict.Server
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The access token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of validating access tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
if (notification.Principal == null)
{
context.Logger.LogError("The userinfo request was rejected because the access token was invalid.");
@ -498,7 +489,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (context.Transaction.Properties.TryGetValue(Properties.Principal, out var principal))
if (context.Transaction.Properties.TryGetValue(Properties.AmbientPrincipal, out var principal))
{
context.Principal ??= (ClaimsPrincipal) principal;
}

154
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -8,6 +8,7 @@ using System;
using System.Collections.Immutable;
using System.ComponentModel;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
@ -18,6 +19,7 @@ using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants;
using static OpenIddict.Server.OpenIddictServerEvents;
using static OpenIddict.Server.OpenIddictServerHandlerFilters;
using Properties = OpenIddict.Server.OpenIddictServerConstants.Properties;
namespace OpenIddict.Server
{
@ -26,12 +28,17 @@ namespace OpenIddict.Server
{
public static ImmutableArray<OpenIddictServerHandlerDescriptor> DefaultHandlers { get; } = ImmutableArray.Create(
/*
* Challenge response processing:
* Authentication processing:
*/
AttachAmbientPrincipal.Descriptor,
/*
* Challenge processing:
*/
AttachDefaultChallengeError.Descriptor,
/*
* Sign-in response processing:
* Sign-in processing:
*/
ValidateSigninResponse.Descriptor,
AttachDefaultScopes.Descriptor,
@ -50,16 +57,65 @@ namespace OpenIddict.Server
.AddRange(Session.DefaultHandlers)
.AddRange(Userinfo.DefaultHandlers);
/// <summary>
/// Contains the logic responsible of attaching the ambient principal resolved for the current request.
/// </summary>
public class AttachAmbientPrincipal : IOpenIddictServerHandler<ProcessAuthenticationContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessAuthenticationContext>()
.UseSingletonHandler<AttachAmbientPrincipal>()
.SetOrder(int.MinValue + 100_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
switch (context.EndpointType)
{
case OpenIddictServerEndpointType.Authorization:
case OpenIddictServerEndpointType.Logout:
case OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType():
case OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType():
case OpenIddictServerEndpointType.Userinfo:
{
if (context.Transaction.Properties.TryGetValue(Properties.AmbientPrincipal, out var principal))
{
context.Principal = (ClaimsPrincipal) principal;
}
return default;
}
default: throw new InvalidOperationException("An identity cannot be extracted from this request.");
}
}
}
/// <summary>
/// Contains the logic responsible of ensuring that the challenge response contains an appropriate error.
/// </summary>
public class AttachDefaultChallengeError : IOpenIddictServerHandler<ProcessChallengeResponseContext>
public class AttachDefaultChallengeError : IOpenIddictServerHandler<ProcessChallengeContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessChallengeResponseContext>()
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessChallengeContext>()
.UseSingletonHandler<AttachDefaultChallengeError>()
.SetOrder(int.MinValue + 100_000)
.Build();
@ -71,7 +127,7 @@ namespace OpenIddict.Server
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessChallengeResponseContext context)
public ValueTask HandleAsync([NotNull] ProcessChallengeContext context)
{
if (context == null)
{
@ -110,13 +166,13 @@ namespace OpenIddict.Server
/// Contains the logic responsible of ensuring that the sign-in response
/// is compatible with the type of the endpoint that handled the request.
/// </summary>
public class ValidateSigninResponse : IOpenIddictServerHandler<ProcessSigninResponseContext>
public class ValidateSigninResponse : IOpenIddictServerHandler<ProcessSigninContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninResponseContext>()
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.UseSingletonHandler<ValidateSigninResponse>()
.SetOrder(int.MinValue + 100_000)
.Build();
@ -128,7 +184,7 @@ namespace OpenIddict.Server
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessSigninResponseContext context)
public ValueTask HandleAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -167,13 +223,13 @@ namespace OpenIddict.Server
/// <summary>
/// Contains the logic responsible of attaching default scopes to the authentication principal.
/// </summary>
public class AttachDefaultScopes : IOpenIddictServerHandler<ProcessSigninResponseContext>
public class AttachDefaultScopes : IOpenIddictServerHandler<ProcessSigninContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninResponseContext>()
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.UseSingletonHandler<AttachDefaultScopes>()
.SetOrder(ValidateSigninResponse.Descriptor.Order + 1_000)
.Build();
@ -185,7 +241,7 @@ namespace OpenIddict.Server
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessSigninResponseContext context)
public ValueTask HandleAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -207,13 +263,13 @@ namespace OpenIddict.Server
/// <summary>
/// Contains the logic responsible of attaching default presenters to the authentication principal.
/// </summary>
public class AttachDefaultPresenters : IOpenIddictServerHandler<ProcessSigninResponseContext>
public class AttachDefaultPresenters : IOpenIddictServerHandler<ProcessSigninContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninResponseContext>()
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.UseSingletonHandler<AttachDefaultPresenters>()
.SetOrder(AttachDefaultScopes.Descriptor.Order + 1_000)
.Build();
@ -225,7 +281,7 @@ namespace OpenIddict.Server
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessSigninResponseContext context)
public ValueTask HandleAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -246,13 +302,13 @@ namespace OpenIddict.Server
/// <summary>
/// Contains the logic responsible of selecting the token types returned to the client application.
/// </summary>
public class EvaluateReturnedTokens : IOpenIddictServerHandler<ProcessSigninResponseContext>
public class EvaluateReturnedTokens : IOpenIddictServerHandler<ProcessSigninContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninResponseContext>()
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.UseSingletonHandler<EvaluateReturnedTokens>()
.SetOrder(AttachDefaultPresenters.Descriptor.Order + 1_000)
.Build();
@ -264,7 +320,7 @@ namespace OpenIddict.Server
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessSigninResponseContext context)
public ValueTask HandleAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -332,7 +388,7 @@ namespace OpenIddict.Server
/// <summary>
/// Contains the logic responsible of generating and attaching an access token.
/// </summary>
public class AttachAccessToken : IOpenIddictServerHandler<ProcessSigninResponseContext>
public class AttachAccessToken : IOpenIddictServerHandler<ProcessSigninContext>
{
private readonly IOpenIddictServerProvider _provider;
@ -343,7 +399,7 @@ namespace OpenIddict.Server
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninResponseContext>()
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.AddFilter<RequireAccessTokenIncluded>()
.UseScopedHandler<AttachAccessToken>()
.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 1_000)
@ -356,7 +412,7 @@ namespace OpenIddict.Server
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ProcessSigninResponseContext context)
public async ValueTask HandleAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -402,7 +458,7 @@ namespace OpenIddict.Server
// Remove the destinations from the claim properties.
foreach (var claim in principal.Claims)
{
claim.Properties.Remove(Properties.Destinations);
claim.Properties.Remove(OpenIddictConstants.Properties.Destinations);
}
// When receiving a grant_type=refresh_token request, determine whether the client application
@ -427,15 +483,6 @@ namespace OpenIddict.Server
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The access token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of generating access tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
context.Response.TokenType = TokenTypes.Bearer;
context.Response.AccessToken = notification.Token;
@ -458,7 +505,7 @@ namespace OpenIddict.Server
/// <summary>
/// Contains the logic responsible of generating and attaching an authorization code.
/// </summary>
public class AttachAuthorizationCode : IOpenIddictServerHandler<ProcessSigninResponseContext>
public class AttachAuthorizationCode : IOpenIddictServerHandler<ProcessSigninContext>
{
private readonly IOpenIddictServerProvider _provider;
@ -469,7 +516,7 @@ namespace OpenIddict.Server
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninResponseContext>()
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.AddFilter<RequireAuthorizationCodeIncluded>()
.UseScopedHandler<AttachAuthorizationCode>()
.SetOrder(AttachAccessToken.Descriptor.Order + 1_000)
@ -482,7 +529,7 @@ namespace OpenIddict.Server
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ProcessSigninResponseContext context)
public async ValueTask HandleAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -532,15 +579,6 @@ namespace OpenIddict.Server
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The authorization code was not correctly processed. This may indicate ")
.Append("that the event handler responsible of generating authorization codes ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
context.Response.Code = notification.Token;
}
}
@ -548,7 +586,7 @@ namespace OpenIddict.Server
/// <summary>
/// Contains the logic responsible of generating and attaching a refresh token.
/// </summary>
public class AttachRefreshToken : IOpenIddictServerHandler<ProcessSigninResponseContext>
public class AttachRefreshToken : IOpenIddictServerHandler<ProcessSigninContext>
{
private readonly IOpenIddictServerProvider _provider;
@ -559,7 +597,7 @@ namespace OpenIddict.Server
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninResponseContext>()
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.AddFilter<RequireRefreshTokenIncluded>()
.UseScopedHandler<AttachRefreshToken>()
.SetOrder(AttachAuthorizationCode.Descriptor.Order + 1_000)
@ -572,7 +610,7 @@ namespace OpenIddict.Server
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ProcessSigninResponseContext context)
public async ValueTask HandleAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -596,15 +634,6 @@ namespace OpenIddict.Server
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The refresh token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of generating refresh tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
context.Response.RefreshToken = notification.Token;
}
}
@ -612,7 +641,7 @@ namespace OpenIddict.Server
/// <summary>
/// Contains the logic responsible of generating and attaching an identity token.
/// </summary>
public class AttachIdentityToken : IOpenIddictServerHandler<ProcessSigninResponseContext>
public class AttachIdentityToken : IOpenIddictServerHandler<ProcessSigninContext>
{
private readonly IOpenIddictServerProvider _provider;
@ -623,7 +652,7 @@ namespace OpenIddict.Server
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninResponseContext>()
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.AddFilter<RequireIdentityTokenIncluded>()
.UseScopedHandler<AttachIdentityToken>()
.SetOrder(AttachRefreshToken.Descriptor.Order + 1_000)
@ -636,7 +665,7 @@ namespace OpenIddict.Server
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ProcessSigninResponseContext context)
public async ValueTask HandleAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
@ -677,7 +706,7 @@ namespace OpenIddict.Server
// Remove the destinations from the claim properties.
foreach (var claim in principal.Claims)
{
claim.Properties.Remove(Properties.Destinations);
claim.Properties.Remove(OpenIddictConstants.Properties.Destinations);
}
var lifetime = context.Principal.GetIdentityTokenLifetime() ?? context.Options.IdentityTokenLifetime;
@ -750,15 +779,6 @@ namespace OpenIddict.Server
await _provider.DispatchAsync(notification);
if (!notification.IsHandled)
{
throw new InvalidOperationException(new StringBuilder()
.Append("The identity token was not correctly processed. This may indicate ")
.Append("that the event handler responsible of generating identity tokens ")
.Append("was not registered or was explicitly removed from the handlers list.")
.ToString());
}
context.Response.IdToken = notification.Token;
static HashAlgorithm GetHashAlgorithm(SigningCredentials credentials)

Loading…
Cancel
Save