Browse Source

Introduce new properties in ProcessSignInContext to allow for more control over the token creation process

pull/1099/head
Kévin Chalet 6 years ago
parent
commit
254be824c9
  1. 4
      src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx
  2. 4
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs
  3. 10
      src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs
  4. 2
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs
  5. 112
      src/OpenIddict.Server/OpenIddictServerEvents.cs
  6. 12
      src/OpenIddict.Server/OpenIddictServerExtensions.cs
  7. 36
      src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs
  8. 5
      src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
  9. 5
      src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs
  10. 5
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  11. 364
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  12. 70
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs

4
src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx

@ -1776,10 +1776,6 @@ To register the OpenIddict core services, reference the 'OpenIddict.Core' packag
<value>The token shouldn't be null or empty at this point.</value>
<comment>{Locked}</comment>
</data>
<data name="ID4011" xml:space="preserve">
<value>The OpenIddict Core services should be registered.</value>
<comment>{Locked}</comment>
</data>
<data name="ID6000" xml:space="preserve">
<value>An error occurred while validating the token '{Token}'.</value>
<comment>{Locked}</comment>

4
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs

@ -244,13 +244,13 @@ namespace OpenIddict.Server.AspNetCore
encryptingCredentials: context.Options.EncryptionCredentials.First(),
additionalHeaderClaims: new Dictionary<string, object>
{
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.AuthorizationRequest
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.LogoutRequest
});
// Note: the cache key is always prefixed with a specific marker
// to avoid collisions with the other types of cached payloads.
await _cache.SetStringAsync(Cache.LogoutRequest + context.Request.RequestId,
token, _options.CurrentValue.AuthorizationEndpointCachingPolicy);
token, _options.CurrentValue.LogoutEndpointCachingPolicy);
// Create a new GET logout request containing only the request_id parameter.
var address = QueryHelpers.AddQueryString(

10
src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs

@ -177,7 +177,7 @@ namespace OpenIddict.Server.DataProtection
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireAccessTokenIncluded>()
.AddFilter<RequireAccessTokenGenerated>()
.AddFilter<RequireDataProtectionAccessTokenFormatEnabled>()
.UseSingletonHandler<GenerateDataProtectionAccessToken>()
.SetOrder(GenerateIdentityModelAccessToken.Descriptor.Order - 500)
@ -240,7 +240,7 @@ namespace OpenIddict.Server.DataProtection
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireAuthorizationCodeIncluded>()
.AddFilter<RequireAuthorizationCodeGenerated>()
.AddFilter<RequireDataProtectionAuthorizationCodeFormatEnabled>()
.UseSingletonHandler<GenerateDataProtectionAuthorizationCode>()
.SetOrder(GenerateIdentityModelAuthorizationCode.Descriptor.Order - 500)
@ -303,7 +303,7 @@ namespace OpenIddict.Server.DataProtection
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDeviceCodeIncluded>()
.AddFilter<RequireDeviceCodeGenerated>()
.AddFilter<RequireDataProtectionDeviceCodeFormatEnabled>()
.UseSingletonHandler<GenerateDataProtectionDeviceCode>()
.SetOrder(GenerateIdentityModelDeviceCode.Descriptor.Order - 500)
@ -366,7 +366,7 @@ namespace OpenIddict.Server.DataProtection
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireRefreshTokenIncluded>()
.AddFilter<RequireRefreshTokenGenerated>()
.AddFilter<RequireDataProtectionRefreshTokenFormatEnabled>()
.UseSingletonHandler<GenerateDataProtectionRefreshToken>()
.SetOrder(GenerateIdentityModelRefreshToken.Descriptor.Order - 500)
@ -429,7 +429,7 @@ namespace OpenIddict.Server.DataProtection
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireUserCodeIncluded>()
.AddFilter<RequireUserCodeGenerated>()
.AddFilter<RequireDataProtectionUserCodeFormatEnabled>()
.UseSingletonHandler<GenerateDataProtectionUserCode>()
.SetOrder(GenerateIdentityModelUserCode.Descriptor.Order - 500)

2
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs

@ -244,7 +244,7 @@ namespace OpenIddict.Server.Owin
// Note: the cache key is always prefixed with a specific marker
// to avoid collisions with the other types of cached payloads.
await _cache.SetStringAsync(Cache.LogoutRequest + context.Request.RequestId,
token, _options.CurrentValue.AuthorizationEndpointCachingPolicy);
token, _options.CurrentValue.LogoutEndpointCachingPolicy);
// Create a new GET logout request containing only the request_id parameter.
var address = WebUtilities.AddQueryString(

112
src/OpenIddict.Server/OpenIddictServerEvents.cs

@ -387,82 +387,172 @@ namespace OpenIddict.Server
/// <summary>
/// Gets or sets a boolean indicating whether an access token
/// should be returned to the client application.
/// should be generated (and optionally returned to the client).
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeAccessToken { get; set; }
public bool GenerateAccessToken { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether an authorization code
/// should be returned to the client application.
/// should be generated (and optionally returned to the client).
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeAuthorizationCode { get; set; }
public bool GenerateAuthorizationCode { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether a device code
/// should be returned to the client application.
/// should be generated (and optionally returned to the client).
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeDeviceCode { get; set; }
public bool GenerateDeviceCode { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether an identity token
/// should be returned to the client application.
/// should be generated (and optionally returned to the client).
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeIdentityToken { get; set; }
public bool GenerateIdentityToken { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether a refresh token
/// should be returned to the client application.
/// should be generated (and optionally returned to the client).
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeRefreshToken { get; set; }
public bool GenerateRefreshToken { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether a user code
/// should be returned to the client application.
/// should be generated (and optionally returned to the client).
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool GenerateUserCode { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the generated access token
/// should be returned to the client application as part of the response.
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeAccessToken { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the generated authorization code
/// should be returned to the client application as part of the response.
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeAuthorizationCode { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the generated device code
/// should be returned to the client application as part of the response.
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeDeviceCode { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the generated identity token
/// should be returned to the client application as part of the response.
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeIdentityToken { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the generated refresh token
/// should be returned to the client application as part of the response.
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeRefreshToken { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether the generated user code
/// should be returned to the client application as part of the response.
/// Note: overriding the value of this property is generally not
/// recommended, except when dealing with non-standard clients.
/// </summary>
public bool IncludeUserCode { get; set; }
/// <summary>
/// Gets or sets the generated access token, if applicable.
/// The access token will only be returned if
/// <see cref="IncludeAccessToken"/> is set to <c>true</c>.
/// </summary>
public string? AccessToken { get; set; }
/// <summary>
/// Gets or sets the principal containing the claims that
/// will be used to create the access token, if applicable.
/// </summary>
public ClaimsPrincipal? AccessTokenPrincipal { get; set; }
/// <summary>
/// Gets or sets the generated authorization code, if applicable.
/// The authorization code will only be returned if
/// <see cref="IncludeAuthorizationCode"/> is set to <c>true</c>.
/// </summary>
public string? AuthorizationCode { get; set; }
/// <summary>
/// Gets or sets the principal containing the claims that
/// will be used to create the authorization code, if applicable.
/// </summary>
public ClaimsPrincipal? AuthorizationCodePrincipal { get; set; }
/// <summary>
/// Gets or sets the generated device code, if applicable.
/// The device code will only be returned if
/// <see cref="IncludeDeviceCode"/> is set to <c>true</c>.
/// </summary>
public string? DeviceCode { get; set; }
/// <summary>
/// Gets or sets the principal containing the claims that
/// will be used to create the device code, if applicable.
/// </summary>
public ClaimsPrincipal? DeviceCodePrincipal { get; set; }
/// <summary>
/// Gets or sets the generated identity token, if applicable.
/// The identity token will only be returned if
/// <see cref="IncludeIdentityToken"/> is set to <c>true</c>.
/// </summary>
public string? IdentityToken { get; set; }
/// <summary>
/// Gets or sets the principal containing the claims that
/// will be used to create the identity token, if applicable.
/// </summary>
public ClaimsPrincipal? IdentityTokenPrincipal { get; set; }
/// <summary>
/// Gets or sets the generated refresh token, if applicable.
/// The refresh token will only be returned if
/// <see cref="IncludeRefreshToken"/> is set to <c>true</c>.
/// </summary>
public string? RefreshToken { get; set; }
/// <summary>
/// Gets or sets the principal containing the claims that
/// will be used to create the refresh token, if applicable.
/// </summary>
public ClaimsPrincipal? RefreshTokenPrincipal { get; set; }
/// <summary>
/// Gets or sets the generated user code, if applicable.
/// The user code will only be returned if
/// <see cref="IncludeUserCode"/> is set to <c>true</c>.
/// </summary>
public string? UserCode { get; set; }
/// <summary>
/// Gets or sets the principal containing the claims that
/// will be used to create the user code, if applicable.

12
src/OpenIddict.Server/OpenIddictServerExtensions.cs

@ -48,25 +48,25 @@ namespace Microsoft.Extensions.DependencyInjection
builder.Services.TryAdd(DefaultHandlers.Select(descriptor => descriptor.ServiceDescriptor));
// Register the built-in filters used by the default OpenIddict server event handlers.
builder.Services.TryAddSingleton<RequireAccessTokenIncluded>();
builder.Services.TryAddSingleton<RequireAuthorizationCodeIncluded>();
builder.Services.TryAddSingleton<RequireAccessTokenGenerated>();
builder.Services.TryAddSingleton<RequireAuthorizationCodeGenerated>();
builder.Services.TryAddSingleton<RequireAuthorizationStorageEnabled>();
builder.Services.TryAddSingleton<RequireAuthorizationRequest>();
builder.Services.TryAddSingleton<RequireClientIdParameter>();
builder.Services.TryAddSingleton<RequireConfigurationRequest>();
builder.Services.TryAddSingleton<RequireCryptographyRequest>();
builder.Services.TryAddSingleton<RequireDegradedModeDisabled>();
builder.Services.TryAddSingleton<RequireDeviceCodeIncluded>();
builder.Services.TryAddSingleton<RequireDeviceCodeGenerated>();
builder.Services.TryAddSingleton<RequireDeviceRequest>();
builder.Services.TryAddSingleton<RequireEndpointPermissionsEnabled>();
builder.Services.TryAddSingleton<RequireGrantTypePermissionsEnabled>();
builder.Services.TryAddSingleton<RequireIdentityTokenIncluded>();
builder.Services.TryAddSingleton<RequireIdentityTokenGenerated>();
builder.Services.TryAddSingleton<RequireIntrospectionRequest>();
builder.Services.TryAddSingleton<RequireLogoutRequest>();
builder.Services.TryAddSingleton<RequirePostLogoutRedirectUriParameter>();
builder.Services.TryAddSingleton<RequireReferenceAccessTokensEnabled>();
builder.Services.TryAddSingleton<RequireReferenceRefreshTokensEnabled>();
builder.Services.TryAddSingleton<RequireRefreshTokenIncluded>();
builder.Services.TryAddSingleton<RequireRefreshTokenGenerated>();
builder.Services.TryAddSingleton<RequireRevocationRequest>();
builder.Services.TryAddSingleton<RequireRollingTokensDisabled>();
builder.Services.TryAddSingleton<RequireRollingRefreshTokensEnabled>();
@ -75,7 +75,7 @@ namespace Microsoft.Extensions.DependencyInjection
builder.Services.TryAddSingleton<RequireScopeValidationEnabled>();
builder.Services.TryAddSingleton<RequireTokenStorageEnabled>();
builder.Services.TryAddSingleton<RequireTokenRequest>();
builder.Services.TryAddSingleton<RequireUserCodeIncluded>();
builder.Services.TryAddSingleton<RequireUserCodeGenerated>();
builder.Services.TryAddSingleton<RequireUserinfoRequest>();
builder.Services.TryAddSingleton<RequireVerificationRequest>();

36
src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs

@ -15,9 +15,9 @@ namespace OpenIddict.Server
public static class OpenIddictServerHandlerFilters
{
/// <summary>
/// Represents a filter that excludes the associated handlers if no access token is returned.
/// Represents a filter that excludes the associated handlers if no access token is generated.
/// </summary>
public class RequireAccessTokenIncluded : IOpenIddictServerHandlerFilter<ProcessSignInContext>
public class RequireAccessTokenGenerated : IOpenIddictServerHandlerFilter<ProcessSignInContext>
{
public ValueTask<bool> IsActiveAsync(ProcessSignInContext context)
{
@ -26,14 +26,14 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
return new ValueTask<bool>(context.IncludeAccessToken);
return new ValueTask<bool>(context.GenerateAccessToken);
}
}
/// <summary>
/// Represents a filter that excludes the associated handlers if no authorization code is returned.
/// Represents a filter that excludes the associated handlers if no authorization code is generated.
/// </summary>
public class RequireAuthorizationCodeIncluded : IOpenIddictServerHandlerFilter<ProcessSignInContext>
public class RequireAuthorizationCodeGenerated : IOpenIddictServerHandlerFilter<ProcessSignInContext>
{
public ValueTask<bool> IsActiveAsync(ProcessSignInContext context)
{
@ -42,7 +42,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
return new ValueTask<bool>(context.IncludeAuthorizationCode);
return new ValueTask<bool>(context.GenerateAuthorizationCode);
}
}
@ -143,9 +143,9 @@ namespace OpenIddict.Server
}
/// <summary>
/// Represents a filter that excludes the associated handlers if no device code is returned.
/// Represents a filter that excludes the associated handlers if no device code is generated.
/// </summary>
public class RequireDeviceCodeIncluded : IOpenIddictServerHandlerFilter<ProcessSignInContext>
public class RequireDeviceCodeGenerated : IOpenIddictServerHandlerFilter<ProcessSignInContext>
{
public ValueTask<bool> IsActiveAsync(ProcessSignInContext context)
{
@ -154,7 +154,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
return new ValueTask<bool>(context.IncludeDeviceCode);
return new ValueTask<bool>(context.GenerateDeviceCode);
}
}
@ -207,9 +207,9 @@ namespace OpenIddict.Server
}
/// <summary>
/// Represents a filter that excludes the associated handlers if no identity token is returned.
/// Represents a filter that excludes the associated handlers if no identity token is generated.
/// </summary>
public class RequireIdentityTokenIncluded : IOpenIddictServerHandlerFilter<ProcessSignInContext>
public class RequireIdentityTokenGenerated : IOpenIddictServerHandlerFilter<ProcessSignInContext>
{
public ValueTask<bool> IsActiveAsync(ProcessSignInContext context)
{
@ -218,7 +218,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
return new ValueTask<bool>(context.IncludeIdentityToken);
return new ValueTask<bool>(context.GenerateIdentityToken);
}
}
@ -303,9 +303,9 @@ namespace OpenIddict.Server
}
/// <summary>
/// Represents a filter that excludes the associated handlers if no refresh token is returned.
/// Represents a filter that excludes the associated handlers if no refresh token is generated.
/// </summary>
public class RequireRefreshTokenIncluded : IOpenIddictServerHandlerFilter<ProcessSignInContext>
public class RequireRefreshTokenGenerated : IOpenIddictServerHandlerFilter<ProcessSignInContext>
{
public ValueTask<bool> IsActiveAsync(ProcessSignInContext context)
{
@ -314,7 +314,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
return new ValueTask<bool>(context.IncludeRefreshToken);
return new ValueTask<bool>(context.GenerateRefreshToken);
}
}
@ -447,9 +447,9 @@ namespace OpenIddict.Server
}
/// <summary>
/// Represents a filter that excludes the associated handlers if no user code is returned.
/// Represents a filter that excludes the associated handlers if no user code is generated.
/// </summary>
public class RequireUserCodeIncluded : IOpenIddictServerHandlerFilter<ProcessSignInContext>
public class RequireUserCodeGenerated : IOpenIddictServerHandlerFilter<ProcessSignInContext>
{
public ValueTask<bool> IsActiveAsync(ProcessSignInContext context)
{
@ -458,7 +458,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
return new ValueTask<bool>(context.IncludeUserCode);
return new ValueTask<bool>(context.GenerateUserCode);
}
}

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

@ -1121,7 +1121,10 @@ namespace OpenIddict.Server
// even if the service was registered and resolved from the dependency injection container.
if (scopes.Count != 0 && !context.Options.EnableDegradedMode)
{
Debug.Assert(_scopeManager is not null, SR.GetResourceString(SR.ID4011));
if (_scopeManager is null)
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
}
await foreach (var scope in _scopeManager.FindByNamesAsync(scopes.ToImmutableArray()))
{

5
src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs

@ -405,7 +405,10 @@ namespace OpenIddict.Server
// even if the service was registered and resolved from the dependency injection container.
if (scopes.Count != 0 && !context.Options.EnableDegradedMode)
{
Debug.Assert(_scopeManager is not null, SR.GetResourceString(SR.ID4011));
if (_scopeManager is null)
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
}
await foreach (var scope in _scopeManager.FindByNamesAsync(scopes.ToImmutableArray()))
{

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

@ -686,7 +686,10 @@ namespace OpenIddict.Server
// even if the service was registered and resolved from the dependency injection container.
if (scopes.Count != 0 && !context.Options.EnableDegradedMode)
{
Debug.Assert(_scopeManager is not null, SR.GetResourceString(SR.ID4011));
if (_scopeManager is null)
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
}
await foreach (var scope in _scopeManager.FindByNamesAsync(scopes.ToImmutableArray()))
{

364
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -63,7 +63,7 @@ namespace OpenIddict.Server
AttachDefaultScopes.Descriptor,
AttachDefaultPresenters.Descriptor,
InferResources.Descriptor,
EvaluateReturnedTokens.Descriptor,
EvaluateTokenTypes.Descriptor,
AttachAuthorization.Descriptor,
PrepareAccessTokenPrincipal.Descriptor,
@ -104,8 +104,7 @@ namespace OpenIddict.Server
GenerateIdentityModelIdentityToken.Descriptor,
BeautifyUserCode.Descriptor,
AttachAccessTokenProperties.Descriptor,
AttachDeviceCodeProperties.Descriptor,
AttachTokenParameters.Descriptor,
/*
* Sign-out processing:
@ -1575,16 +1574,17 @@ namespace OpenIddict.Server
}
/// <summary>
/// Contains the logic responsible of selecting the token types returned to the client application.
/// Contains the logic responsible of selecting the token types that
/// should be generated and optionally returned in the response.
/// </summary>
public class EvaluateReturnedTokens : IOpenIddictServerHandler<ProcessSignInContext>
public class EvaluateTokenTypes : IOpenIddictServerHandler<ProcessSignInContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.UseSingletonHandler<EvaluateReturnedTokens>()
.UseSingletonHandler<EvaluateTokenTypes>()
.SetOrder(InferResources.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
.Build();
@ -1599,73 +1599,80 @@ namespace OpenIddict.Server
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
context.IncludeAccessToken = context.EndpointType switch
(context.GenerateAccessToken, context.IncludeAccessToken) = context.EndpointType switch
{
// For authorization requests, return an access token if a response type containing token was specified.
OpenIddictServerEndpointType.Authorization => context.Request.HasResponseType(ResponseTypes.Token),
// For authorization requests, generate and return an access token
// if a response type containing the "token" value was specified.
OpenIddictServerEndpointType.Authorization when context.Request.HasResponseType(ResponseTypes.Token)
=> (true, true),
// For token requests, always return an access token.
OpenIddictServerEndpointType.Token => true,
// For token requests, always generate and return an access token.
OpenIddictServerEndpointType.Token => (true, true),
_ => false
_ => (false, false)
};
context.IncludeAuthorizationCode = context.EndpointType switch
(context.GenerateAuthorizationCode, context.IncludeAuthorizationCode) = context.EndpointType switch
{
// For authorization requests, return an authorization code if a response type containing code was specified.
OpenIddictServerEndpointType.Authorization => context.Request.HasResponseType(ResponseTypes.Code),
// For authorization requests, generate and return an authorization code
// if a response type containing the "code" value was specified.
OpenIddictServerEndpointType.Authorization when context.Request.HasResponseType(ResponseTypes.Code)
=> (true, true),
_ => false
_ => (false, false)
};
context.IncludeDeviceCode = context.EndpointType switch
(context.GenerateDeviceCode, context.IncludeDeviceCode) = context.EndpointType switch
{
// For device requests, always return a device code.
OpenIddictServerEndpointType.Device => true,
// For device requests, always generate and return a device code.
OpenIddictServerEndpointType.Device => (true, true),
// Note: a device code is not directly returned by the verification endpoint (that generally
// returns an empty response or redirects the user agent to another page), but a device code
// must be generated to replace the payload of the device code initially returned to the client.
// In this case, the new device code is not returned as part of the response but persisted in the DB.
OpenIddictServerEndpointType.Verification => true,
// In this case, the device code is not returned as part of the response but persisted in the DB.
OpenIddictServerEndpointType.Verification => (true, false),
_ => false
_ => (false, false)
};
context.IncludeRefreshToken = context.EndpointType switch
(context.GenerateIdentityToken, context.IncludeIdentityToken) = context.EndpointType switch
{
// For token requests, never return a refresh token if the offline_access scope was not granted.
OpenIddictServerEndpointType.Token when !context.Principal.HasScope(Scopes.OfflineAccess) => false,
// For authorization requests, generate and return an identity token if a response type
// containing code was specified and if the openid scope was explicitly or implicitly granted.
OpenIddictServerEndpointType.Authorization when
context.Principal.HasScope(Scopes.OpenId) &&
context.Request.HasResponseType(ResponseTypes.IdToken) => (true, true),
// For grant_type=refresh_token token requests, only return a refresh token if rolling tokens are enabled.
OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType()
=> context.Options.UseRollingRefreshTokens,
// For token requests that don't meet the previous criteria, allow a refresh token to be returned.
OpenIddictServerEndpointType.Token => true,
// For token requests, only generate and return an identity token if the openid scope was granted.
OpenIddictServerEndpointType.Token when context.Principal.HasScope(Scopes.OpenId) => (true, true),
_ => false
_ => (false, false)
};
context.IncludeIdentityToken = context.EndpointType switch
(context.GenerateRefreshToken, context.IncludeRefreshToken) = context.EndpointType switch
{
// For authorization requests, return an identity token if a response type containing code
// was specified and if the openid scope was explicitly or implicitly granted.
OpenIddictServerEndpointType.Authorization => context.Principal.HasScope(Scopes.OpenId) &&
context.Request.HasResponseType(ResponseTypes.IdToken),
// For token requests, never generate a refresh token if the offline_access scope was not granted.
OpenIddictServerEndpointType.Token when !context.Principal.HasScope(Scopes.OfflineAccess)
=> (false, false),
// For token requests, only return an identity token if the openid scope was granted.
OpenIddictServerEndpointType.Token => context.Principal.HasScope(Scopes.OpenId),
// For grant_type=refresh_token token requests, only generate
// and return a refresh token if rolling tokens are enabled.
OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType() &&
context.Options.UseRollingRefreshTokens => (true, true),
_ => false
// For token requests that don't meet the previous criteria, allow a refresh token to be returned.
OpenIddictServerEndpointType.Token when !context.Request.IsRefreshTokenGrantType() => (true, true),
_ => (false, false)
};
context.IncludeUserCode = context.EndpointType switch
(context.GenerateUserCode, context.IncludeUserCode) = context.EndpointType switch
{
// Only return a user code if the request is a device authorization request.
OpenIddictServerEndpointType.Device => true,
// Only generate and return a user code if the request is a device authorization request.
OpenIddictServerEndpointType.Device => (true, true),
_ => false
_ => (false, false)
};
return default;
@ -1699,7 +1706,7 @@ namespace OpenIddict.Server
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireAuthorizationStorageEnabled>()
.UseScopedHandler<AttachAuthorization>()
.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 1_000)
.SetOrder(EvaluateTokenTypes.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
.Build();
@ -1714,7 +1721,7 @@ namespace OpenIddict.Server
Debug.Assert(context.Principal is not null, SR.GetResourceString(SR.ID4006));
// If no authorization code, device code or refresh token is returned, don't create an authorization.
if (!context.IncludeAuthorizationCode && !context.IncludeDeviceCode && !context.IncludeRefreshToken)
if (!context.GenerateAuthorizationCode && !context.GenerateDeviceCode && !context.GenerateRefreshToken)
{
return;
}
@ -1783,7 +1790,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireAccessTokenIncluded>()
.AddFilter<RequireAccessTokenGenerated>()
.UseSingletonHandler<PrepareAccessTokenPrincipal>()
.SetOrder(AttachAuthorization.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -1902,7 +1909,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireAuthorizationCodeIncluded>()
.AddFilter<RequireAuthorizationCodeGenerated>()
.UseSingletonHandler<PrepareAuthorizationCodePrincipal>()
.SetOrder(PrepareAccessTokenPrincipal.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -2006,7 +2013,7 @@ namespace OpenIddict.Server
// Note: a device code principal is produced when a device code is included in the response or when a
// device code entry is replaced when processing a sign-in response sent to the verification endpoint.
if (context.EndpointType != OpenIddictServerEndpointType.Verification && !context.IncludeDeviceCode)
if (context.EndpointType != OpenIddictServerEndpointType.Verification && !context.GenerateDeviceCode)
{
return default;
}
@ -2069,7 +2076,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireRefreshTokenIncluded>()
.AddFilter<RequireRefreshTokenGenerated>()
.UseSingletonHandler<PrepareRefreshTokenPrincipal>()
.SetOrder(PrepareDeviceCodePrincipal.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -2153,7 +2160,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireIdentityTokenIncluded>()
.AddFilter<RequireIdentityTokenGenerated>()
.UseSingletonHandler<PrepareIdentityTokenPrincipal>()
.SetOrder(PrepareRefreshTokenPrincipal.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -2267,7 +2274,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireUserCodeIncluded>()
.AddFilter<RequireUserCodeGenerated>()
.UseSingletonHandler<PrepareUserCodePrincipal>()
.SetOrder(PrepareIdentityTokenPrincipal.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -2582,7 +2589,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireAccessTokenIncluded>()
.AddFilter<RequireAccessTokenGenerated>()
.UseScopedHandler<CreateAccessTokenEntry>()
.SetOrder(ExtendRefreshTokenEntry.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -2650,7 +2657,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireAccessTokenIncluded>()
.AddFilter<RequireAccessTokenGenerated>()
.UseSingletonHandler<GenerateIdentityModelAccessToken>()
.SetOrder(CreateAccessTokenEntry.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -2665,7 +2672,7 @@ namespace OpenIddict.Server
}
// If an access token was already attached by another handler, don't overwrite it.
if (!string.IsNullOrEmpty(context.Response.AccessToken))
if (!string.IsNullOrEmpty(context.AccessToken))
{
return default;
}
@ -2739,9 +2746,10 @@ namespace OpenIddict.Server
additionalHeaderClaims: descriptor.AdditionalHeaderClaims);
}
context.Response.AccessToken = token;
context.AccessToken = token;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6013), principal.GetClaim(Claims.JwtId), token, principal.Claims);
context.Logger.LogTrace(SR.GetResourceString(SR.ID6013), principal.GetClaim(Claims.JwtId),
context.AccessToken, principal.Claims);
return default;
}
@ -2768,7 +2776,7 @@ namespace OpenIddict.Server
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireReferenceAccessTokensEnabled>()
.AddFilter<RequireAccessTokenIncluded>()
.AddFilter<RequireAccessTokenGenerated>()
.UseScopedHandler<ConvertReferenceAccessToken>()
.SetOrder(GenerateIdentityModelAccessToken.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -2782,7 +2790,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (string.IsNullOrEmpty(context.Response.AccessToken))
if (string.IsNullOrEmpty(context.AccessToken))
{
return;
}
@ -2818,13 +2826,13 @@ namespace OpenIddict.Server
// Attach the generated token to the token entry, persist the change
// and replace the returned token by the reference identifier.
descriptor.Payload = context.Response.AccessToken;
descriptor.Payload = context.AccessToken;
descriptor.Principal = principal;
descriptor.ReferenceId = Base64UrlEncoder.Encode(data);
await _tokenManager.UpdateAsync(token, descriptor);
context.Response.AccessToken = descriptor.ReferenceId;
context.AccessToken = descriptor.ReferenceId;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6014), identifier, descriptor.ReferenceId);
}
@ -2856,7 +2864,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireAuthorizationCodeIncluded>()
.AddFilter<RequireAuthorizationCodeGenerated>()
.UseScopedHandler<CreateAuthorizationCodeEntry>()
.SetOrder(ConvertReferenceAccessToken.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -2924,7 +2932,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireAuthorizationCodeIncluded>()
.AddFilter<RequireAuthorizationCodeGenerated>()
.UseSingletonHandler<GenerateIdentityModelAuthorizationCode>()
.SetOrder(CreateAuthorizationCodeEntry.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -2939,7 +2947,7 @@ namespace OpenIddict.Server
}
// If an authorization code was already attached by another handler, don't overwrite it.
if (!string.IsNullOrEmpty(context.Response.Code))
if (!string.IsNullOrEmpty(context.AuthorizationCode))
{
return default;
}
@ -2994,9 +3002,10 @@ namespace OpenIddict.Server
encryptingCredentials: context.Options.EncryptionCredentials.First(),
additionalHeaderClaims: descriptor.AdditionalHeaderClaims);
context.Response.Code = token;
context.AuthorizationCode = token;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6016), principal.GetClaim(Claims.JwtId), token, principal.Claims);
context.Logger.LogTrace(SR.GetResourceString(SR.ID6016), principal.GetClaim(Claims.JwtId),
context.AuthorizationCode, principal.Claims);
return default;
}
@ -3022,7 +3031,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireAuthorizationCodeIncluded>()
.AddFilter<RequireAuthorizationCodeGenerated>()
.UseScopedHandler<ConvertReferenceAuthorizationCode>()
.SetOrder(GenerateIdentityModelAuthorizationCode.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3036,7 +3045,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (string.IsNullOrEmpty(context.Response.Code))
if (string.IsNullOrEmpty(context.AuthorizationCode))
{
return;
}
@ -3072,13 +3081,13 @@ namespace OpenIddict.Server
// Attach the generated token to the token entry, persist the change
// and replace the returned token by the reference identifier.
descriptor.Payload = context.Response.Code;
descriptor.Payload = context.AuthorizationCode;
descriptor.Principal = principal;
descriptor.ReferenceId = Base64UrlEncoder.Encode(data);
await _tokenManager.UpdateAsync(token, descriptor);
context.Response.Code = descriptor.ReferenceId;
context.AuthorizationCode = descriptor.ReferenceId;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6017), identifier, descriptor.ReferenceId);
}
@ -3110,7 +3119,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireDeviceCodeIncluded>()
.AddFilter<RequireDeviceCodeGenerated>()
.UseScopedHandler<CreateDeviceCodeEntry>()
.SetOrder(ConvertReferenceAuthorizationCode.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3183,7 +3192,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDeviceCodeIncluded>()
.AddFilter<RequireDeviceCodeGenerated>()
.UseSingletonHandler<GenerateIdentityModelDeviceCode>()
.SetOrder(CreateDeviceCodeEntry.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3198,7 +3207,7 @@ namespace OpenIddict.Server
}
// If a device code was already attached by another handler, don't overwrite it.
if (!string.IsNullOrEmpty(context.Response.DeviceCode))
if (!string.IsNullOrEmpty(context.DeviceCode))
{
return default;
}
@ -3253,9 +3262,10 @@ namespace OpenIddict.Server
encryptingCredentials: context.Options.EncryptionCredentials.First(),
additionalHeaderClaims: descriptor.AdditionalHeaderClaims);
context.Response.DeviceCode = token;
context.DeviceCode = token;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6019), principal.GetClaim(Claims.JwtId), token, principal.Claims);
context.Logger.LogTrace(SR.GetResourceString(SR.ID6019), principal.GetClaim(Claims.JwtId),
context.DeviceCode, principal.Claims);
return default;
}
@ -3282,7 +3292,7 @@ namespace OpenIddict.Server
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
// Note: device codes are always reference tokens.
.AddFilter<RequireDeviceCodeIncluded>()
.AddFilter<RequireDeviceCodeGenerated>()
.UseScopedHandler<ConvertReferenceDeviceCode>()
.SetOrder(GenerateIdentityModelDeviceCode.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3296,7 +3306,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (string.IsNullOrEmpty(context.Response.DeviceCode))
if (string.IsNullOrEmpty(context.DeviceCode))
{
return;
}
@ -3337,13 +3347,13 @@ namespace OpenIddict.Server
// Attach the generated token to the token entry, persist the change
// and replace the returned token by the reference identifier.
descriptor.Payload = context.Response.DeviceCode;
descriptor.Payload = context.DeviceCode;
descriptor.Principal = principal;
descriptor.ReferenceId = Base64UrlEncoder.Encode(data);
await _tokenManager.UpdateAsync(token, descriptor);
context.Response.DeviceCode = descriptor.ReferenceId;
context.DeviceCode = descriptor.ReferenceId;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6020), identifier, descriptor.ReferenceId);
}
@ -3369,7 +3379,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireDeviceCodeIncluded>()
.AddFilter<RequireDeviceCodeGenerated>()
.UseScopedHandler<UpdateReferenceDeviceCodeEntry>()
.SetOrder(ConvertReferenceDeviceCode.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3383,7 +3393,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (string.IsNullOrEmpty(context.Response.DeviceCode))
if (string.IsNullOrEmpty(context.DeviceCode))
{
return;
}
@ -3421,16 +3431,13 @@ namespace OpenIddict.Server
// Note: the lifetime is deliberately extended to give more time to the client to redeem the code.
descriptor.ExpirationDate = principal.GetExpirationDate();
descriptor.Payload = context.Response.DeviceCode;
descriptor.Payload = context.DeviceCode;
descriptor.Principal = principal;
descriptor.Status = Statuses.Valid;
descriptor.Subject = principal.GetClaim(Claims.Subject);
await _tokenManager.UpdateAsync(token, descriptor);
// Don't return the prepared device code directly from the verification endpoint.
context.Response.DeviceCode = null;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6021), await _tokenManager.GetIdAsync(token));
}
}
@ -3461,7 +3468,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireRefreshTokenIncluded>()
.AddFilter<RequireRefreshTokenGenerated>()
.UseScopedHandler<CreateRefreshTokenEntry>()
.SetOrder(UpdateReferenceDeviceCodeEntry.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3529,7 +3536,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireRefreshTokenIncluded>()
.AddFilter<RequireRefreshTokenGenerated>()
.UseSingletonHandler<GenerateIdentityModelRefreshToken>()
.SetOrder(CreateRefreshTokenEntry.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3544,7 +3551,7 @@ namespace OpenIddict.Server
}
// If a refresh token was already attached by another handler, don't overwrite it.
if (!string.IsNullOrEmpty(context.Response.RefreshToken))
if (!string.IsNullOrEmpty(context.RefreshToken))
{
return default;
}
@ -3594,14 +3601,14 @@ namespace OpenIddict.Server
// Sign and encrypt the refresh token.
var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor);
token = context.Options.JsonWebTokenHandler.EncryptToken(token,
encryptingCredentials: context.Options.EncryptionCredentials.First(),
additionalHeaderClaims: descriptor.AdditionalHeaderClaims);
context.Response.RefreshToken = token;
context.RefreshToken = token;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6023), principal.GetClaim(Claims.JwtId), token, principal.Claims);
context.Logger.LogTrace(SR.GetResourceString(SR.ID6023), principal.GetClaim(Claims.JwtId),
context.RefreshToken, principal.Claims);
return default;
}
@ -3628,7 +3635,7 @@ namespace OpenIddict.Server
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireReferenceRefreshTokensEnabled>()
.AddFilter<RequireRefreshTokenIncluded>()
.AddFilter<RequireRefreshTokenGenerated>()
.UseScopedHandler<ConvertReferenceRefreshToken>()
.SetOrder(GenerateIdentityModelRefreshToken.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3642,7 +3649,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (string.IsNullOrEmpty(context.Response.RefreshToken))
if (string.IsNullOrEmpty(context.RefreshToken))
{
return;
}
@ -3678,13 +3685,13 @@ namespace OpenIddict.Server
// Attach the generated token to the token entry, persist the change
// and replace the returned token by the reference identifier.
descriptor.Payload = context.Response.RefreshToken;
descriptor.Payload = context.RefreshToken;
descriptor.Principal = principal;
descriptor.ReferenceId = Base64UrlEncoder.Encode(data);
await _tokenManager.UpdateAsync(token, descriptor);
context.Response.RefreshToken = descriptor.ReferenceId;
context.RefreshToken = descriptor.ReferenceId;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6024), identifier, descriptor.ReferenceId);
}
@ -3700,8 +3707,8 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDeviceCodeIncluded>()
.AddFilter<RequireUserCodeIncluded>()
.AddFilter<RequireDeviceCodeGenerated>()
.AddFilter<RequireUserCodeGenerated>()
.UseSingletonHandler<AttachDeviceCodeIdentifier>()
.SetOrder(ConvertReferenceRefreshToken.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3757,7 +3764,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireUserCodeIncluded>()
.AddFilter<RequireUserCodeGenerated>()
.UseScopedHandler<CreateUserCodeEntry>()
.SetOrder(AttachDeviceCodeIdentifier.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3825,7 +3832,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireUserCodeIncluded>()
.AddFilter<RequireUserCodeGenerated>()
.UseSingletonHandler<GenerateIdentityModelUserCode>()
.SetOrder(CreateUserCodeEntry.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3840,7 +3847,7 @@ namespace OpenIddict.Server
}
// If a user code was already attached by another handler, don't overwrite it.
if (!string.IsNullOrEmpty(context.Response.UserCode))
if (!string.IsNullOrEmpty(context.UserCode))
{
return default;
}
@ -3885,9 +3892,10 @@ namespace OpenIddict.Server
encryptingCredentials: context.Options.EncryptionCredentials.First(),
additionalHeaderClaims: descriptor.AdditionalHeaderClaims);
context.Response.UserCode = token;
context.UserCode = token;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6026), principal.GetClaim(Claims.JwtId), token, principal.Claims);
context.Logger.LogTrace(SR.GetResourceString(SR.ID6026), principal.GetClaim(Claims.JwtId),
context.UserCode, principal.Claims);
return default;
}
@ -3914,7 +3922,7 @@ namespace OpenIddict.Server
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
// Note: user codes are always reference tokens.
.AddFilter<RequireUserCodeIncluded>()
.AddFilter<RequireUserCodeGenerated>()
.UseScopedHandler<ConvertReferenceUserCode>()
.SetOrder(GenerateIdentityModelUserCode.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -3928,7 +3936,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (string.IsNullOrEmpty(context.Response.UserCode))
if (string.IsNullOrEmpty(context.UserCode))
{
return;
}
@ -3962,13 +3970,13 @@ namespace OpenIddict.Server
// Attach the generated token to the token entry, persist the change
// and replace the returned token by the reference identifier.
descriptor.Payload = context.Response.UserCode;
descriptor.Payload = context.UserCode;
descriptor.Principal = principal;
descriptor.ReferenceId = await GenerateReferenceIdentifierAsync(_tokenManager);
await _tokenManager.UpdateAsync(token, descriptor);
context.Response.UserCode = descriptor.ReferenceId;
context.UserCode = descriptor.ReferenceId;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6027), identifier, descriptor.ReferenceId);
@ -4015,7 +4023,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireIdentityTokenIncluded>()
.AddFilter<RequireIdentityTokenGenerated>()
.UseSingletonHandler<AttachTokenDigests>()
.SetOrder(ConvertReferenceUserCode.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -4035,8 +4043,7 @@ namespace OpenIddict.Server
throw new InvalidOperationException(SR.GetResourceString(SR.ID0022));
}
if (string.IsNullOrEmpty(context.Response.AccessToken) &&
string.IsNullOrEmpty(context.Response.Code))
if (string.IsNullOrEmpty(context.AccessToken) && string.IsNullOrEmpty(context.AuthorizationCode))
{
return default;
}
@ -4054,18 +4061,18 @@ namespace OpenIddict.Server
throw new InvalidOperationException(SR.GetResourceString(SR.ID0267));
}
if (!string.IsNullOrEmpty(context.Response.AccessToken))
if (!string.IsNullOrEmpty(context.AccessToken))
{
var digest = hash.ComputeHash(Encoding.ASCII.GetBytes(context.Response.AccessToken));
var digest = hash.ComputeHash(Encoding.ASCII.GetBytes(context.AccessToken));
// Note: only the left-most half of the hash is used.
// See http://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken
principal.SetClaim(Claims.AccessTokenHash, Base64UrlEncoder.Encode(digest, 0, digest.Length / 2));
}
if (!string.IsNullOrEmpty(context.Response.Code))
if (!string.IsNullOrEmpty(context.AuthorizationCode))
{
var digest = hash.ComputeHash(Encoding.ASCII.GetBytes(context.Response.Code));
var digest = hash.ComputeHash(Encoding.ASCII.GetBytes(context.AuthorizationCode));
// Note: only the left-most half of the hash is used.
// See http://openid.net/specs/openid-connect-core-1_0.html#HybridIDToken
@ -4163,7 +4170,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireIdentityTokenIncluded>()
.AddFilter<RequireIdentityTokenGenerated>()
.UseScopedHandler<CreateIdentityTokenEntry>()
.SetOrder(AttachTokenDigests.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -4231,7 +4238,7 @@ namespace OpenIddict.Server
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireIdentityTokenIncluded>()
.AddFilter<RequireIdentityTokenGenerated>()
.UseSingletonHandler<GenerateIdentityModelIdentityToken>()
.SetOrder(CreateIdentityTokenEntry.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -4246,7 +4253,7 @@ namespace OpenIddict.Server
}
// If an identity token was already attached by another handler, don't overwrite it.
if (!string.IsNullOrEmpty(context.Response.IdToken))
if (!string.IsNullOrEmpty(context.IdentityToken))
{
return default;
}
@ -4306,9 +4313,10 @@ namespace OpenIddict.Server
// Sign and attach the identity token.
var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor);
context.Response.IdToken = token;
context.IdentityToken = token;
context.Logger.LogTrace(SR.GetResourceString(SR.ID6029), principal.GetClaim(Claims.JwtId), token, principal.Claims);
context.Logger.LogTrace(SR.GetResourceString(SR.ID6029), principal.GetClaim(Claims.JwtId),
context.IdentityToken, principal.Claims);
return default;
}
@ -4329,7 +4337,7 @@ namespace OpenIddict.Server
// but the default CreateReferenceUserCodeEntry that creates the user code
// reference identifiers only works when the degraded mode is disabled.
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireUserCodeIncluded>()
.AddFilter<RequireUserCodeGenerated>()
.UseSingletonHandler<BeautifyUserCode>()
.SetOrder(GenerateIdentityModelIdentityToken.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
@ -4347,7 +4355,7 @@ namespace OpenIddict.Server
// appended before each new block of 4 integers. These dashes are expected to be
// stripped from the user codes when receiving them at the verification endpoint.
var builder = new StringBuilder(context.Response.UserCode);
var builder = new StringBuilder(context.UserCode);
if (builder.Length % 4 != 0)
{
return default;
@ -4361,24 +4369,23 @@ namespace OpenIddict.Server
}
}
context.Response.UserCode = builder.ToString();
context.UserCode = builder.ToString();
return default;
}
}
/// <summary>
/// Contains the logic responsible of attaching additional access token properties to the sign-in response.
/// Contains the logic responsible of attaching the tokens and their metadata to the sign-in response.
/// </summary>
public class AttachAccessTokenProperties : IOpenIddictServerHandler<ProcessSignInContext>
public class AttachTokenParameters : IOpenIddictServerHandler<ProcessSignInContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireAccessTokenIncluded>()
.UseSingletonHandler<AttachAccessTokenProperties>()
.UseSingletonHandler<AttachTokenParameters>()
.SetOrder(BeautifyUserCode.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
.Build();
@ -4391,73 +4398,78 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.AccessTokenPrincipal is not null, SR.GetResourceString(SR.ID4006));
if (context.IncludeAccessToken)
{
context.Response.AccessToken = context.AccessToken;
context.Response.TokenType = TokenTypes.Bearer;
context.Response.TokenType = TokenTypes.Bearer;
// If the principal is available, attach additional metadata.
if (context.AccessTokenPrincipal is not null)
{
// If an expiration date was set on the access token principal, return it to the client application.
var date = context.AccessTokenPrincipal.GetExpirationDate();
if (date.HasValue && date.Value > DateTimeOffset.UtcNow)
{
context.Response.ExpiresIn = (long) ((date.Value - DateTimeOffset.UtcNow).TotalSeconds + .5);
}
// If an expiration date was set on the access token principal, return it to the client application.
var date = context.AccessTokenPrincipal.GetExpirationDate();
if (date.HasValue && date.Value > DateTimeOffset.UtcNow)
{
context.Response.ExpiresIn = (long) ((date.Value - DateTimeOffset.UtcNow).TotalSeconds + .5);
// If the granted access token scopes differ from the requested scopes, return the granted scopes
// list as a parameter to inform the client application of the fact the scopes set will be reduced.
var scopes = new HashSet<string>(context.AccessTokenPrincipal.GetScopes(), StringComparer.Ordinal);
if ((context.EndpointType == OpenIddictServerEndpointType.Token && context.Request.IsAuthorizationCodeGrantType()) ||
!scopes.SetEquals(context.Request.GetScopes()))
{
context.Response.Scope = string.Join(" ", scopes);
}
}
}
// If the granted access token scopes differ from the requested scopes, return the granted scopes
// list as a parameter to inform the client application of the fact the scopes set will be reduced.
var scopes = new HashSet<string>(context.AccessTokenPrincipal.GetScopes(), StringComparer.Ordinal);
if ((context.EndpointType == OpenIddictServerEndpointType.Token && context.Request.IsAuthorizationCodeGrantType()) ||
!scopes.SetEquals(context.Request.GetScopes()))
if (context.IncludeAuthorizationCode)
{
context.Response.Scope = string.Join(" ", scopes);
context.Response.Code = context.AuthorizationCode;
}
return default;
}
}
if (context.IncludeDeviceCode)
{
context.Response.DeviceCode = context.DeviceCode;
/// <summary>
/// Contains the logic responsible of attaching additional device code properties to the sign-in response.
/// </summary>
public class AttachDeviceCodeProperties : IOpenIddictServerHandler<ProcessSignInContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDeviceCodeIncluded>()
.UseSingletonHandler<AttachDeviceCodeProperties>()
.SetOrder(AttachAccessTokenProperties.Descriptor.Order + 1_000)
.SetType(OpenIddictServerHandlerType.BuiltIn)
.Build();
// If the principal is available, attach additional metadata.
if (context.DeviceCodePrincipal is not null)
{
// If an expiration date was set on the device code principal, return it to the client application.
var date = context.DeviceCodePrincipal.GetExpirationDate();
if (date.HasValue && date.Value > DateTimeOffset.UtcNow)
{
context.Response.ExpiresIn = (long) ((date.Value - DateTimeOffset.UtcNow).TotalSeconds + .5);
}
}
}
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessSignInContext context)
{
if (context is null)
if (context.IncludeIdentityToken)
{
throw new ArgumentNullException(nameof(context));
context.Response.IdToken = context.IdentityToken;
}
Debug.Assert(context.DeviceCodePrincipal is not null, SR.GetResourceString(SR.ID4006));
var address = GetEndpointAbsoluteUri(context.Issuer, context.Options.VerificationEndpointUris.FirstOrDefault());
if (address is not null)
if (context.IncludeRefreshToken)
{
var builder = new UriBuilder(address)
{
Query = string.Concat(Parameters.UserCode, "=", context.Response.UserCode)
};
context.Response[Parameters.VerificationUri] = address.AbsoluteUri;
context.Response[Parameters.VerificationUriComplete] = builder.Uri.AbsoluteUri;
context.Response.RefreshToken = context.RefreshToken;
}
// If an expiration date was set on the device code principal, return it to the client application.
var date = context.DeviceCodePrincipal.GetExpirationDate();
if (date.HasValue && date.Value > DateTimeOffset.UtcNow)
if (context.IncludeUserCode)
{
context.Response.ExpiresIn = (long) ((date.Value - DateTimeOffset.UtcNow).TotalSeconds + .5);
context.Response.UserCode = context.UserCode;
var address = GetEndpointAbsoluteUri(context.Issuer, context.Options.VerificationEndpointUris.FirstOrDefault());
if (address is not null)
{
var builder = new UriBuilder(address)
{
Query = string.Concat(Parameters.UserCode, "=", context.UserCode)
};
context.Response[Parameters.VerificationUri] = address.AbsoluteUri;
context.Response[Parameters.VerificationUriComplete] = builder.Uri.AbsoluteUri;
}
}
return default;

70
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs

@ -1608,15 +1608,15 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
context.IncludeAccessToken = false;
context.IncludeAuthorizationCode = true;
context.IncludeIdentityToken = true;
context.IncludeRefreshToken = true;
context.GenerateAccessToken = context.IncludeAccessToken = false;
context.GenerateAuthorizationCode = context.IncludeAuthorizationCode = true;
context.GenerateIdentityToken = context.IncludeIdentityToken = true;
context.GenerateRefreshToken = context.IncludeRefreshToken = true;
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -1662,12 +1662,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateAuthorizationCode);
Assert.True(context.IncludeAuthorizationCode);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -1801,12 +1802,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateAccessToken);
Assert.True(context.IncludeAccessToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -1856,12 +1858,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateAccessToken);
Assert.True(context.IncludeAccessToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -1908,12 +1911,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateAccessToken);
Assert.True(context.IncludeAccessToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -1951,12 +1955,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateAccessToken);
Assert.True(context.IncludeAccessToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -1995,12 +2000,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateAccessToken);
Assert.True(context.IncludeAccessToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2040,12 +2046,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateAccessToken);
Assert.True(context.IncludeAccessToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2114,12 +2121,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.False(context.GenerateRefreshToken);
Assert.False(context.IncludeRefreshToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2168,12 +2176,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateRefreshToken);
Assert.True(context.IncludeRefreshToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2221,12 +2230,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateRefreshToken);
Assert.True(context.IncludeRefreshToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2255,12 +2265,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateRefreshToken);
Assert.True(context.IncludeRefreshToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
options.AddEventHandler<HandleTokenRequestContext>(builder =>
@ -2300,12 +2311,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateRefreshToken);
Assert.True(context.IncludeRefreshToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
options.AddEventHandler<HandleTokenRequestContext>(builder =>
@ -2346,12 +2358,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateRefreshToken);
Assert.True(context.IncludeRefreshToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
options.AddEventHandler<HandleTokenRequestContext>(builder =>
@ -2398,12 +2411,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.False(context.GenerateIdentityToken);
Assert.False(context.IncludeIdentityToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2446,12 +2460,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateIdentityToken);
Assert.True(context.IncludeIdentityToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2502,12 +2517,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateIdentityToken);
Assert.True(context.IncludeIdentityToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2555,12 +2571,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateIdentityToken);
Assert.True(context.IncludeIdentityToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2589,12 +2606,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateIdentityToken);
Assert.True(context.IncludeIdentityToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
options.AddEventHandler<HandleTokenRequestContext>(builder =>
@ -2643,12 +2661,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateIdentityToken);
Assert.True(context.IncludeIdentityToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});
@ -2689,12 +2708,13 @@ namespace OpenIddict.Server.IntegrationTests
{
builder.UseInlineHandler(context =>
{
Assert.True(context.GenerateIdentityToken);
Assert.True(context.IncludeIdentityToken);
return default;
});
builder.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 500);
builder.SetOrder(EvaluateTokenTypes.Descriptor.Order + 500);
});
});

Loading…
Cancel
Save