Browse Source

Implement client authentication support for the PAR endpoint

Kévin Chalet 8 months ago
parent
commit
0f46191cbb
  1. 3
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs
  2. 142
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
  3. 13
      src/OpenIddict.Client/OpenIddictClientHandlers.cs
  4. 17
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  5. 172
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs

3
sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs

@ -154,7 +154,6 @@ public class Worker : IHostedService
{
ApplicationType = ApplicationTypes.Web,
ClientId = "mvc",
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
ClientType = ClientTypes.Confidential,
ConsentType = ConsentTypes.Systematic,
DisplayName = "MVC client application",
@ -180,6 +179,8 @@ public class Worker : IHostedService
"""))
}
},
#else
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
#endif
RedirectUris =
{

142
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs

@ -36,6 +36,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
* Challenge processing:
*/
AttachNonDefaultDeviceAuthorizationEndpointClientAuthenticationMethod.Descriptor,
AttachNonDefaultPushedAuthorizationEndpointClientAuthenticationMethod.Descriptor,
/*
* Introspection processing:
@ -290,7 +291,15 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
_ => context.Options.ClientAuthenticationMethods.Intersect(context.Registration.ClientAuthenticationMethods, StringComparer.Ordinal).ToList()
},
Server: context.Configuration.DeviceAuthorizationEndpointAuthMethodsSupported) switch
// Note: if the authorization server doesn't support the OpenIddict-specific
// "device_authorization_request_endpoint_auth_methods_supported" node,
// fall back to the "token_endpoint_auth_methods_supported" node,
// which is the same logic as for the pushed authorization endpoint.
Server: context.Configuration.DeviceAuthorizationEndpointAuthMethodsSupported.Count switch
{
0 => context.Configuration.TokenEndpointAuthMethodsSupported,
_ => context.Configuration.DeviceAuthorizationEndpointAuthMethodsSupported,
}) switch
{
// If a TLS client authentication certificate could be resolved and both the
// client and the server explicitly support tls_client_auth, always prefer it.
@ -365,6 +374,137 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
}
}
/// <summary>
/// Contains the logic responsible for negotiating the best pushed authorization endpoint
/// client authentication method supported by both the client and the authorization server.
/// </summary>
public sealed class AttachNonDefaultPushedAuthorizationEndpointClientAuthenticationMethod : IOpenIddictClientHandler<ProcessChallengeContext>
{
private readonly IOptionsMonitor<OpenIddictClientSystemNetHttpOptions> _options;
public AttachNonDefaultPushedAuthorizationEndpointClientAuthenticationMethod(
IOptionsMonitor<OpenIddictClientSystemNetHttpOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<ProcessChallengeContext>()
.AddFilter<RequirePushedAuthorizationRequest>()
.UseSingletonHandler<AttachNonDefaultPushedAuthorizationEndpointClientAuthenticationMethod>()
.SetOrder(AttachPushedAuthorizationEndpointClientAuthenticationMethod.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// If an explicit client authentication method was attached, don't overwrite it.
if (!string.IsNullOrEmpty(context.PushedAuthorizationEndpointClientAuthenticationMethod))
{
return default;
}
context.PushedAuthorizationEndpointClientAuthenticationMethod = (
// Note: if client authentication methods are explicitly listed in the client registration, only use
// the client authentication methods that are both listed and enabled in the global client options.
// Otherwise, always default to the client authentication methods that have been enabled globally.
Client: context.Registration.ClientAuthenticationMethods.Count switch
{
0 => context.Options.ClientAuthenticationMethods as ICollection<string>,
_ => context.Options.ClientAuthenticationMethods.Intersect(context.Registration.ClientAuthenticationMethods, StringComparer.Ordinal).ToList()
},
// Note: if the authorization server doesn't support the OpenIddict-specific
// "pushed_authorization_request_endpoint_auth_methods_supported" node, fall back to
// the "token_endpoint_auth_methods_supported" node, as required by the specification.
//
// See https://datatracker.ietf.org/doc/html/rfc9126#section-2 for more information.
Server: context.Configuration.PushedAuthorizationEndpointAuthMethodsSupported.Count switch
{
0 => context.Configuration.TokenEndpointAuthMethodsSupported,
_ => context.Configuration.PushedAuthorizationEndpointAuthMethodsSupported,
}) switch
{
// If a TLS client authentication certificate could be resolved and both the
// client and the server explicitly support tls_client_auth, always prefer it.
({ Count: > 0 } client, { Count: > 0 } server) when
client.Contains(ClientAuthenticationMethods.TlsClientAuth) &&
server.Contains(ClientAuthenticationMethods.TlsClientAuth) &&
(context.Configuration.MtlsPushedAuthorizationEndpoint ?? context.Configuration.PushedAuthorizationEndpoint) is Uri endpoint &&
string.Equals(endpoint.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase) &&
_options.CurrentValue.TlsClientAuthenticationCertificateSelector(context.Registration) is not null
=> ClientAuthenticationMethods.TlsClientAuth,
// If a self-signed TLS client authentication certificate could be resolved and both
// the client and the server explicitly support self_signed_tls_client_auth, use it.
({ Count: > 0 } client, { Count: > 0 } server) when
client.Contains(ClientAuthenticationMethods.SelfSignedTlsClientAuth) &&
server.Contains(ClientAuthenticationMethods.SelfSignedTlsClientAuth) &&
(context.Configuration.MtlsPushedAuthorizationEndpoint ?? context.Configuration.PushedAuthorizationEndpoint) is Uri endpoint &&
string.Equals(endpoint.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase) &&
_options.CurrentValue.SelfSignedTlsClientAuthenticationCertificateSelector(context.Registration) is not null
=> ClientAuthenticationMethods.SelfSignedTlsClientAuth,
// If at least one asymmetric signing key was attached to the client registration
// and both the client and the server explicitly support private_key_jwt, use it.
({ Count: > 0 } client, { Count: > 0 } server) when
client.Contains(ClientAuthenticationMethods.PrivateKeyJwt) &&
server.Contains(ClientAuthenticationMethods.PrivateKeyJwt) &&
context.Registration.SigningCredentials.Exists(static credentials => credentials.Key is AsymmetricSecurityKey)
=> ClientAuthenticationMethods.PrivateKeyJwt,
// If a client secret was attached to the client registration and both the client and
// the server explicitly support client_secret_post, prefer it to basic authentication.
({ Count: > 0 } client, { Count: > 0 } server) when !string.IsNullOrEmpty(context.Registration.ClientSecret) &&
client.Contains(ClientAuthenticationMethods.ClientSecretPost) &&
server.Contains(ClientAuthenticationMethods.ClientSecretPost)
=> ClientAuthenticationMethods.ClientSecretPost,
// 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 the server configuration
// doesn't list any supported client authentication method or doesn't support client_secret_post.
//
// 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.
({ Count: > 0 } client, { Count: > 0 } server) when !string.IsNullOrEmpty(context.Registration.ClientSecret) &&
client.Contains(ClientAuthenticationMethods.ClientSecretBasic) &&
server.Contains(ClientAuthenticationMethods.ClientSecretBasic)
=> ClientAuthenticationMethods.ClientSecretBasic,
({ Count: > 0 } client, { Count: 0 }) when !string.IsNullOrEmpty(context.Registration.ClientSecret) &&
client.Contains(ClientAuthenticationMethods.ClientSecretBasic)
=> ClientAuthenticationMethods.ClientSecretBasic,
_ => null
};
return default;
}
}
/// <summary>
/// Contains the logic responsible for negotiating the best introspection endpoint client
/// authentication method supported by both the client and the authorization server.

13
src/OpenIddict.Client/OpenIddictClientHandlers.cs

@ -5651,7 +5651,15 @@ public static partial class OpenIddictClientHandlers
_ => context.Options.ClientAuthenticationMethods.Intersect(context.Registration.ClientAuthenticationMethods, StringComparer.Ordinal).ToList()
},
Server: context.Configuration.DeviceAuthorizationEndpointAuthMethodsSupported) switch
// Note: if the authorization server doesn't support the OpenIddict-specific
// "device_authorization_request_endpoint_auth_methods_supported" node,
// fall back to the "token_endpoint_auth_methods_supported" node,
// which is the same logic as for the pushed authorization endpoint.
Server: context.Configuration.DeviceAuthorizationEndpointAuthMethodsSupported.Count switch
{
0 => context.Configuration.TokenEndpointAuthMethodsSupported,
_ => context.Configuration.DeviceAuthorizationEndpointAuthMethodsSupported,
}) switch
{
// If at least one signing key was attached to the client registration and both
// the client and the server explicitly support private_key_jwt, always prefer it.
@ -5967,9 +5975,8 @@ public static partial class OpenIddictClientHandlers
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<ProcessChallengeContext>()
.AddFilter<RequireDeviceAuthorizationRequest>()
.UseSingletonHandler<EvaluateGeneratedChallengeClientAssertion>()
.SetOrder(AttachDeviceAuthorizationRequestParameters.Descriptor.Order + 1_000)
.SetOrder(AttachPushedAuthorizationRequestParameters.Descriptor.Order + 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();

17
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -315,7 +315,8 @@ public static partial class OpenIddictServerHandlers
// By default, client assertions are not required, but they are extracted and validated if
// present and invalid client assertions are always automatically rejected by OpenIddict.
OpenIddictServerEndpointType.DeviceAuthorization or OpenIddictServerEndpointType.Introspection or
OpenIddictServerEndpointType.Revocation or OpenIddictServerEndpointType.Token
OpenIddictServerEndpointType.PushedAuthorization or OpenIddictServerEndpointType.Revocation or
OpenIddictServerEndpointType.Token
=> (true, false, true, true),
_ => (false, false, false, false)
@ -446,7 +447,8 @@ public static partial class OpenIddictServerHandlers
(context.ClientAssertion, context.ClientAssertionType) = context.EndpointType switch
{
OpenIddictServerEndpointType.DeviceAuthorization or OpenIddictServerEndpointType.Introspection or
OpenIddictServerEndpointType.Revocation or OpenIddictServerEndpointType.Token
OpenIddictServerEndpointType.PushedAuthorization or OpenIddictServerEndpointType.Revocation or
OpenIddictServerEndpointType.Token
when context.ExtractClientAssertion
=> (context.Request.ClientAssertion, context.Request.ClientAssertionType),
@ -1057,6 +1059,12 @@ public static partial class OpenIddictServerHandlers
case OpenIddictServerEndpointType.Revocation when context.Options.AcceptAnonymousClients:
case OpenIddictServerEndpointType.Token when context.Options.AcceptAnonymousClients:
return;
// Note: despite being conceptually similar to the token endpoint, the pushed authorization
// endpoint deliberately doesn't allow anonymous clients, as a client_id is always required
// for both regular authorization requests and pushed authorization requests.
//
// See https://datatracker.ietf.org/doc/html/rfc9126#section-2.1 for more information.
}
context.Logger.LogInformation(SR.GetResourceString(SR.ID6220), Parameters.ClientId);
@ -1088,7 +1096,8 @@ public static partial class OpenIddictServerHandlers
{
// For non-interactive endpoints, return "invalid_client" instead of "invalid_request".
OpenIddictServerEndpointType.DeviceAuthorization or OpenIddictServerEndpointType.Introspection or
OpenIddictServerEndpointType.Revocation or OpenIddictServerEndpointType.Token
OpenIddictServerEndpointType.PushedAuthorization or OpenIddictServerEndpointType.Revocation or
OpenIddictServerEndpointType.Token
=> Errors.InvalidClient,
_ => Errors.InvalidRequest
@ -1142,7 +1151,6 @@ public static partial class OpenIddictServerHandlers
if (context.EndpointType is OpenIddictServerEndpointType.Authorization or
OpenIddictServerEndpointType.EndSession or
OpenIddictServerEndpointType.EndUserVerification or
OpenIddictServerEndpointType.PushedAuthorization or
OpenIddictServerEndpointType.UserInfo)
{
return;
@ -1252,7 +1260,6 @@ public static partial class OpenIddictServerHandlers
if (context.EndpointType is OpenIddictServerEndpointType.Authorization or
OpenIddictServerEndpointType.EndSession or
OpenIddictServerEndpointType.EndUserVerification or
OpenIddictServerEndpointType.PushedAuthorization or
OpenIddictServerEndpointType.UserInfo)
{
return;

172
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs

@ -3095,6 +3095,130 @@ public abstract partial class OpenIddictServerIntegrationTests
Assert.Equal(SR.FormatID8000(SR.ID2029), response.ErrorUri);
}
[Fact]
public async Task ValidatePushedAuthorizationRequest_ClientSecretCannotBeUsedByPublicClients()
{
// Arrange
var application = new OpenIddictApplication();
var manager = CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
});
await using var server = await CreateServerAsync(options =>
{
options.Services.AddSingleton(manager);
});
await using var client = await server.CreateClientAsync();
// Act
var response = await client.PostAsync("/connect/par", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code
});
// Assert
Assert.Equal(Errors.InvalidClient, response.Error);
Assert.Equal(SR.FormatID2053(Parameters.ClientSecret), response.ErrorDescription);
Assert.Equal(SR.FormatID8000(SR.ID2053), response.ErrorUri);
Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()), Times.AtLeastOnce());
Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task ValidatePushedAuthorizationRequest_ClientSecretIsRequiredForNonPublicClients()
{
// Arrange
var application = new OpenIddictApplication();
var manager = CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
});
await using var server = await CreateServerAsync(options =>
{
options.Services.AddSingleton(manager);
});
await using var client = await server.CreateClientAsync();
// Act
var response = await client.PostAsync("/connect/par", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = null,
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code
});
// Assert
Assert.Equal(Errors.InvalidClient, response.Error);
Assert.Equal(SR.FormatID2054(Parameters.ClientSecret), response.ErrorDescription);
Assert.Equal(SR.FormatID8000(SR.ID2054), response.ErrorUri);
Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()), Times.AtLeastOnce());
Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task ValidatePushedAuthorizationRequest_RequestIsRejectedWhenClientCredentialsAreInvalid()
{
// Arrange
var application = new OpenIddictApplication();
var manager = CreateApplicationManager(mock =>
{
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
mock.Setup(manager => manager.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
});
await using var server = await CreateServerAsync(options =>
{
options.Services.AddSingleton(manager);
});
await using var client = await server.CreateClientAsync();
// Act
var response = await client.PostAsync("/connect/par", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = ResponseTypes.Code
});
// Assert
Assert.Equal(Errors.InvalidClient, response.Error);
Assert.Equal(SR.GetResourceString(SR.ID2055), response.ErrorDescription);
Assert.Equal(SR.FormatID8000(SR.ID2055), response.ErrorUri);
Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()), Times.AtLeastOnce());
Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()), Times.AtLeastOnce());
Mock.Get(manager).Verify(manager => manager.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny<CancellationToken>()), Times.Once());
}
[Fact]
public async Task ValidatePushedAuthorizationRequest_MissingRedirectUriCausesAnErrorForOpenIdRequests()
{
@ -4000,7 +4124,7 @@ public abstract partial class OpenIddictServerIntegrationTests
});
// Assert
Assert.Equal(Errors.InvalidRequest, response.Error);
Assert.Equal(Errors.InvalidClient, response.Error);
Assert.Equal(SR.FormatID2052(Parameters.ClientId), response.ErrorDescription);
Assert.Equal(SR.FormatID8000(SR.ID2052), response.ErrorUri);
@ -4047,6 +4171,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4088,6 +4215,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.GetPermissionsAsync(application, It.IsAny<CancellationToken>()))
.ReturnsAsync(ImmutableArray.Create("rst:" + type));
@ -4151,6 +4281,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Confidential, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateClientSecretAsync(application, "7Fjfp0ZBr1KtDRbnfVdmIw", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.GetPermissionsAsync(application, It.IsAny<CancellationToken>()))
.ReturnsAsync(ImmutableArray<string>.Empty);
});
@ -4166,6 +4299,7 @@ public abstract partial class OpenIddictServerIntegrationTests
var response = await client.PostAsync("/connect/par", new OpenIddictRequest
{
ClientId = "Fabrikam",
ClientSecret = "7Fjfp0ZBr1KtDRbnfVdmIw",
Nonce = "n-0S6_WzA2Mj",
RedirectUri = "http://www.fabrikam.com/path",
ResponseType = type,
@ -4192,6 +4326,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4267,6 +4404,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4324,6 +4464,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4374,6 +4517,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.GetPermissionsAsync(application, It.IsAny<CancellationToken>()))
.ReturnsAsync(ImmutableArray.Create("rst:" + type));
@ -4431,6 +4577,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4481,6 +4630,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
});
@ -4520,6 +4672,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4576,6 +4731,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4622,6 +4780,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4676,6 +4837,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4730,6 +4894,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
@ -4899,6 +5066,9 @@ public abstract partial class OpenIddictServerIntegrationTests
mock.Setup(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny<CancellationToken>()))
.ReturnsAsync(application);
mock.Setup(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
mock.Setup(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny<CancellationToken>()))
.ReturnsAsync(true);

Loading…
Cancel
Save