41 changed files with 2857 additions and 309 deletions
@ -0,0 +1,131 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Collections.Immutable; |
|||
using System.Diagnostics; |
|||
using System.Net.Http.Headers; |
|||
using System.Text; |
|||
|
|||
namespace OpenIddict.Client.SystemNetHttp; |
|||
|
|||
public static partial class OpenIddictClientSystemNetHttpHandlers |
|||
{ |
|||
public static class Device |
|||
{ |
|||
public static ImmutableArray<OpenIddictClientHandlerDescriptor> DefaultHandlers { get; } = ImmutableArray.Create( |
|||
/* |
|||
* DeviceAuthorization request processing: |
|||
*/ |
|||
CreateHttpClient<PrepareDeviceAuthorizationRequestContext>.Descriptor, |
|||
PreparePostHttpRequest<PrepareDeviceAuthorizationRequestContext>.Descriptor, |
|||
AttachHttpVersion<PrepareDeviceAuthorizationRequestContext>.Descriptor, |
|||
AttachJsonAcceptHeaders<PrepareDeviceAuthorizationRequestContext>.Descriptor, |
|||
AttachUserAgentHeader<PrepareDeviceAuthorizationRequestContext>.Descriptor, |
|||
AttachFromHeader<PrepareDeviceAuthorizationRequestContext>.Descriptor, |
|||
AttachBasicAuthenticationCredentials.Descriptor, |
|||
AttachFormParameters<PrepareDeviceAuthorizationRequestContext>.Descriptor, |
|||
SendHttpRequest<ApplyDeviceAuthorizationRequestContext>.Descriptor, |
|||
DisposeHttpRequest<ApplyDeviceAuthorizationRequestContext>.Descriptor, |
|||
|
|||
/* |
|||
* DeviceAuthorization response processing: |
|||
*/ |
|||
DecompressResponseContent<ExtractDeviceAuthorizationResponseContext>.Descriptor, |
|||
ExtractJsonHttpResponse<ExtractDeviceAuthorizationResponseContext>.Descriptor, |
|||
ExtractWwwAuthenticateHeader<ExtractDeviceAuthorizationResponseContext>.Descriptor, |
|||
ValidateHttpResponse<ExtractDeviceAuthorizationResponseContext>.Descriptor, |
|||
DisposeHttpResponse<ExtractDeviceAuthorizationResponseContext>.Descriptor); |
|||
|
|||
/// <summary>
|
|||
/// Contains the logic responsible for attaching the client credentials to the HTTP Authorization header.
|
|||
/// </summary>
|
|||
public sealed class AttachBasicAuthenticationCredentials : IOpenIddictClientHandler<PrepareDeviceAuthorizationRequestContext> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the default descriptor definition assigned to this handler.
|
|||
/// </summary>
|
|||
public static OpenIddictClientHandlerDescriptor Descriptor { get; } |
|||
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareDeviceAuthorizationRequestContext>() |
|||
.AddFilter<RequireHttpMetadataUri>() |
|||
.UseSingletonHandler<AttachBasicAuthenticationCredentials>() |
|||
.SetOrder(AttachFormParameters<PrepareDeviceAuthorizationRequestContext>.Descriptor.Order - 500) |
|||
.SetType(OpenIddictClientHandlerType.BuiltIn) |
|||
.Build(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public ValueTask HandleAsync(PrepareDeviceAuthorizationRequestContext context) |
|||
{ |
|||
if (context is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(context)); |
|||
} |
|||
|
|||
Debug.Assert(context.Request is not null, SR.GetResourceString(SR.ID4008)); |
|||
|
|||
// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
|
|||
// this may indicate that the request was incorrectly processed by another client stack.
|
|||
var request = context.Transaction.GetHttpRequestMessage() ?? |
|||
throw new InvalidOperationException(SR.GetResourceString(SR.ID0173)); |
|||
|
|||
// The OAuth 2.0 specification recommends sending the client credentials using basic authentication.
|
|||
// However, this authentication method is known to have severe compatibility/interoperability issues:
|
|||
//
|
|||
// - While restricted to clients that have been given a secret (i.e confidential clients) by the
|
|||
// specification, basic authentication is also sometimes required by server implementations for
|
|||
// public clients that don't have a client secret: in this case, an empty password is used and
|
|||
// the client identifier is sent alone in the Authorization header (instead of being sent using
|
|||
// the standard "client_id" parameter present in the request body).
|
|||
//
|
|||
// - While the OAuth 2.0 specification requires that the client credentials be formURL-encoded
|
|||
// before being base64-encoded, many implementations are known to implement a non-standard
|
|||
// encoding scheme, where neither the client_id nor the client_secret are formURL-encoded.
|
|||
//
|
|||
// To guarantee that the OpenIddict implementation can be used with most servers implementions,
|
|||
// basic authentication is only used when a client secret is present and client_secret_post is
|
|||
// always preferred when it's explicitly listed as a supported client authentication method.
|
|||
// If client_secret_post is not listed or if the server returned an empty methods list,
|
|||
// client_secret_basic is always used, as it MUST be implemented by all OAuth 2.0 servers.
|
|||
//
|
|||
// See https://tools.ietf.org/html/rfc8414#section-2
|
|||
// and https://tools.ietf.org/html/rfc6749#section-2.3.1 for more information.
|
|||
if (request.Headers.Authorization is null && |
|||
!string.IsNullOrEmpty(context.Request.ClientId) && |
|||
!string.IsNullOrEmpty(context.Request.ClientSecret) && |
|||
UseBasicAuthentication(context.Configuration)) |
|||
{ |
|||
// Important: the credentials MUST be formURL-encoded before being base64-encoded.
|
|||
var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(new StringBuilder() |
|||
.Append(EscapeDataString(context.Request.ClientId)) |
|||
.Append(':') |
|||
.Append(EscapeDataString(context.Request.ClientSecret)) |
|||
.ToString())); |
|||
|
|||
// Attach the authorization header containing the client credentials to the HTTP request.
|
|||
request.Headers.Authorization = new AuthenticationHeaderValue(Schemes.Basic, credentials); |
|||
|
|||
// Remove the client credentials from the request payload to ensure they are not sent twice.
|
|||
context.Request.ClientId = context.Request.ClientSecret = null; |
|||
} |
|||
|
|||
return default; |
|||
|
|||
static bool UseBasicAuthentication(OpenIddictConfiguration configuration) |
|||
=> configuration.DeviceAuthorizationEndpointAuthMethodsSupported switch |
|||
{ |
|||
// If at least one authentication method was explicit added, only use basic authentication
|
|||
// if it's supported AND if client_secret_post is not supported or enabled by the server.
|
|||
{ Count: > 0 } methods => methods.Contains(ClientAuthenticationMethods.ClientSecretBasic) && |
|||
!methods.Contains(ClientAuthenticationMethods.ClientSecretPost), |
|||
|
|||
// Otherwise, if no authentication method was explicit added, assume only basic is supported.
|
|||
{ Count: _ } => true |
|||
}; |
|||
|
|||
static string EscapeDataString(string value) => Uri.EscapeDataString(value).Replace("%20", "+"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Collections.Immutable; |
|||
using static OpenIddict.Client.WebIntegration.OpenIddictClientWebIntegrationConstants; |
|||
|
|||
namespace OpenIddict.Client.WebIntegration; |
|||
|
|||
public static partial class OpenIddictClientWebIntegrationHandlers |
|||
{ |
|||
public static class Device |
|||
{ |
|||
public static ImmutableArray<OpenIddictClientHandlerDescriptor> DefaultHandlers { get; } = ImmutableArray.Create( |
|||
/* |
|||
* Token response extraction: |
|||
*/ |
|||
MapNonStandardResponseParameters.Descriptor); |
|||
|
|||
/// <summary>
|
|||
/// Contains the logic responsible for mapping non-standard response parameters
|
|||
/// to their standard equivalent for the providers that require it.
|
|||
/// </summary>
|
|||
public sealed class MapNonStandardResponseParameters : IOpenIddictClientHandler<ExtractDeviceAuthorizationResponseContext> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the default descriptor definition assigned to this handler.
|
|||
/// </summary>
|
|||
public static OpenIddictClientHandlerDescriptor Descriptor { get; } |
|||
= OpenIddictClientHandlerDescriptor.CreateBuilder<ExtractDeviceAuthorizationResponseContext>() |
|||
.UseSingletonHandler<MapNonStandardResponseParameters>() |
|||
.SetOrder(int.MaxValue - 50_000) |
|||
.SetType(OpenIddictClientHandlerType.BuiltIn) |
|||
.Build(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public ValueTask HandleAsync(ExtractDeviceAuthorizationResponseContext context) |
|||
{ |
|||
if (context is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(context)); |
|||
} |
|||
|
|||
if (context.Response is null) |
|||
{ |
|||
return default; |
|||
} |
|||
|
|||
// Note: Google doesn't return a standard "verification_uri" parameter
|
|||
// but returns a custom "verification_url" that serves the same purpose.
|
|||
if (context.Registration.ProviderName is Providers.Google) |
|||
{ |
|||
context.Response[Parameters.VerificationUri] = context.Response["verification_url"]; |
|||
context.Response["verification_url"] = null; |
|||
} |
|||
|
|||
return default; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,123 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
namespace OpenIddict.Client; |
|||
|
|||
public static partial class OpenIddictClientEvents |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an event called for each request to the device authorization endpoint
|
|||
/// to give the user code a chance to add parameters to the device authorization request.
|
|||
/// </summary>
|
|||
public sealed class PrepareDeviceAuthorizationRequestContext : BaseExternalContext |
|||
{ |
|||
/// <summary>
|
|||
/// Creates a new instance of the <see cref="PrepareDeviceAuthorizationRequestContext"/> class.
|
|||
/// </summary>
|
|||
public PrepareDeviceAuthorizationRequestContext(OpenIddictClientTransaction transaction) |
|||
: base(transaction) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the request.
|
|||
/// </summary>
|
|||
public OpenIddictRequest Request |
|||
{ |
|||
get => Transaction.Request!; |
|||
set => Transaction.Request = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an event called for each request to the device authorization endpoint
|
|||
/// to send the device authorization request to the remote authorization server.
|
|||
/// </summary>
|
|||
public sealed class ApplyDeviceAuthorizationRequestContext : BaseExternalContext |
|||
{ |
|||
/// <summary>
|
|||
/// Creates a new instance of the <see cref="ApplyDeviceAuthorizationRequestContext"/> class.
|
|||
/// </summary>
|
|||
public ApplyDeviceAuthorizationRequestContext(OpenIddictClientTransaction transaction) |
|||
: base(transaction) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the request.
|
|||
/// </summary>
|
|||
public OpenIddictRequest Request |
|||
{ |
|||
get => Transaction.Request!; |
|||
set => Transaction.Request = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an event called for each device authorization response
|
|||
/// to extract the response parameters from the server response.
|
|||
/// </summary>
|
|||
public sealed class ExtractDeviceAuthorizationResponseContext : BaseExternalContext |
|||
{ |
|||
/// <summary>
|
|||
/// Creates a new instance of the <see cref="ExtractDeviceAuthorizationResponseContext"/> class.
|
|||
/// </summary>
|
|||
public ExtractDeviceAuthorizationResponseContext(OpenIddictClientTransaction transaction) |
|||
: base(transaction) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the request.
|
|||
/// </summary>
|
|||
public OpenIddictRequest Request |
|||
{ |
|||
get => Transaction.Request!; |
|||
set => Transaction.Request = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the response, or <see langword="null"/> if it wasn't extracted yet.
|
|||
/// </summary>
|
|||
public OpenIddictResponse? Response |
|||
{ |
|||
get => Transaction.Response; |
|||
set => Transaction.Response = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Represents an event called for each device authorization response.
|
|||
/// </summary>
|
|||
public sealed class HandleDeviceAuthorizationResponseContext : BaseExternalContext |
|||
{ |
|||
/// <summary>
|
|||
/// Creates a new instance of the <see cref="HandleDeviceAuthorizationResponseContext"/> class.
|
|||
/// </summary>
|
|||
public HandleDeviceAuthorizationResponseContext(OpenIddictClientTransaction transaction) |
|||
: base(transaction) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the request.
|
|||
/// </summary>
|
|||
public OpenIddictRequest Request |
|||
{ |
|||
get => Transaction.Request!; |
|||
set => Transaction.Request = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the response.
|
|||
/// </summary>
|
|||
public OpenIddictResponse Response |
|||
{ |
|||
get => Transaction.Response!; |
|||
set => Transaction.Response = value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,246 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System.Collections.Immutable; |
|||
using System.Text.Json; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace OpenIddict.Client; |
|||
|
|||
public static partial class OpenIddictClientHandlers |
|||
{ |
|||
public static class Device |
|||
{ |
|||
public static ImmutableArray<OpenIddictClientHandlerDescriptor> DefaultHandlers { get; } = ImmutableArray.Create( |
|||
/* |
|||
* Device authorization response handling: |
|||
*/ |
|||
ValidateWellKnownParameters.Descriptor, |
|||
HandleErrorResponse.Descriptor, |
|||
ValidateVerificationEndpointUri.Descriptor); |
|||
|
|||
/// <summary>
|
|||
/// Contains the logic responsible for validating the well-known parameters contained in the device authorization response.
|
|||
/// </summary>
|
|||
public sealed class ValidateWellKnownParameters : IOpenIddictClientHandler<HandleDeviceAuthorizationResponseContext> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the default descriptor definition assigned to this handler.
|
|||
/// </summary>
|
|||
public static OpenIddictClientHandlerDescriptor Descriptor { get; } |
|||
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleDeviceAuthorizationResponseContext>() |
|||
.UseSingletonHandler<ValidateWellKnownParameters>() |
|||
.SetOrder(int.MinValue + 100_000) |
|||
.SetType(OpenIddictClientHandlerType.BuiltIn) |
|||
.Build(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public ValueTask HandleAsync(HandleDeviceAuthorizationResponseContext context) |
|||
{ |
|||
if (context is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(context)); |
|||
} |
|||
|
|||
foreach (var parameter in context.Response.GetParameters()) |
|||
{ |
|||
if (!ValidateParameterType(parameter.Key, parameter.Value)) |
|||
{ |
|||
context.Reject( |
|||
error: Errors.ServerError, |
|||
description: SR.FormatID2107(parameter.Key), |
|||
uri: SR.FormatID8000(SR.ID2107)); |
|||
|
|||
return default; |
|||
} |
|||
} |
|||
|
|||
return default; |
|||
|
|||
// Note: in the typical case, the response parameters should be deserialized from a
|
|||
// JSON response and thus natively stored as System.Text.Json.JsonElement instances.
|
|||
//
|
|||
// In the rare cases where the underlying value wouldn't be a JsonElement instance
|
|||
// (e.g when custom parameters are manually added to the response), the static
|
|||
// conversion operator would take care of converting the underlying value to a
|
|||
// JsonElement instance using the same value type as the original parameter value.
|
|||
static bool ValidateParameterType(string name, OpenIddictParameter value) => name switch |
|||
{ |
|||
// Error parameters MUST be formatted as unique strings:
|
|||
Parameters.Error or Parameters.ErrorDescription or Parameters.ErrorUri |
|||
=> ((JsonElement) value).ValueKind is JsonValueKind.String, |
|||
|
|||
// The following parameters MUST be formatted as unique strings:
|
|||
Parameters.DeviceCode or Parameters.UserCode or |
|||
Parameters.VerificationUri or Parameters.VerificationUriComplete |
|||
=> ((JsonElement) value).ValueKind is JsonValueKind.String, |
|||
|
|||
// The following parameters MUST be formatted as numeric dates:
|
|||
Parameters.ExpiresIn => (JsonElement) value is { ValueKind: JsonValueKind.Number } element && |
|||
element.TryGetDecimal(out decimal result) && result is >= 0, |
|||
|
|||
// The following parameters MUST be formatted as positive integers:
|
|||
Parameters.Interval => (JsonElement) value is { ValueKind: JsonValueKind.Number } element && |
|||
element.TryGetDecimal(out decimal result) && result is >= 0, |
|||
|
|||
// Parameters that are not in the well-known list can be of any type.
|
|||
_ => true |
|||
}; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Contains the logic responsible for surfacing potential errors from the device authorization response.
|
|||
/// </summary>
|
|||
public sealed class HandleErrorResponse : IOpenIddictClientHandler<HandleDeviceAuthorizationResponseContext> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the default descriptor definition assigned to this handler.
|
|||
/// </summary>
|
|||
public static OpenIddictClientHandlerDescriptor Descriptor { get; } |
|||
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleDeviceAuthorizationResponseContext>() |
|||
.UseSingletonHandler<HandleErrorResponse>() |
|||
.SetOrder(ValidateWellKnownParameters.Descriptor.Order + 1_000) |
|||
.SetType(OpenIddictClientHandlerType.BuiltIn) |
|||
.Build(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public ValueTask HandleAsync(HandleDeviceAuthorizationResponseContext context) |
|||
{ |
|||
if (context is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(context)); |
|||
} |
|||
|
|||
// For more information, see https://www.rfc-editor.org/rfc/rfc8628#section-3.2.
|
|||
if (!string.IsNullOrEmpty(context.Response.Error)) |
|||
{ |
|||
context.Logger.LogInformation(SR.GetResourceString(SR.ID6216), context.Response); |
|||
|
|||
context.Reject( |
|||
error: context.Response.Error switch |
|||
{ |
|||
Errors.InvalidClient => Errors.InvalidRequest, |
|||
Errors.InvalidScope => Errors.InvalidScope, |
|||
Errors.InvalidRequest => Errors.InvalidRequest, |
|||
Errors.UnauthorizedClient => Errors.UnauthorizedClient, |
|||
_ => Errors.ServerError |
|||
}, |
|||
description: SR.GetResourceString(SR.ID2167), |
|||
uri: SR.FormatID8000(SR.ID2167)); |
|||
|
|||
return default; |
|||
} |
|||
|
|||
return default; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Contains the logic responsible for validating the verification
|
|||
/// endpoint URI contained in the device authorization response.
|
|||
/// </summary>
|
|||
public sealed class ValidateVerificationEndpointUri : IOpenIddictClientHandler<HandleDeviceAuthorizationResponseContext> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the default descriptor definition assigned to this handler.
|
|||
/// </summary>
|
|||
public static OpenIddictClientHandlerDescriptor Descriptor { get; } |
|||
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleDeviceAuthorizationResponseContext>() |
|||
.UseSingletonHandler<ValidateVerificationEndpointUri>() |
|||
.SetOrder(HandleErrorResponse.Descriptor.Order + 1_000) |
|||
.SetType(OpenIddictClientHandlerType.BuiltIn) |
|||
.Build(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public ValueTask HandleAsync(HandleDeviceAuthorizationResponseContext context) |
|||
{ |
|||
if (context is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(context)); |
|||
} |
|||
|
|||
// Return an error if the mandatory "verification_uri" parameter is missing.
|
|||
// For more information, see https://www.rfc-editor.org/rfc/rfc8628#section-3.2.
|
|||
if (string.IsNullOrEmpty(context.Response.VerificationUri)) |
|||
{ |
|||
context.Reject( |
|||
error: Errors.ServerError, |
|||
description: SR.FormatID2168(Parameters.VerificationUri), |
|||
uri: SR.FormatID8000(SR.ID2168)); |
|||
|
|||
return default; |
|||
} |
|||
|
|||
// Return an error if the "verification_uri" parameter is malformed.
|
|||
if (!Uri.IsWellFormedUriString(context.Response.VerificationUri, UriKind.Absolute)) |
|||
{ |
|||
context.Reject( |
|||
error: Errors.ServerError, |
|||
description: SR.FormatID2169(Parameters.VerificationUri), |
|||
uri: SR.FormatID8000(SR.ID2169)); |
|||
|
|||
return default; |
|||
} |
|||
|
|||
// Note: the "verification_uri_complete" parameter is optional and MUST not
|
|||
// cause an error if it's missing from the device authorization response.
|
|||
if (!string.IsNullOrEmpty(context.Response.VerificationUriComplete) && |
|||
!Uri.IsWellFormedUriString(context.Response.VerificationUriComplete, UriKind.Absolute)) |
|||
{ |
|||
context.Reject( |
|||
error: Errors.ServerError, |
|||
description: SR.FormatID2169(Parameters.VerificationUriComplete), |
|||
uri: SR.FormatID8000(SR.ID2169)); |
|||
|
|||
return default; |
|||
} |
|||
|
|||
return default; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Contains the logic responsible for validating the "expires_in"
|
|||
/// parameter contained in the device authorization response.
|
|||
/// </summary>
|
|||
public sealed class ValidateExpiration : IOpenIddictClientHandler<HandleDeviceAuthorizationResponseContext> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the default descriptor definition assigned to this handler.
|
|||
/// </summary>
|
|||
public static OpenIddictClientHandlerDescriptor Descriptor { get; } |
|||
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleDeviceAuthorizationResponseContext>() |
|||
.UseSingletonHandler<ValidateExpiration>() |
|||
.SetOrder(ValidateVerificationEndpointUri.Descriptor.Order + 1_000) |
|||
.SetType(OpenIddictClientHandlerType.BuiltIn) |
|||
.Build(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public ValueTask HandleAsync(HandleDeviceAuthorizationResponseContext context) |
|||
{ |
|||
if (context is null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(context)); |
|||
} |
|||
|
|||
// Return an error if the mandatory "expires_in" parameter is missing.
|
|||
// For more information, see https://www.rfc-editor.org/rfc/rfc8628#section-3.2.
|
|||
if (context.Response.ExpiresIn is null) |
|||
{ |
|||
context.Reject( |
|||
error: Errors.ServerError, |
|||
description: SR.FormatID2168(Parameters.ExpiresIn), |
|||
uri: SR.FormatID8000(SR.ID2168)); |
|||
|
|||
return default; |
|||
} |
|||
|
|||
return default; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
Loading…
Reference in new issue