Browse Source

Replace references to "URL" by "URI" when resource identifiers are not required to be resource locators

pull/1615/head
Kévin Chalet 3 years ago
parent
commit
8c14d4e3e9
  1. 22
      gen/OpenIddict.Client.WebIntegration.Generators/OpenIddictClientWebIntegrationGenerator.cs
  2. 2
      sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/AuthenticationController.cs
  3. 2
      sandbox/OpenIddict.Sandbox.AspNet.Client/Startup.cs
  4. 2
      sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthenticationController.cs
  5. 2
      sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs
  6. 2
      sandbox/OpenIddict.Sandbox.AspNetCore.Client/Startup.cs
  7. 2
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/Startup.cs
  8. 28
      shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs
  9. 10
      src/OpenIddict.Abstractions/Caches/IOpenIddictApplicationCache.cs
  10. 4
      src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs
  11. 20
      src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs
  12. 74
      src/OpenIddict.Abstractions/OpenIddictResources.resx
  13. 14
      src/OpenIddict.Abstractions/Primitives/OpenIddictConfiguration.cs
  14. 26
      src/OpenIddict.Abstractions/Stores/IOpenIddictApplicationStore.cs
  15. 4
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs
  16. 6
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs
  17. 4
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs
  18. 6
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs
  19. 2
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpExtensions.cs
  20. 8
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlerFilters.cs
  21. 2
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs
  22. 4
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs
  23. 30
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
  24. 2
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs
  25. 4
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs
  26. 4
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
  27. 6
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml
  28. 4
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xsd
  29. 84
      src/OpenIddict.Client/OpenIddictClientBuilder.cs
  30. 12
      src/OpenIddict.Client/OpenIddictClientConfiguration.cs
  31. 14
      src/OpenIddict.Client/OpenIddictClientEvents.cs
  32. 4
      src/OpenIddict.Client/OpenIddictClientHandlers.Authentication.cs
  33. 52
      src/OpenIddict.Client/OpenIddictClientHandlers.Discovery.cs
  34. 19
      src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs
  35. 4
      src/OpenIddict.Client/OpenIddictClientHandlers.Session.cs
  36. 62
      src/OpenIddict.Client/OpenIddictClientHandlers.cs
  37. 2
      src/OpenIddict.Client/OpenIddictClientOptions.cs
  38. 22
      src/OpenIddict.Client/OpenIddictClientRegistration.cs
  39. 2
      src/OpenIddict.Client/OpenIddictClientRetriever.cs
  40. 112
      src/OpenIddict.Client/OpenIddictClientService.cs
  41. 28
      src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs
  42. 130
      src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
  43. 4
      src/OpenIddict.EntityFramework.Models/OpenIddictEntityFrameworkApplication.cs
  44. 56
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
  45. 4
      src/OpenIddict.EntityFrameworkCore.Models/OpenIddictEntityFrameworkCoreApplication.cs
  46. 56
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs
  47. 4
      src/OpenIddict.MongoDb.Models/OpenIddictMongoDbApplication.cs
  48. 28
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs
  49. 2
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs
  50. 4
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs
  51. 4
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Device.cs
  52. 4
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs
  53. 2
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs
  54. 2
      src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs
  55. 4
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs
  56. 4
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Device.cs
  57. 4
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs
  58. 2
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs
  59. 372
      src/OpenIddict.Server/OpenIddictServerBuilder.cs
  60. 6
      src/OpenIddict.Server/OpenIddictServerConfiguration.cs
  61. 18
      src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs
  62. 18
      src/OpenIddict.Server/OpenIddictServerEvents.Discovery.cs
  63. 18
      src/OpenIddict.Server/OpenIddictServerEvents.Session.cs
  64. 2
      src/OpenIddict.Server/OpenIddictServerEvents.cs
  65. 18
      src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
  66. 8
      src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
  67. 6
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  68. 12
      src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs
  69. 23
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  70. 2
      src/OpenIddict.Server/OpenIddictServerOptions.cs
  71. 2
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreBuilder.cs
  72. 2
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs
  73. 2
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinBuilder.cs
  74. 2
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs
  75. 2
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpExtensions.cs
  76. 8
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlerFilters.cs
  77. 2
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs
  78. 30
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs
  79. 28
      src/OpenIddict.Validation/OpenIddictValidationBuilder.cs
  80. 31
      src/OpenIddict.Validation/OpenIddictValidationConfiguration.cs
  81. 6
      src/OpenIddict.Validation/OpenIddictValidationEvents.cs
  82. 24
      src/OpenIddict.Validation/OpenIddictValidationHandlers.Discovery.cs
  83. 2
      src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs
  84. 8
      src/OpenIddict.Validation/OpenIddictValidationOptions.cs
  85. 74
      src/OpenIddict.Validation/OpenIddictValidationService.cs
  86. 12
      test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs
  87. 10
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs
  88. 8
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs
  89. 4
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Session.cs
  90. 4
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs
  91. 12
      test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs
  92. 164
      test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs
  93. 10
      test/OpenIddict.Validation.IntegrationTests/OpenIddictValidationIntegrationTestClient.cs

22
gen/OpenIddict.Client.WebIntegration.Generators/OpenIddictClientWebIntegrationGenerator.cs

@ -175,31 +175,31 @@ public sealed partial class OpenIddictClientWebIntegrationBuilder
/// <summary> /// <summary>
/// Sets the redirection URI, if applicable. /// Sets the redirection URI, if applicable.
/// </summary> /// </summary>
/// <param name=""address"">The redirection URI.</param> /// <param name=""uri"">The redirection URI.</param>
/// <returns>The <see cref=""OpenIddictClientWebIntegrationBuilder.{{ provider.name }}""/> instance.</returns> /// <returns>The <see cref=""OpenIddictClientWebIntegrationBuilder.{{ provider.name }}""/> instance.</returns>
public {{ provider.name }} SetRedirectUri(Uri address) public {{ provider.name }} SetRedirectUri(Uri uri)
{ {
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
return Configure(options => options.RedirectUri = address); return Configure(options => options.RedirectUri = uri);
} }
/// <summary> /// <summary>
/// Sets the redirection URI, if applicable. /// Sets the redirection URI, if applicable.
/// </summary> /// </summary>
/// <param name=""address"">The redirection URI.</param> /// <param name=""uri"">The redirection URI.</param>
/// <returns>The <see cref=""OpenIddictClientWebIntegrationBuilder.{{ provider.name }}""/> instance.</returns> /// <returns>The <see cref=""OpenIddictClientWebIntegrationBuilder.{{ provider.name }}""/> instance.</returns>
public {{ provider.name }} SetRedirectUri([StringSyntax(StringSyntaxAttribute.Uri)] string address) public {{ provider.name }} SetRedirectUri([StringSyntax(StringSyntaxAttribute.Uri)] string uri)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
return SetRedirectUri(new Uri(address, UriKind.RelativeOrAbsolute)); return SetRedirectUri(new Uri(uri, UriKind.RelativeOrAbsolute));
} }
/// <summary> /// <summary>
@ -813,7 +813,7 @@ public sealed partial class OpenIddictClientWebIntegrationOptions
public string? ClientSecret { get; set; } public string? ClientSecret { get; set; }
/// <summary> /// <summary>
/// Gets or sets the redirection URL. /// Gets or sets the redirect URI.
/// </summary> /// </summary>
public Uri? RedirectUri { get; set; } public Uri? RedirectUri { get; set; }

2
sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/AuthenticationController.cs

@ -216,7 +216,7 @@ namespace OpenIddict.Sandbox.AspNet.Client.Controllers
var properties = new AuthenticationProperties(result.Properties.Dictionary var properties = new AuthenticationProperties(result.Properties.Dictionary
.Where(item => item switch .Where(item => item switch
{ {
// Preserve the redirect URL. // Preserve the return URL.
{ Key: ".redirect" } => true, { Key: ".redirect" } => true,
// If needed, the tokens returned by the authorization server can be stored in the authentication cookie. // If needed, the tokens returned by the authorization server can be stored in the authentication cookie.

2
sandbox/OpenIddict.Sandbox.AspNet.Client/Startup.cs

@ -69,7 +69,7 @@ namespace OpenIddict.Sandbox.AspNet.Client
// Enable the redirection endpoint needed to handle the callback stage. // Enable the redirection endpoint needed to handle the callback stage.
// //
// Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint
// address per provider, unless all the registered providers support returning an "iss" // URI per provider, unless all the registered providers support returning a special "iss"
// parameter containing their URL as part of authorization responses. For more information, // parameter containing their URL as part of authorization responses. For more information,
// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4.
options.SetRedirectionEndpointUris( options.SetRedirectionEndpointUris(

2
sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthenticationController.cs

@ -109,7 +109,7 @@ namespace OpenIddict.Sandbox.AspNet.Server.Controllers
var properties = new AuthenticationProperties(result.Properties.Dictionary var properties = new AuthenticationProperties(result.Properties.Dictionary
.Where(item => item switch .Where(item => item switch
{ {
// Preserve the redirect URL. // Preserve the return URL.
{ Key: ".redirect" } => true, { Key: ".redirect" } => true,
// If needed, the tokens returned by the authorization server can be stored in the authentication cookie. // If needed, the tokens returned by the authorization server can be stored in the authentication cookie.

2
sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs

@ -154,7 +154,7 @@ namespace OpenIddict.Sandbox.AspNet.Server
// Enable the redirection endpoint needed to handle the callback stage. // Enable the redirection endpoint needed to handle the callback stage.
// //
// Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint
// address per provider, unless all the registered providers support returning an "iss" // URI per provider, unless all the registered providers support returning a special "iss"
// parameter containing their URL as part of authorization responses. For more information, // parameter containing their URL as part of authorization responses. For more information,
// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4.
options.SetRedirectionEndpointUris("callback/login/github"); options.SetRedirectionEndpointUris("callback/login/github");

2
sandbox/OpenIddict.Sandbox.AspNetCore.Client/Startup.cs

@ -77,7 +77,7 @@ public class Startup
// Enable the redirection endpoint needed to handle the callback stage. // Enable the redirection endpoint needed to handle the callback stage.
// //
// Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint
// address per provider, unless all the registered providers support returning an "iss" // URI per provider, unless all the registered providers support returning a special "iss"
// parameter containing their URL as part of authorization responses. For more information, // parameter containing their URL as part of authorization responses. For more information,
// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4.
options.SetRedirectionEndpointUris( options.SetRedirectionEndpointUris(

2
sandbox/OpenIddict.Sandbox.AspNetCore.Server/Startup.cs

@ -71,7 +71,7 @@ public class Startup
// Enable the redirection endpoint needed to handle the callback stage. // Enable the redirection endpoint needed to handle the callback stage.
// //
// Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint
// address per provider, unless all the registered providers support returning an "iss" // URI per provider, unless all the registered providers support returning a special "iss"
// parameter containing their URL as part of authorization responses. For more information, // parameter containing their URL as part of authorization responses. For more information,
// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4.
options.SetRedirectionEndpointUris("callback/login/github"); options.SetRedirectionEndpointUris("callback/login/github");

28
shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs

@ -172,18 +172,18 @@ internal static class OpenIddictHelpers
/// <summary> /// <summary>
/// Adds a query string parameter to the specified <see cref="Uri"/>. /// Adds a query string parameter to the specified <see cref="Uri"/>.
/// </summary> /// </summary>
/// <param name="address">The address, to which the query string parameter will be appended.</param> /// <param name="uri">The URI to which the query string parameter will be appended.</param>
/// <param name="name">The name of the query string parameter to append.</param> /// <param name="name">The name of the query string parameter to append.</param>
/// <param name="value">The value of the query string parameter to append.</param> /// <param name="value">The value of the query string parameter to append.</param>
/// <returns>The final <see cref="Uri"/> instance, with the specified parameter appended.</returns> /// <returns>The final <see cref="Uri"/> instance, with the specified parameter appended.</returns>
public static Uri AddQueryStringParameter(Uri address, string name, string? value) public static Uri AddQueryStringParameter(Uri uri, string name, string? value)
{ {
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
var builder = new StringBuilder(address.Query); var builder = new StringBuilder(uri.Query);
if (builder.Length > 0) if (builder.Length > 0)
{ {
builder.Append('&'); builder.Append('&');
@ -197,22 +197,22 @@ internal static class OpenIddictHelpers
builder.Append(Uri.EscapeDataString(value)); builder.Append(Uri.EscapeDataString(value));
} }
return new UriBuilder(address) { Query = builder.ToString() }.Uri; return new UriBuilder(uri) { Query = builder.ToString() }.Uri;
} }
/// <summary> /// <summary>
/// Adds query string parameters to the specified <see cref="Uri"/>. /// Adds query string parameters to the specified <see cref="Uri"/>.
/// </summary> /// </summary>
/// <param name="address">The address, to which the query string parameters will be appended.</param> /// <param name="uri">The URI to which the query string parameters will be appended.</param>
/// <param name="parameters">The query string parameters to append.</param> /// <param name="parameters">The query string parameters to append.</param>
/// <returns>The final <see cref="Uri"/> instance, with the specified parameters appended.</returns> /// <returns>The final <see cref="Uri"/> instance, with the specified parameters appended.</returns>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="parameters"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="parameters"/> is <see langword="null"/>.</exception>
public static Uri AddQueryStringParameters(Uri address, IReadOnlyDictionary<string, StringValues> parameters) public static Uri AddQueryStringParameters(Uri uri, IReadOnlyDictionary<string, StringValues> parameters)
{ {
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
if (parameters is null) if (parameters is null)
@ -222,10 +222,10 @@ internal static class OpenIddictHelpers
if (parameters.Count is 0) if (parameters.Count is 0)
{ {
return address; return uri;
} }
var builder = new StringBuilder(address.Query); var builder = new StringBuilder(uri.Query);
foreach (var parameter in parameters) foreach (var parameter in parameters)
{ {
@ -263,7 +263,7 @@ internal static class OpenIddictHelpers
} }
} }
return new UriBuilder(address) { Query = builder.ToString() }.Uri; return new UriBuilder(uri) { Query = builder.ToString() }.Uri;
} }
/// <summary> /// <summary>

10
src/OpenIddict.Abstractions/Caches/IOpenIddictApplicationCache.cs

@ -45,22 +45,22 @@ public interface IOpenIddictApplicationCache<TApplication> where TApplication :
ValueTask<TApplication?> FindByIdAsync(string identifier, CancellationToken cancellationToken); ValueTask<TApplication?> FindByIdAsync(string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Retrieves all the applications associated with the specified redirect_uri. /// Retrieves all the applications associated with the specified post_logout_redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The redirect_uri associated with the applications.</param> /// <param name="uri">The post_logout_redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The client applications corresponding to the specified redirect_uri.</returns> /// <returns>The client applications corresponding to the specified redirect_uri.</returns>
IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync( IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken); [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Retrieves all the applications associated with the specified redirect_uri. /// Retrieves all the applications associated with the specified redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The redirect_uri associated with the applications.</param> /// <param name="uri">The redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The client applications corresponding to the specified redirect_uri.</returns> /// <returns>The client applications corresponding to the specified redirect_uri.</returns>
IAsyncEnumerable<TApplication> FindByRedirectUriAsync( IAsyncEnumerable<TApplication> FindByRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken); [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Removes the specified application from the cache. /// Removes the specified application from the cache.

4
src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs

@ -41,7 +41,7 @@ public class OpenIddictApplicationDescriptor
public HashSet<string> Permissions { get; } = new(StringComparer.Ordinal); public HashSet<string> Permissions { get; } = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Gets the logout callback URLs associated with the application. /// Gets the post-logout redirect URIs associated with the application.
/// </summary> /// </summary>
public HashSet<Uri> PostLogoutRedirectUris { get; } = new(); public HashSet<Uri> PostLogoutRedirectUris { get; } = new();
@ -51,7 +51,7 @@ public class OpenIddictApplicationDescriptor
public Dictionary<string, JsonElement> Properties { get; } = new(StringComparer.Ordinal); public Dictionary<string, JsonElement> Properties { get; } = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Gets the callback URLs associated with the application. /// Gets the redirect URIs associated with the application.
/// </summary> /// </summary>
public HashSet<Uri> RedirectUris { get; } = new(); public HashSet<Uri> RedirectUris { get; } = new();

20
src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs

@ -115,20 +115,20 @@ public interface IOpenIddictApplicationManager
/// <summary> /// <summary>
/// Retrieves all the applications associated with the specified post_logout_redirect_uri. /// Retrieves all the applications associated with the specified post_logout_redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The post_logout_redirect_uri associated with the applications.</param> /// <param name="uri">The post_logout_redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The client applications corresponding to the specified post_logout_redirect_uri.</returns> /// <returns>The client applications corresponding to the specified post_logout_redirect_uri.</returns>
IAsyncEnumerable<object> FindByPostLogoutRedirectUriAsync( IAsyncEnumerable<object> FindByPostLogoutRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken = default); [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Retrieves all the applications associated with the specified redirect_uri. /// Retrieves all the applications associated with the specified redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The redirect_uri associated with the applications.</param> /// <param name="uri">The redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The client applications corresponding to the specified redirect_uri.</returns> /// <returns>The client applications corresponding to the specified redirect_uri.</returns>
IAsyncEnumerable<object> FindByRedirectUriAsync( IAsyncEnumerable<object> FindByRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken = default); [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Executes the specified query and returns the first element. /// Executes the specified query and returns the first element.
@ -264,7 +264,7 @@ public interface IOpenIddictApplicationManager
ValueTask<ImmutableArray<string>> GetPermissionsAsync(object application, CancellationToken cancellationToken = default); ValueTask<ImmutableArray<string>> GetPermissionsAsync(object application, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Retrieves the logout callback addresses associated with an application. /// Retrieves the post-logout redirect URIs associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
@ -286,7 +286,7 @@ public interface IOpenIddictApplicationManager
ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(object application, CancellationToken cancellationToken = default); ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(object application, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Retrieves the callback addresses associated with an application. /// Retrieves the redirect URIs associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
@ -457,7 +457,7 @@ public interface IOpenIddictApplicationManager
/// Validates the post_logout_redirect_uri to ensure it's associated with an application. /// Validates the post_logout_redirect_uri to ensure it's associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="address">The address that should be compared to one of the post_logout_redirect_uri stored in the database.</param> /// <param name="uri">The URI that should be compared to one of the post_logout_redirect_uri stored in the database.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <remarks>Note: if no client_id parameter is specified in logout requests, this method may not be called.</remarks> /// <remarks>Note: if no client_id parameter is specified in logout requests, this method may not be called.</remarks>
/// <returns> /// <returns>
@ -465,18 +465,18 @@ public interface IOpenIddictApplicationManager
/// whose result returns a boolean indicating whether the post_logout_redirect_uri was valid. /// whose result returns a boolean indicating whether the post_logout_redirect_uri was valid.
/// </returns> /// </returns>
ValueTask<bool> ValidatePostLogoutRedirectUriAsync(object application, ValueTask<bool> ValidatePostLogoutRedirectUriAsync(object application,
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken = default); [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// Validates the redirect_uri to ensure it's associated with an application. /// Validates the redirect_uri to ensure it's associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="address">The address that should be compared to one of the redirect_uri stored in the database.</param> /// <param name="uri">The URI that should be compared to one of the redirect_uri stored in the database.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation, /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation,
/// whose result returns a boolean indicating whether the redirect_uri was valid. /// whose result returns a boolean indicating whether the redirect_uri was valid.
/// </returns> /// </returns>
ValueTask<bool> ValidateRedirectUriAsync(object application, ValueTask<bool> ValidateRedirectUriAsync(object application,
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken = default); [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken = default);
} }

74
src/OpenIddict.Abstractions/OpenIddictResources.resx

@ -193,7 +193,7 @@ Alternatively, you can disable the built-in database-based server features by en
<value>A token cannot be created from a null principal.</value> <value>A token cannot be created from a null principal.</value>
</data> </data>
<data name="ID0023" xml:space="preserve"> <data name="ID0023" xml:space="preserve">
<value>The issuer must be a non-null, non-empty absolute URL.</value> <value>The issuer must be a non-null, non-empty absolute URI.</value>
</data> </data>
<data name="ID0024" xml:space="preserve"> <data name="ID0024" xml:space="preserve">
<value>A sign-out response cannot be returned from this endpoint.</value> <value>A sign-out response cannot be returned from this endpoint.</value>
@ -367,7 +367,7 @@ Consider using 'options.AddSigningCredentials(SigningCredentials)' instead.</val
<value>The grant type cannot be null or empty.</value> <value>The grant type cannot be null or empty.</value>
</data> </data>
<data name="ID0072" xml:space="preserve"> <data name="ID0072" xml:space="preserve">
<value>Endpoint addresses must be valid URLs.</value> <value>Endpoint URIs must be valid URIs.</value>
</data> </data>
<data name="ID0073" xml:space="preserve"> <data name="ID0073" xml:space="preserve">
<value>Claims cannot be null or empty.</value> <value>Claims cannot be null or empty.</value>
@ -394,7 +394,7 @@ Consider using 'options.AddSigningCredentials(SigningCredentials)' instead.</val
<value>The verification endpoint must be enabled to use the device flow.</value> <value>The verification endpoint must be enabled to use the device flow.</value>
</data> </data>
<data name="ID0081" xml:space="preserve"> <data name="ID0081" xml:space="preserve">
<value>Endpoint addresses cannot start with '{0}'.</value> <value>Endpoint URIs cannot start with '{0}'.</value>
</data> </data>
<data name="ID0082" xml:space="preserve"> <data name="ID0082" xml:space="preserve">
<value>Dependency injection support must be enabled in Quartz.NET when using the OpenIddict integration. <value>Dependency injection support must be enabled in Quartz.NET when using the OpenIddict integration.
@ -550,7 +550,7 @@ To register the server services, use 'services.AddOpenIddict().AddServer()'.</va
<value>The base URI or request URI cannot be retrieved from the request context or are now valid absolute URIs.</value> <value>The base URI or request URI cannot be retrieved from the request context or are now valid absolute URIs.</value>
</data> </data>
<data name="ID0128" xml:space="preserve"> <data name="ID0128" xml:space="preserve">
<value>An OAuth 2.0/OpenID Connect server configuration or an issuer address must be registered. <value>An OAuth 2.0/OpenID Connect server configuration or an issuer URI must be registered.
To use a local OpenIddict server, reference the 'OpenIddict.Validation.ServerIntegration' package and call 'services.AddOpenIddict().AddValidation().UseLocalServer()' to import the server settings. To use a local OpenIddict server, reference the 'OpenIddict.Validation.ServerIntegration' package and call 'services.AddOpenIddict().AddValidation().UseLocalServer()' to import the server settings.
To use a remote server, reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' and 'services.AddOpenIddict().AddValidation().SetIssuer()' to use server discovery. To use a remote server, reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' and 'services.AddOpenIddict().AddValidation().SetIssuer()' to use server discovery.
Alternatively, you can register a static server configuration by calling 'services.AddOpenIddict().AddValidation().SetConfiguration()'.</value> Alternatively, you can register a static server configuration by calling 'services.AddOpenIddict().AddValidation().SetConfiguration()'.</value>
@ -560,7 +560,7 @@ Alternatively, you can register a static server configuration by calling 'servic
Reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' to register the default System.Net.Http-based integration.</value> Reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' to register the default System.Net.Http-based integration.</value>
</data> </data>
<data name="ID0130" xml:space="preserve"> <data name="ID0130" xml:space="preserve">
<value>The issuer or the metadata address must be set when using introspection.</value> <value>The issuer or the configuration endpoint URI must be set when using introspection.</value>
</data> </data>
<data name="ID0131" xml:space="preserve"> <data name="ID0131" xml:space="preserve">
<value>The client identifier cannot be null or empty when using introspection.</value> <value>The client identifier cannot be null or empty when using introspection.</value>
@ -579,10 +579,10 @@ Reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.A
Reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' to register the default System.Net.Http-based integration.</value> Reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' to register the default System.Net.Http-based integration.</value>
</data> </data>
<data name="ID0136" xml:space="preserve"> <data name="ID0136" xml:space="preserve">
<value>The authority must be provided and must be an absolute URL.</value> <value>The issuer must be provided and must be an absolute URI.</value>
</data> </data>
<data name="ID0137" xml:space="preserve"> <data name="ID0137" xml:space="preserve">
<value>The authority cannot contain a fragment or a query string.</value> <value>The issuer cannot contain a fragment or a query string.</value>
</data> </data>
<data name="ID0138" xml:space="preserve"> <data name="ID0138" xml:space="preserve">
<value>The event handler of type '{0}' couldn't be resolved. <value>The event handler of type '{0}' couldn't be resolved.
@ -603,10 +603,10 @@ To register the OpenIddict core services, reference the 'OpenIddict.Core' packag
To register the OpenIddict core services, reference the 'OpenIddict.Core' package and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.</value> To register the OpenIddict core services, reference the 'OpenIddict.Core' package and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.</value>
</data> </data>
<data name="ID0143" xml:space="preserve"> <data name="ID0143" xml:space="preserve">
<value>The address cannot be null or empty.</value> <value>The URI cannot be null or empty.</value>
</data> </data>
<data name="ID0144" xml:space="preserve"> <data name="ID0144" xml:space="preserve">
<value>The address must be a valid absolute URI.</value> <value>The URI must be a valid absolute URI.</value>
</data> </data>
<data name="ID0145" xml:space="preserve"> <data name="ID0145" xml:space="preserve">
<value>The server configuration couldn't be retrieved.</value> <value>The server configuration couldn't be retrieved.</value>
@ -857,10 +857,10 @@ To register the validation services, use 'services.AddOpenIddict().AddValidation
<value>The requirement name cannot be null or empty.</value> <value>The requirement name cannot be null or empty.</value>
</data> </data>
<data name="ID0213" xml:space="preserve"> <data name="ID0213" xml:space="preserve">
<value>Callback URLs cannot be null or empty.</value> <value>Callback URIs cannot be null or empty.</value>
</data> </data>
<data name="ID0214" xml:space="preserve"> <data name="ID0214" xml:space="preserve">
<value>Callback URLs must be valid absolute URLs.</value> <value>Callback URIs must be valid absolute URIs.</value>
</data> </data>
<data name="ID0215" xml:space="preserve"> <data name="ID0215" xml:space="preserve">
<value>One or more validation error(s) occurred while trying to update an existing application:</value> <value>One or more validation error(s) occurred while trying to update an existing application:</value>
@ -1111,7 +1111,7 @@ To register the OpenIddict core services, reference the 'OpenIddict.Core' packag
<value>The context type associated with the specified descriptor doesn't match the context type of this builder.</value> <value>The context type associated with the specified descriptor doesn't match the context type of this builder.</value>
</data> </data>
<data name="ID0285" xml:space="preserve"> <data name="ID0285" xml:space="preserve">
<value>Endpoint addresses must be unique across endpoints.</value> <value>Endpoint URIs must be unique across endpoints.</value>
</data> </data>
<data name="ID0286" xml:space="preserve"> <data name="ID0286" xml:space="preserve">
<value>The specified principal doesn't contain a valid claims-based identity.</value> <value>The specified principal doesn't contain a valid claims-based identity.</value>
@ -1180,7 +1180,7 @@ To apply redirection responses, create a class implementing 'IOpenIddictClientHa
<value>No issuer was specified in the challenge properties. When multiple clients are registered, an issuer (or a provider name) must be specified in the challenge properties.</value> <value>No issuer was specified in the challenge properties. When multiple clients are registered, an issuer (or a provider name) must be specified in the challenge properties.</value>
</data> </data>
<data name="ID0306" xml:space="preserve"> <data name="ID0306" xml:space="preserve">
<value>The specified issuer is not a valid or absolute URL.</value> <value>The specified issuer is not a valid or absolute URI.</value>
</data> </data>
<data name="ID0307" xml:space="preserve"> <data name="ID0307" xml:space="preserve">
<value>The issuer extracted from the server configuration metadata doesn't match the expected value.</value> <value>The issuer extracted from the server configuration metadata doesn't match the expected value.</value>
@ -1484,7 +1484,7 @@ Consider registering a certificate using 'services.AddOpenIddict().AddClient().A
<value>The mandatory '{0}' parameter is missing.</value> <value>The mandatory '{0}' parameter is missing.</value>
</data> </data>
<data name="ID2030" xml:space="preserve"> <data name="ID2030" xml:space="preserve">
<value>The '{0}' parameter must be a valid absolute URL.</value> <value>The '{0}' parameter must be a valid absolute URI.</value>
</data> </data>
<data name="ID2031" xml:space="preserve"> <data name="ID2031" xml:space="preserve">
<value>The '{0}' parameter must not include a fragment.</value> <value>The '{0}' parameter must not include a fragment.</value>
@ -1577,10 +1577,10 @@ Consider registering a certificate using 'services.AddOpenIddict().AddClient().A
<value>A scope with the same name already exists.</value> <value>A scope with the same name already exists.</value>
</data> </data>
<data name="ID2061" xml:space="preserve"> <data name="ID2061" xml:space="preserve">
<value>Callback URLs cannot be null or empty.</value> <value>Callback URIs cannot be null or empty.</value>
</data> </data>
<data name="ID2062" xml:space="preserve"> <data name="ID2062" xml:space="preserve">
<value>Callback URLs must be valid absolute URLs.</value> <value>Callback URIs must be valid absolute URIs.</value>
</data> </data>
<data name="ID2063" xml:space="preserve"> <data name="ID2063" xml:space="preserve">
<value>This client application is not allowed to use the token endpoint.</value> <value>This client application is not allowed to use the token endpoint.</value>
@ -1610,7 +1610,7 @@ Consider registering a certificate using 'services.AddOpenIddict().AddClient().A
<value>The specified refresh token cannot be used by this client application.</value> <value>The specified refresh token cannot be used by this client application.</value>
</data> </data>
<data name="ID2072" xml:space="preserve"> <data name="ID2072" xml:space="preserve">
<value>The specified '{0}' parameter doesn't match the client redirection address the authorization code was initially sent to.</value> <value>The specified '{0}' parameter doesn't match the client redirection URI the authorization code was initially sent to.</value>
</data> </data>
<data name="ID2073" xml:space="preserve"> <data name="ID2073" xml:space="preserve">
<value>The '{0}' parameter cannot be used when no '{1}' was specified in the authorization request.</value> <value>The '{0}' parameter cannot be used when no '{1}' was specified in the authorization request.</value>
@ -1694,7 +1694,7 @@ Consider registering a certificate using 'services.AddOpenIddict().AddClient().A
<value>No JWKS endpoint could be found in the server configuration.</value> <value>No JWKS endpoint could be found in the server configuration.</value>
</data> </data>
<data name="ID2100" xml:space="preserve"> <data name="ID2100" xml:space="preserve">
<value>A server configuration containing an invalid '{0}' URL was returned.</value> <value>A server configuration containing an invalid '{0}' URI was returned.</value>
</data> </data>
<data name="ID2102" xml:space="preserve"> <data name="ID2102" xml:space="preserve">
<value>The JWKS document didn't contain a valid '{0}' node with at least one key.</value> <value>The JWKS document didn't contain a valid '{0}' node with at least one key.</value>
@ -1736,7 +1736,7 @@ Consider registering a certificate using 'services.AddOpenIddict().AddClient().A
<value>A client secret cannot be associated with a public application.</value> <value>A client secret cannot be associated with a public application.</value>
</data> </data>
<data name="ID2115" xml:space="preserve"> <data name="ID2115" xml:space="preserve">
<value>Callback URLs cannot contain a fragment.</value> <value>Callback URIs cannot contain a fragment.</value>
</data> </data>
<data name="ID2116" xml:space="preserve"> <data name="ID2116" xml:space="preserve">
<value>The authorization type cannot be null or empty.</value> <value>The authorization type cannot be null or empty.</value>
@ -1793,7 +1793,7 @@ Consider registering a certificate using 'services.AddOpenIddict().AddClient().A
<value>The '{0}' claim returned in the specified userinfo response/token doesn't match the expected value.</value> <value>The '{0}' claim returned in the specified userinfo response/token doesn't match the expected value.</value>
</data> </data>
<data name="ID2134" xml:space="preserve"> <data name="ID2134" xml:space="preserve">
<value>Callback URLs cannot contain an "{0}" parameter.</value> <value>Callback URIs cannot contain an "{0}" parameter.</value>
</data> </data>
<data name="ID2135" xml:space="preserve"> <data name="ID2135" xml:space="preserve">
<value>The '{0}' parameter must not include a '{1}' component.</value> <value>The '{0}' parameter must not include a '{1}' component.</value>
@ -1805,7 +1805,7 @@ Consider registering a certificate using 'services.AddOpenIddict().AddClient().A
<value>An invalid JSON response was returned by the remote HTTP server.</value> <value>An invalid JSON response was returned by the remote HTTP server.</value>
</data> </data>
<data name="ID2138" xml:space="preserve"> <data name="ID2138" xml:space="preserve">
<value>The current address doesn't match the address of the redirection endpoint selected during the initial authorization request.</value> <value>The current URI doesn't match the URI of the redirection endpoint selected during the initial authorization request.</value>
</data> </data>
<data name="ID2139" xml:space="preserve"> <data name="ID2139" xml:space="preserve">
<value>The specified state token has already been redeemed.</value> <value>The specified state token has already been redeemed.</value>
@ -1925,7 +1925,7 @@ Consider registering a certificate using 'services.AddOpenIddict().AddClient().A
<value>EC-based keys should have a non-null OID raw value or friendly name.</value> <value>EC-based keys should have a non-null OID raw value or friendly name.</value>
</data> </data>
<data name="ID4013" xml:space="preserve"> <data name="ID4013" xml:space="preserve">
<value>The issuer should be a valid absolute URL at this point.</value> <value>The issuer should be a valid absolute URI at this point.</value>
</data> </data>
<data name="ID4014" xml:space="preserve"> <data name="ID4014" xml:space="preserve">
<value>The username shouldn't be null or empty at this point.</value> <value>The username shouldn't be null or empty at this point.</value>
@ -1998,10 +1998,10 @@ The principal used to create the token contained the following claims: {Claims}.
<value>The authorization request was rejected because the mandatory '{Parameter}' parameter was missing.</value> <value>The authorization request was rejected because the mandatory '{Parameter}' parameter was missing.</value>
</data> </data>
<data name="ID6034" xml:space="preserve"> <data name="ID6034" xml:space="preserve">
<value>The authorization request was rejected because the '{Parameter}' parameter wasn't a valid absolute URL: {RedirectUri}.</value> <value>The authorization request was rejected because the '{Parameter}' parameter wasn't a valid absolute URI: {RedirectUri}.</value>
</data> </data>
<data name="ID6035" xml:space="preserve"> <data name="ID6035" xml:space="preserve">
<value>The authorization request was rejected because the '{Parameter}' contained a URL fragment: {RedirectUri}.</value> <value>The authorization request was rejected because the '{Parameter}' contained a URI fragment: {RedirectUri}.</value>
</data> </data>
<data name="ID6036" xml:space="preserve"> <data name="ID6036" xml:space="preserve">
<value>The authorization request was rejected because the '{ResponseType}' response type is not supported.</value> <value>The authorization request was rejected because the '{ResponseType}' response type is not supported.</value>
@ -2055,7 +2055,7 @@ The principal used to create the token contained the following claims: {Claims}.
<value>The authorization request was rejected because the application '{ClientId}' was not allowed to use the '{Scope}' scope.</value> <value>The authorization request was rejected because the application '{ClientId}' was not allowed to use the '{Scope}' scope.</value>
</data> </data>
<data name="ID6053" xml:space="preserve"> <data name="ID6053" xml:space="preserve">
<value>The request address matched a server endpoint: {Endpoint}.</value> <value>The request URI matched a server endpoint: {Endpoint}.</value>
</data> </data>
<data name="ID6054" xml:space="preserve"> <data name="ID6054" xml:space="preserve">
<value>The device request was successfully extracted: {Request}.</value> <value>The device request was successfully extracted: {Request}.</value>
@ -2274,10 +2274,10 @@ The principal used to create the token contained the following claims: {Claims}.
<value>The logout request was successfully validated.</value> <value>The logout request was successfully validated.</value>
</data> </data>
<data name="ID6126" xml:space="preserve"> <data name="ID6126" xml:space="preserve">
<value>The logout request was rejected because the '{Parameter}' parameter wasn't a valid absolute URL: {PostLogoutRedirectUri}.</value> <value>The logout request was rejected because the '{Parameter}' parameter wasn't a valid absolute URI: {PostLogoutRedirectUri}.</value>
</data> </data>
<data name="ID6127" xml:space="preserve"> <data name="ID6127" xml:space="preserve">
<value>The logout request was rejected because the '{Parameter}' contained a URL fragment: {PostLogoutRedirectUri}.</value> <value>The logout request was rejected because the '{Parameter}' contained a URI fragment: {PostLogoutRedirectUri}.</value>
</data> </data>
<data name="ID6128" xml:space="preserve"> <data name="ID6128" xml:space="preserve">
<value>The logout request was rejected because the specified post_logout_redirect_uri was invalid: {PostLogoutRedirectUri}.</value> <value>The logout request was rejected because the specified post_logout_redirect_uri was invalid: {PostLogoutRedirectUri}.</value>
@ -2455,34 +2455,34 @@ This may indicate that the hashed entry is corrupted or malformed.</value>
<value>An unsupported {StatusCode} response was returned by the remote HTTP server: {ContentType} {Payload}.</value> <value>An unsupported {StatusCode} response was returned by the remote HTTP server: {ContentType} {Payload}.</value>
</data> </data>
<data name="ID6186" xml:space="preserve"> <data name="ID6186" xml:space="preserve">
<value>The configuration request was successfully sent to {Address}: {Request}.</value> <value>The configuration request was successfully sent to {Uri}: {Request}.</value>
</data> </data>
<data name="ID6187" xml:space="preserve"> <data name="ID6187" xml:space="preserve">
<value>The configuration response returned by {Address} was successfully extracted: {Response}.</value> <value>The configuration response returned by {Uri} was successfully extracted: {Response}.</value>
</data> </data>
<data name="ID6188" xml:space="preserve"> <data name="ID6188" xml:space="preserve">
<value>The cryptography request was successfully sent to {Address}: {Request}.</value> <value>The cryptography request was successfully sent to {Uri}: {Request}.</value>
</data> </data>
<data name="ID6189" xml:space="preserve"> <data name="ID6189" xml:space="preserve">
<value>The cryptography response returned by {Address} was successfully extracted: {Response}.</value> <value>The cryptography response returned by {Uri} was successfully extracted: {Response}.</value>
</data> </data>
<data name="ID6190" xml:space="preserve"> <data name="ID6190" xml:space="preserve">
<value>The introspection request was successfully sent to {Address}: {Request}.</value> <value>The introspection request was successfully sent to {Uri}: {Request}.</value>
</data> </data>
<data name="ID6191" xml:space="preserve"> <data name="ID6191" xml:space="preserve">
<value>The introspection response returned by {Address} was successfully extracted: {Response}.</value> <value>The introspection response returned by {Uri} was successfully extracted: {Response}.</value>
</data> </data>
<data name="ID6192" xml:space="preserve"> <data name="ID6192" xml:space="preserve">
<value>The token request was successfully sent to {Address}: {Request}.</value> <value>The token request was successfully sent to {Uri}: {Request}.</value>
</data> </data>
<data name="ID6193" xml:space="preserve"> <data name="ID6193" xml:space="preserve">
<value>The token response returned by {Address} was successfully extracted: {Response}.</value> <value>The token response returned by {Uri} was successfully extracted: {Response}.</value>
</data> </data>
<data name="ID6194" xml:space="preserve"> <data name="ID6194" xml:space="preserve">
<value>The userinfo request was successfully sent to {Address}: {Request}.</value> <value>The userinfo request was successfully sent to {Uri}: {Request}.</value>
</data> </data>
<data name="ID6195" xml:space="preserve"> <data name="ID6195" xml:space="preserve">
<value>The userinfo response returned by {Address} was successfully extracted: {Response}.</value> <value>The userinfo response returned by {Uri} was successfully extracted: {Response}.</value>
</data> </data>
<data name="ID6196" xml:space="preserve"> <data name="ID6196" xml:space="preserve">
<value>The logout request was rejected because the client application was not found: '{ClientId}'.</value> <value>The logout request was rejected because the client application was not found: '{ClientId}'.</value>

14
src/OpenIddict.Abstractions/Primitives/OpenIddictConfiguration.cs

@ -17,7 +17,7 @@ namespace OpenIddict.Abstractions;
public sealed class OpenIddictConfiguration public sealed class OpenIddictConfiguration
{ {
/// <summary> /// <summary>
/// Gets or sets the address of the authorization endpoint. /// Gets or sets the URI of the authorization endpoint.
/// </summary> /// </summary>
public Uri? AuthorizationEndpoint { get; set; } public Uri? AuthorizationEndpoint { get; set; }
@ -32,7 +32,7 @@ public sealed class OpenIddictConfiguration
public HashSet<string> CodeChallengeMethodsSupported { get; } = new(StringComparer.Ordinal); public HashSet<string> CodeChallengeMethodsSupported { get; } = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Gets or sets the address of the end session endpoint. /// Gets or sets the URI of the end session endpoint.
/// </summary> /// </summary>
public Uri? EndSessionEndpoint { get; set; } public Uri? EndSessionEndpoint { get; set; }
@ -42,7 +42,7 @@ public sealed class OpenIddictConfiguration
public HashSet<string> GrantTypesSupported { get; } = new(StringComparer.Ordinal); public HashSet<string> GrantTypesSupported { get; } = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Gets or sets the address of the introspection endpoint. /// Gets or sets the URI of the introspection endpoint.
/// </summary> /// </summary>
public Uri? IntrospectionEndpoint { get; set; } public Uri? IntrospectionEndpoint { get; set; }
@ -52,7 +52,7 @@ public sealed class OpenIddictConfiguration
public HashSet<string> IntrospectionEndpointAuthMethodsSupported { get; } = new(StringComparer.Ordinal); public HashSet<string> IntrospectionEndpointAuthMethodsSupported { get; } = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Gets or sets the address of the issuer. /// Gets or sets the URI of the issuer.
/// </summary> /// </summary>
public Uri? Issuer { get; set; } public Uri? Issuer { get; set; }
@ -62,7 +62,7 @@ public sealed class OpenIddictConfiguration
public JsonWebKeySet? JsonWebKeySet { get; set; } public JsonWebKeySet? JsonWebKeySet { get; set; }
/// <summary> /// <summary>
/// Gets or sets the address of the JWKS endpoint. /// Gets or sets the URI of the JWKS endpoint.
/// </summary> /// </summary>
public Uri? JwksUri { get; set; } public Uri? JwksUri { get; set; }
@ -92,7 +92,7 @@ public sealed class OpenIddictConfiguration
public List<SecurityKey> SigningKeys { get; } = new(); public List<SecurityKey> SigningKeys { get; } = new();
/// <summary> /// <summary>
/// Gets or sets the address of the token endpoint. /// Gets or sets the URI of the token endpoint.
/// </summary> /// </summary>
public Uri? TokenEndpoint { get; set; } public Uri? TokenEndpoint { get; set; }
@ -102,7 +102,7 @@ public sealed class OpenIddictConfiguration
public HashSet<string> TokenEndpointAuthMethodsSupported { get; } = new(StringComparer.Ordinal); public HashSet<string> TokenEndpointAuthMethodsSupported { get; } = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Gets or sets the address of the userinfo endpoint. /// Gets or sets the URI of the userinfo endpoint.
/// </summary> /// </summary>
public Uri? UserinfoEndpoint { get; set; } public Uri? UserinfoEndpoint { get; set; }
} }

26
src/OpenIddict.Abstractions/Stores/IOpenIddictApplicationStore.cs

@ -80,20 +80,20 @@ public interface IOpenIddictApplicationStore<TApplication> where TApplication :
/// <summary> /// <summary>
/// Retrieves all the applications associated with the specified post_logout_redirect_uri. /// Retrieves all the applications associated with the specified post_logout_redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The post_logout_redirect_uri associated with the applications.</param> /// <param name="uri">The post_logout_redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The client applications corresponding to the specified post_logout_redirect_uri.</returns> /// <returns>The client applications corresponding to the specified post_logout_redirect_uri.</returns>
IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync( IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken); [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Retrieves all the applications associated with the specified redirect_uri. /// Retrieves all the applications associated with the specified redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The redirect_uri associated with the applications.</param> /// <param name="uri">The redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The client applications corresponding to the specified redirect_uri.</returns> /// <returns>The client applications corresponding to the specified redirect_uri.</returns>
IAsyncEnumerable<TApplication> FindByRedirectUriAsync( IAsyncEnumerable<TApplication> FindByRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken); [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Executes the specified query and returns the first element. /// Executes the specified query and returns the first element.
@ -202,7 +202,7 @@ public interface IOpenIddictApplicationStore<TApplication> where TApplication :
ValueTask<ImmutableArray<string>> GetPermissionsAsync(TApplication application, CancellationToken cancellationToken); ValueTask<ImmutableArray<string>> GetPermissionsAsync(TApplication application, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Retrieves the logout callback addresses associated with an application. /// Retrieves the post-logout redirect URIs associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
@ -224,7 +224,7 @@ public interface IOpenIddictApplicationStore<TApplication> where TApplication :
ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TApplication application, CancellationToken cancellationToken); ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TApplication application, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Retrieves the callback addresses associated with an application. /// Retrieves the redirect URIs associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
@ -344,14 +344,13 @@ public interface IOpenIddictApplicationStore<TApplication> where TApplication :
ValueTask SetPermissionsAsync(TApplication application, ImmutableArray<string> permissions, CancellationToken cancellationToken); ValueTask SetPermissionsAsync(TApplication application, ImmutableArray<string> permissions, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the logout callback addresses associated with an application. /// Sets the post-logout redirect URIs associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="addresses">The logout callback addresses associated with the application </param> /// <param name="uris">The post-logout redirect URIs associated with the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
ValueTask SetPostLogoutRedirectUrisAsync(TApplication application, ValueTask SetPostLogoutRedirectUrisAsync(TApplication application, ImmutableArray<string> uris, CancellationToken cancellationToken);
ImmutableArray<string> addresses, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the additional properties associated with an application. /// Sets the additional properties associated with an application.
@ -364,14 +363,13 @@ public interface IOpenIddictApplicationStore<TApplication> where TApplication :
ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken); ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the callback addresses associated with an application. /// Sets the redirect URIs associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="addresses">The callback addresses associated with the application </param> /// <param name="uris">The redirect URIs associated with the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns> /// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
ValueTask SetRedirectUrisAsync(TApplication application, ValueTask SetRedirectUrisAsync(TApplication application, ImmutableArray<string> uris, CancellationToken cancellationToken);
ImmutableArray<string> addresses, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the requirements associated with an application. /// Sets the requirements associated with an application.

4
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs

@ -172,8 +172,8 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Op
properties.ExpiresUtc = principal.GetExpirationDate(); properties.ExpiresUtc = principal.GetExpirationDate();
properties.IssuedUtc = principal.GetCreationDate(); properties.IssuedUtc = principal.GetCreationDate();
// Restore the return URL using the "target_link_uri" that was stored // Restore the target link URI that was stored in the state
// in the state token when the challenge operation started, if available. // token when the challenge operation started, if available.
properties.RedirectUri = context.StateTokenPrincipal?.GetClaim(Claims.TargetLinkUri); properties.RedirectUri = context.StateTokenPrincipal?.GetClaim(Claims.TargetLinkUri);
List<AuthenticationToken>? tokens = null; List<AuthenticationToken>? tokens = null;

6
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs

@ -95,7 +95,7 @@ public static partial class OpenIddictClientAspNetCoreHandlers
// sent by the HTTP client) is not desirable as it would affect all requests, including requests // sent by the HTTP client) is not desirable as it would affect all requests, including requests
// that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily // that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily
// used to build an absolute base URI and a request URI that will be used to determine whether the // used to build an absolute base URI and a request URI that will be used to determine whether the
// received request matches one of the addresses assigned to an OpenIddict endpoint. If the request // received request matches one of the URIs assigned to an OpenIddict endpoint. If the request
// is later handled by OpenIddict, an additional check will be made to require the Host header. // is later handled by OpenIddict, an additional check will be made to require the Host header.
(context.BaseUri, context.RequestUri) = request.Host switch (context.BaseUri, context.RequestUri) = request.Host switch
@ -464,7 +464,7 @@ public static partial class OpenIddictClientAspNetCoreHandlers
context.ProviderName = provider; context.ProviderName = provider;
} }
// If a return URL was specified, use it as the target_link_uri claim. // If a target link URI was specified, attach it to the context.
if (!string.IsNullOrEmpty(properties.RedirectUri)) if (!string.IsNullOrEmpty(properties.RedirectUri))
{ {
context.TargetLinkUri = properties.RedirectUri; context.TargetLinkUri = properties.RedirectUri;
@ -697,7 +697,7 @@ public static partial class OpenIddictClientAspNetCoreHandlers
context.ProviderName = provider; context.ProviderName = provider;
} }
// If a return URL was specified, use it as the target_link_uri claim. // If a target link URI was specified, attach it to the context.
if (!string.IsNullOrEmpty(properties.RedirectUri)) if (!string.IsNullOrEmpty(properties.RedirectUri))
{ {
context.TargetLinkUri = properties.RedirectUri; context.TargetLinkUri = properties.RedirectUri;

4
src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs

@ -187,8 +187,8 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<OpenIddi
properties.ExpiresUtc = principal.GetExpirationDate(); properties.ExpiresUtc = principal.GetExpirationDate();
properties.IssuedUtc = principal.GetCreationDate(); properties.IssuedUtc = principal.GetCreationDate();
// Restore the return URL using the "target_link_uri" that was stored // Restore the target link URI that was stored in the state
// in the state token when the challenge operation started, if available. // token when the challenge operation started, if available.
properties.RedirectUri = context.StateTokenPrincipal?.GetClaim(Claims.TargetLinkUri); properties.RedirectUri = context.StateTokenPrincipal?.GetClaim(Claims.TargetLinkUri);
// Attach the tokens to allow any OWIN component (e.g a controller) // Attach the tokens to allow any OWIN component (e.g a controller)

6
src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs

@ -90,7 +90,7 @@ public static partial class OpenIddictClientOwinHandlers
// sent by the HTTP client) is not desirable as it would affect all requests, including requests // sent by the HTTP client) is not desirable as it would affect all requests, including requests
// that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily // that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily
// used to build an absolute base URI and a request URI that will be used to determine whether the // used to build an absolute base URI and a request URI that will be used to determine whether the
// received request matches one of the addresses assigned to an OpenIddict endpoint. If the request // received request matches one of the URIs assigned to an OpenIddict endpoint. If the request
// is later handled by OpenIddict, an additional check will be made to require the Host header. // is later handled by OpenIddict, an additional check will be made to require the Host header.
(context.BaseUri, context.RequestUri) = request.Host switch (context.BaseUri, context.RequestUri) = request.Host switch
@ -477,7 +477,7 @@ public static partial class OpenIddictClientOwinHandlers
context.ProviderName = provider; context.ProviderName = provider;
} }
// If a return URL was specified, use it as the target_link_uri claim. // If a target link URI was specified, attach it to the context.
if (!string.IsNullOrEmpty(properties.RedirectUri)) if (!string.IsNullOrEmpty(properties.RedirectUri))
{ {
context.TargetLinkUri = properties.RedirectUri; context.TargetLinkUri = properties.RedirectUri;
@ -736,7 +736,7 @@ public static partial class OpenIddictClientOwinHandlers
context.ProviderName = provider; context.ProviderName = provider;
} }
// If a return URL was specified, use it as the target_link_uri claim. // If a target link URI was specified, attach it to the context.
if (!string.IsNullOrEmpty(properties.RedirectUri)) if (!string.IsNullOrEmpty(properties.RedirectUri))
{ {
context.TargetLinkUri = properties.RedirectUri; context.TargetLinkUri = properties.RedirectUri;

2
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpExtensions.cs

@ -37,7 +37,7 @@ public static class OpenIddictClientSystemNetHttpExtensions
builder.Services.TryAdd(OpenIddictClientSystemNetHttpHandlers.DefaultHandlers.Select(descriptor => descriptor.ServiceDescriptor)); builder.Services.TryAdd(OpenIddictClientSystemNetHttpHandlers.DefaultHandlers.Select(descriptor => descriptor.ServiceDescriptor));
// Register the built-in filters used by the default OpenIddict System.Net.Http event handlers. // Register the built-in filters used by the default OpenIddict System.Net.Http event handlers.
builder.Services.TryAddSingleton<RequireHttpMetadataAddress>(); builder.Services.TryAddSingleton<RequireHttpMetadataUri>();
// Note: TryAddEnumerable() is used here to ensure the initializers are registered only once. // Note: TryAddEnumerable() is used here to ensure the initializers are registered only once.
builder.Services.TryAddEnumerable(new[] builder.Services.TryAddEnumerable(new[]

8
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlerFilters.cs

@ -12,9 +12,9 @@ namespace OpenIddict.Client.SystemNetHttp;
public static class OpenIddictClientSystemNetHttpHandlerFilters public static class OpenIddictClientSystemNetHttpHandlerFilters
{ {
/// <summary> /// <summary>
/// Represents a filter that excludes the associated handlers if the metadata address of the issuer is not available. /// Represents a filter that excludes the associated handlers if the metadata URI of the issuer is not available.
/// </summary> /// </summary>
public sealed class RequireHttpMetadataAddress : IOpenIddictClientHandlerFilter<BaseExternalContext> public sealed class RequireHttpMetadataUri : IOpenIddictClientHandlerFilter<BaseExternalContext>
{ {
public ValueTask<bool> IsActiveAsync(BaseExternalContext context) public ValueTask<bool> IsActiveAsync(BaseExternalContext context)
{ {
@ -24,8 +24,8 @@ public static class OpenIddictClientSystemNetHttpHandlerFilters
} }
return new( return new(
string.Equals(context.Address?.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) || string.Equals(context.RemoteUri?.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.Address?.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)); string.Equals(context.RemoteUri?.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase));
} }
} }
} }

2
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs

@ -46,7 +46,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareTokenRequestContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareTokenRequestContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachBasicAuthenticationCredentials>() .UseSingletonHandler<AttachBasicAuthenticationCredentials>()
.SetOrder(AttachFormParameters<PrepareTokenRequestContext>.Descriptor.Order - 500) .SetOrder(AttachFormParameters<PrepareTokenRequestContext>.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)

4
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs

@ -47,7 +47,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachBearerAccessToken>() .UseSingletonHandler<AttachBearerAccessToken>()
.SetOrder(AttachQueryStringParameters<PrepareUserinfoRequestContext>.Descriptor.Order - 500) .SetOrder(AttachQueryStringParameters<PrepareUserinfoRequestContext>.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -88,7 +88,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<ExtractUserinfoResponseContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<ExtractUserinfoResponseContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<ExtractUserinfoTokenHttpResponse>() .UseSingletonHandler<ExtractUserinfoTokenHttpResponse>()
.SetOrder(ExtractJsonHttpResponse<ExtractUserinfoResponseContext>.Descriptor.Order - 500) .SetOrder(ExtractJsonHttpResponse<ExtractUserinfoResponseContext>.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)

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

@ -36,7 +36,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<PrepareGetHttpRequest<TContext>>() .UseSingletonHandler<PrepareGetHttpRequest<TContext>>()
.SetOrder(int.MinValue + 100_000) .SetOrder(int.MinValue + 100_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -52,7 +52,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
// Store the HttpRequestMessage in the transaction properties. // Store the HttpRequestMessage in the transaction properties.
context.Transaction.SetProperty(typeof(HttpRequestMessage).FullName!, context.Transaction.SetProperty(typeof(HttpRequestMessage).FullName!,
new HttpRequestMessage(HttpMethod.Get, context.Address)); new HttpRequestMessage(HttpMethod.Get, context.RemoteUri));
return default; return default;
} }
@ -68,7 +68,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<PreparePostHttpRequest<TContext>>() .UseSingletonHandler<PreparePostHttpRequest<TContext>>()
.SetOrder(PrepareGetHttpRequest<TContext>.Descriptor.Order + 1_000) .SetOrder(PrepareGetHttpRequest<TContext>.Descriptor.Order + 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -84,7 +84,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
// Store the HttpRequestMessage in the transaction properties. // Store the HttpRequestMessage in the transaction properties.
context.Transaction.SetProperty(typeof(HttpRequestMessage).FullName!, context.Transaction.SetProperty(typeof(HttpRequestMessage).FullName!,
new HttpRequestMessage(HttpMethod.Post, context.Address)); new HttpRequestMessage(HttpMethod.Post, context.RemoteUri));
return default; return default;
} }
@ -101,7 +101,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachJsonAcceptHeaders<TContext>>() .UseSingletonHandler<AttachJsonAcceptHeaders<TContext>>()
.SetOrder(PreparePostHttpRequest<TContext>.Descriptor.Order + 1_000) .SetOrder(PreparePostHttpRequest<TContext>.Descriptor.Order + 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -146,7 +146,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachUserAgentHeader<TContext>>() .UseSingletonHandler<AttachUserAgentHeader<TContext>>()
.SetOrder(AttachJsonAcceptHeaders<TContext>.Descriptor.Order + 1_000) .SetOrder(AttachJsonAcceptHeaders<TContext>.Descriptor.Order + 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -195,7 +195,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachQueryStringParameters<TContext>>() .UseSingletonHandler<AttachQueryStringParameters<TContext>>()
.SetOrder(AttachFormParameters<TContext>.Descriptor.Order - 1_000) .SetOrder(AttachFormParameters<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -240,7 +240,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachFormParameters<TContext>>() .UseSingletonHandler<AttachFormParameters<TContext>>()
.SetOrder(int.MaxValue - 100_000) .SetOrder(int.MaxValue - 100_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -287,7 +287,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<SendHttpRequest<TContext>>() .UseSingletonHandler<SendHttpRequest<TContext>>()
.SetOrder(DecompressResponseContent<TContext>.Descriptor.Order - 1_000) .SetOrder(DecompressResponseContent<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -360,7 +360,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<DisposeHttpRequest<TContext>>() .UseSingletonHandler<DisposeHttpRequest<TContext>>()
.SetOrder(int.MaxValue - 100_000) .SetOrder(int.MaxValue - 100_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -398,7 +398,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<DecompressResponseContent<TContext>>() .UseSingletonHandler<DecompressResponseContent<TContext>>()
.SetOrder(ExtractJsonHttpResponse<TContext>.Descriptor.Order - 1_000) .SetOrder(ExtractJsonHttpResponse<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -537,7 +537,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<ExtractJsonHttpResponse<TContext>>() .UseSingletonHandler<ExtractJsonHttpResponse<TContext>>()
.SetOrder(ExtractWwwAuthenticateHeader<TContext>.Descriptor.Order - 1_000) .SetOrder(ExtractWwwAuthenticateHeader<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -605,7 +605,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<ExtractWwwAuthenticateHeader<TContext>>() .UseSingletonHandler<ExtractWwwAuthenticateHeader<TContext>>()
.SetOrder(ValidateHttpResponse<TContext>.Descriptor.Order - 1_000) .SetOrder(ValidateHttpResponse<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -688,7 +688,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<ValidateHttpResponse<TContext>>() .UseSingletonHandler<ValidateHttpResponse<TContext>>()
.SetOrder(DisposeHttpResponse<TContext>.Descriptor.Order - 50_000) .SetOrder(DisposeHttpResponse<TContext>.Descriptor.Order - 50_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -758,7 +758,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<DisposeHttpResponse<TContext>>() .UseSingletonHandler<DisposeHttpResponse<TContext>>()
.SetOrder(int.MaxValue - 100_000) .SetOrder(int.MaxValue - 100_000)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)

2
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs

@ -38,7 +38,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareTokenRequestContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareTokenRequestContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachNonStandardQueryStringParameters>() .UseSingletonHandler<AttachNonStandardQueryStringParameters>()
.SetOrder(AttachQueryStringParameters<PrepareTokenRequestContext>.Descriptor.Order + 500) .SetOrder(AttachQueryStringParameters<PrepareTokenRequestContext>.Descriptor.Order + 500)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)

4
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs

@ -44,7 +44,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachRequestHeaders>() .UseSingletonHandler<AttachRequestHeaders>()
.SetOrder(AttachUserAgentHeader<PrepareUserinfoRequestContext>.Descriptor.Order + 250) .SetOrder(AttachUserAgentHeader<PrepareUserinfoRequestContext>.Descriptor.Order + 250)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)
@ -88,7 +88,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
/// </summary> /// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; } public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>() = OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareUserinfoRequestContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachAccessTokenParameter>() .UseSingletonHandler<AttachAccessTokenParameter>()
.SetOrder(AttachBearerAccessToken.Descriptor.Order + 250) .SetOrder(AttachBearerAccessToken.Descriptor.Order + 250)
.SetType(OpenIddictClientHandlerType.BuiltIn) .SetType(OpenIddictClientHandlerType.BuiltIn)

4
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs

@ -258,7 +258,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
{ {
Providers.Deezer or Providers.Deezer or
Providers.Mixcloud => OpenIddictHelpers.AddQueryStringParameter( Providers.Mixcloud => OpenIddictHelpers.AddQueryStringParameter(
address: new Uri(context.TokenRequest.RedirectUri, UriKind.Absolute), uri: new Uri(context.TokenRequest.RedirectUri, UriKind.Absolute),
name: Parameters.State, name: Parameters.State,
value: context.StateToken).AbsoluteUri, value: context.StateToken).AbsoluteUri,
@ -500,7 +500,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
{ {
Providers.Deezer or Providers.Deezer or
Providers.Mixcloud => (OpenIddictHelpers.AddQueryStringParameter( Providers.Mixcloud => (OpenIddictHelpers.AddQueryStringParameter(
address: new Uri(context.RedirectUri, UriKind.Absolute), uri: new Uri(context.RedirectUri, UriKind.Absolute),
name: Parameters.State, name: Parameters.State,
value: context.Request.State).AbsoluteUri, null), value: context.Request.State).AbsoluteUri, null),

6
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

@ -56,14 +56,14 @@
<Provider Name="Keycloak" Documentation="https://www.keycloak.org/getting-started/getting-started-docker"> <Provider Name="Keycloak" Documentation="https://www.keycloak.org/getting-started/getting-started-docker">
<!-- <!--
Note: Keycloak is a self-hosted-only identity provider that doesn't have a generic issuer address. Note: Keycloak is a self-hosted-only identity provider that doesn't have a generic issuer URI.
As such, the complete address must always be set in the options and include the realm, if applicable. As such, the complete URI must always be set in the options and include the realm, if applicable.
--> -->
<Environment Issuer="{issuer}" /> <Environment Issuer="{issuer}" />
<Setting PropertyName="Issuer" ParameterName="issuer" Type="Uri" Required="true" <Setting PropertyName="Issuer" ParameterName="issuer" Type="Uri" Required="true"
Description="The address used to access the Keycloak identity provider (including the realm, if applicable)" /> Description="The URI used to access the Keycloak identity provider (including the realm, if applicable)" />
</Provider> </Provider>
<Provider Name="LinkedIn" Documentation="https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin"> <Provider Name="LinkedIn" Documentation="https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin">

4
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xsd

@ -216,7 +216,7 @@
<xs:attribute name="Issuer" type="xs:string" use="required"> <xs:attribute name="Issuer" type="xs:string" use="required">
<xs:annotation> <xs:annotation>
<xs:documentation>The issuer URL corresponding to the environment.</xs:documentation> <xs:documentation>The issuer URI corresponding to the environment.</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
@ -421,7 +421,7 @@
<xs:attribute name="Documentation" type="xs:anyURI" use="optional"> <xs:attribute name="Documentation" type="xs:anyURI" use="optional">
<xs:annotation> <xs:annotation>
<xs:documentation>The documentation URL, if applicable.</xs:documentation> <xs:documentation>The documentation URI, if applicable.</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
</xs:complexType> </xs:complexType>

84
src/OpenIddict.Client/OpenIddictClientBuilder.cs

@ -999,108 +999,108 @@ public sealed class OpenIddictClientBuilder
=> Configure(options => options.GrantTypes.Add(GrantTypes.RefreshToken)); => Configure(options => options.GrantTypes.Add(GrantTypes.RefreshToken));
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the redirection endpoint. /// Sets the relative or absolute URIs associated to the redirection endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint /// Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint
/// address per provider, unless all the registered providers support returning an "iss" /// URI per provider, unless all the registered providers support returning an "iss" parameter
/// parameter containing their URL as part of authorization responses. For more information, /// containing their identity as part of authorization responses. For more information,
/// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. /// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4.
/// </remarks> /// </remarks>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns>
public OpenIddictClientBuilder SetRedirectionEndpointUris( public OpenIddictClientBuilder SetRedirectionEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetRedirectionEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetRedirectionEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the redirection endpoint. /// Sets the relative or absolute URIs associated to the redirection endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint /// Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint
/// address per provider, unless all the registered providers support returning an "iss" /// URI per provider, unless all the registered providers support returning an "iss" parameter
/// parameter containing their URL as part of authorization responses. For more information, /// containing their identity as part of authorization responses. For more information,
/// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. /// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4.
/// </remarks> /// </remarks>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns>
public OpenIddictClientBuilder SetRedirectionEndpointUris(params Uri[] addresses) public OpenIddictClientBuilder SetRedirectionEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (Array.Exists(addresses, static address => !address.IsWellFormedOriginalString())) if (Array.Exists(uris, static uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (Array.Exists(addresses, static address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (Array.Exists(uris, static uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.RedirectionEndpointUris.Clear(); options.RedirectionEndpointUris.Clear();
options.RedirectionEndpointUris.AddRange(addresses); options.RedirectionEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the post-logout redirection endpoint. /// Sets the relative or absolute URIs associated to the post-logout redirection endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns>
public OpenIddictClientBuilder SetPostLogoutRedirectionEndpointUris( public OpenIddictClientBuilder SetPostLogoutRedirectionEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetPostLogoutRedirectionEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetPostLogoutRedirectionEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the post-logout redirection endpoint. /// Sets the relative or absolute URIs associated to the post-logout redirection endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns>
public OpenIddictClientBuilder SetPostLogoutRedirectionEndpointUris(params Uri[] addresses) public OpenIddictClientBuilder SetPostLogoutRedirectionEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (Array.Exists(addresses, static address => !address.IsWellFormedOriginalString())) if (Array.Exists(uris, static uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (Array.Exists(addresses, static address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (Array.Exists(uris, static uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.PostLogoutRedirectionEndpointUris.Clear(); options.PostLogoutRedirectionEndpointUris.Clear();
options.PostLogoutRedirectionEndpointUris.AddRange(addresses); options.PostLogoutRedirectionEndpointUris.AddRange(uris);
}); });
} }
@ -1127,19 +1127,19 @@ public sealed class OpenIddictClientBuilder
=> Configure(options => options.StateTokenLifetime = lifetime); => Configure(options => options.StateTokenLifetime = lifetime);
/// <summary> /// <summary>
/// Sets the client URI, which is used as the value for the "issuer" claim. /// Sets the client URI, which is used as the value of the "issuer" claim.
/// </summary> /// </summary>
/// <param name="address">The client URI.</param> /// <param name="uri">The client URI.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictClientBuilder"/> instance.</returns>
[EditorBrowsable(EditorBrowsableState.Advanced)] [EditorBrowsable(EditorBrowsableState.Advanced)]
public OpenIddictClientBuilder SetClientUri(Uri address) public OpenIddictClientBuilder SetClientUri(Uri uri)
{ {
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
return Configure(options => options.ClientUri = address); return Configure(options => options.ClientUri = uri);
} }
/// <inheritdoc/> /// <inheritdoc/>

12
src/OpenIddict.Client/OpenIddictClientConfiguration.cs

@ -70,12 +70,12 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions<OpenId
throw new InvalidOperationException(SR.GetResourceString(SR.ID0313)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0313));
} }
registration.MetadataAddress = OpenIddictHelpers.CreateAbsoluteUri( registration.ConfigurationEndpoint = OpenIddictHelpers.CreateAbsoluteUri(
registration.Issuer, registration.Issuer,
registration.MetadataAddress ?? new Uri(".well-known/openid-configuration", UriKind.Relative)); registration.ConfigurationEndpoint ?? new Uri(".well-known/openid-configuration", UriKind.Relative));
registration.ConfigurationManager = new ConfigurationManager<OpenIddictConfiguration>( registration.ConfigurationManager = new ConfigurationManager<OpenIddictConfiguration>(
registration.MetadataAddress.AbsoluteUri, new OpenIddictClientRetriever(_service, registration)) registration.ConfigurationEndpoint.AbsoluteUri, new OpenIddictClientRetriever(_service, registration))
{ {
AutomaticRefreshInterval = ConfigurationManager<OpenIddictConfiguration>.DefaultAutomaticRefreshInterval, AutomaticRefreshInterval = ConfigurationManager<OpenIddictConfiguration>.DefaultAutomaticRefreshInterval,
RefreshInterval = ConfigurationManager<OpenIddictConfiguration>.DefaultRefreshInterval RefreshInterval = ConfigurationManager<OpenIddictConfiguration>.DefaultRefreshInterval
@ -90,12 +90,12 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions<OpenId
throw new InvalidOperationException(SR.GetResourceString(SR.ID0076)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0076));
} }
var addresses = options.RedirectionEndpointUris.Distinct() var uris = options.RedirectionEndpointUris.Distinct()
.Concat(options.PostLogoutRedirectionEndpointUris.Distinct()) .Concat(options.PostLogoutRedirectionEndpointUris.Distinct())
.ToList(); .ToList();
// Ensure endpoint addresses are unique across endpoints. // Ensure endpoint URIs are unique across endpoints.
if (addresses.Count != addresses.Distinct().Count()) if (uris.Count != uris.Distinct().Count())
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID0285)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0285));
} }

14
src/OpenIddict.Client/OpenIddictClientEvents.cs

@ -140,9 +140,9 @@ public static partial class OpenIddictClientEvents
} }
/// <summary> /// <summary>
/// Gets or sets the address of the external endpoint to communicate with. /// Gets or sets the URI of the external endpoint to communicate with.
/// </summary> /// </summary>
public Uri? Address { get; set; } public Uri? RemoteUri { get; set; }
} }
/// <summary> /// <summary>
@ -271,7 +271,7 @@ public static partial class OpenIddictClientEvents
public string? ErrorDescription { get; set; } public string? ErrorDescription { get; set; }
/// <summary> /// <summary>
/// Gets or sets the error URL returned to the caller. /// Gets or sets the error URI returned to the caller.
/// </summary> /// </summary>
public string? ErrorUri { get; set; } public string? ErrorUri { get; set; }
@ -334,12 +334,12 @@ public static partial class OpenIddictClientEvents
public HashSet<string> Scopes { get; } = new(StringComparer.Ordinal); public HashSet<string> Scopes { get; } = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Gets or sets the address of the token endpoint, if applicable. /// Gets or sets the URI of the token endpoint, if applicable.
/// </summary> /// </summary>
public Uri? TokenEndpoint { get; set; } public Uri? TokenEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the address of the userinfo endpoint, if applicable. /// Gets or sets the URI of the userinfo endpoint, if applicable.
/// </summary> /// </summary>
public Uri? UserinfoEndpoint { get; set; } public Uri? UserinfoEndpoint { get; set; }
@ -803,7 +803,7 @@ public static partial class OpenIddictClientEvents
public string? RequestForgeryProtection { get; set; } public string? RequestForgeryProtection { get; set; }
/// <summary> /// <summary>
/// Gets or sets the optional return URL that will be stored in the state token, if applicable. /// Gets or sets the optional target link URI that will be stored in the state token, if applicable.
/// </summary> /// </summary>
[StringSyntax(StringSyntaxAttribute.Uri)] [StringSyntax(StringSyntaxAttribute.Uri)]
public string? TargetLinkUri { get; set; } public string? TargetLinkUri { get; set; }
@ -925,7 +925,7 @@ public static partial class OpenIddictClientEvents
public string? LoginHint { get; set; } public string? LoginHint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the optional return URL that will be stored in the state token, if applicable. /// Gets or sets the optional target link URI that will be stored in the state token, if applicable.
/// </summary> /// </summary>
public string? TargetLinkUri { get; set; } public string? TargetLinkUri { get; set; }

4
src/OpenIddict.Client/OpenIddictClientHandlers.Authentication.cs

@ -135,7 +135,7 @@ public static partial class OpenIddictClientHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for attaching the address of the authorization request to the request. /// Contains the logic responsible for attaching the URI of the authorization request to the request.
/// </summary> /// </summary>
public sealed class AttachAuthorizationEndpoint : IOpenIddictClientHandler<ApplyAuthorizationRequestContext> public sealed class AttachAuthorizationEndpoint : IOpenIddictClientHandler<ApplyAuthorizationRequestContext>
{ {
@ -156,7 +156,7 @@ public static partial class OpenIddictClientHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
// Ensure the authorization endpoint is present and is a valid absolute URL. // Ensure the authorization endpoint is present and is a valid absolute URI.
if (context.Configuration.AuthorizationEndpoint is not { IsAbsoluteUri: true } || if (context.Configuration.AuthorizationEndpoint is not { IsAbsoluteUri: true } ||
!context.Configuration.AuthorizationEndpoint.IsWellFormedOriginalString()) !context.Configuration.AuthorizationEndpoint.IsWellFormedOriginalString())
{ {

52
src/OpenIddict.Client/OpenIddictClientHandlers.Discovery.cs

@ -201,7 +201,7 @@ public static partial class OpenIddictClientHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
// Note: the issuer returned in the discovery document must exactly match the URL used to access it. // Note: the issuer returned in the discovery document must exactly match the URI used to access it.
// See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation. // See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation.
var issuer = (string?) context.Response[Metadata.Issuer]; var issuer = (string?) context.Response[Metadata.Issuer];
@ -215,7 +215,7 @@ public static partial class OpenIddictClientHandlers
return default; return default;
} }
if (!Uri.TryCreate(issuer, UriKind.Absolute, out Uri? address)) if (!Uri.TryCreate(issuer, UriKind.Absolute, out Uri? uri))
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -226,7 +226,7 @@ public static partial class OpenIddictClientHandlers
} }
// Ensure the issuer matches the expected value. // Ensure the issuer matches the expected value.
if (address != context.Registration.Issuer) if (uri != context.Registration.Issuer)
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -236,14 +236,14 @@ public static partial class OpenIddictClientHandlers
return default; return default;
} }
context.Configuration.Issuer = address; context.Configuration.Issuer = uri;
return default; return default;
} }
} }
/// <summary> /// <summary>
/// Contains the logic responsible for extracting the authorization endpoint address from the discovery document. /// Contains the logic responsible for extracting the authorization endpoint URI from the discovery document.
/// </summary> /// </summary>
public sealed class ExtractAuthorizationEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext> public sealed class ExtractAuthorizationEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext>
{ {
@ -269,15 +269,15 @@ public static partial class OpenIddictClientHandlers
// but is optional in the OAuth 2.0 authorization server metadata specification. To make OpenIddict // but is optional in the OAuth 2.0 authorization server metadata specification. To make OpenIddict
// compatible with the newer OAuth 2.0 specification, null/empty and missing values are allowed here. // compatible with the newer OAuth 2.0 specification, null/empty and missing values are allowed here.
// //
// Handlers that require a non-null authorization endpoint URL are expected to return an error // Handlers that require a non-null authorization endpoint URI are expected to return an error
// if the authorization endpoint URL couldn't be resolved from the authorization server metadata. // if the authorization endpoint URI couldn't be resolved from the authorization server metadata.
// See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationClient // See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationClient
// and https://datatracker.ietf.org/doc/html/rfc8414#section-2 for more information. // and https://datatracker.ietf.org/doc/html/rfc8414#section-2 for more information.
// //
var address = (string?) context.Response[Metadata.AuthorizationEndpoint]; var endpoint = (string?) context.Response[Metadata.AuthorizationEndpoint];
if (!string.IsNullOrEmpty(address)) if (!string.IsNullOrEmpty(endpoint))
{ {
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(endpoint, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -295,7 +295,7 @@ public static partial class OpenIddictClientHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for extracting the JWKS endpoint address from the discovery document. /// Contains the logic responsible for extracting the JWKS endpoint URI from the discovery document.
/// </summary> /// </summary>
public sealed class ExtractCryptographyEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext> public sealed class ExtractCryptographyEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext>
{ {
@ -319,8 +319,8 @@ public static partial class OpenIddictClientHandlers
// Note: the jwks_uri node is required by the OpenID Connect discovery specification. // Note: the jwks_uri node is required by the OpenID Connect discovery specification.
// See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationClient. // See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationClient.
var address = (string?) context.Response[Metadata.JwksUri]; var endpoint = (string?) context.Response[Metadata.JwksUri];
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(endpoint))
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -330,7 +330,7 @@ public static partial class OpenIddictClientHandlers
return default; return default;
} }
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(endpoint, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -347,7 +347,7 @@ public static partial class OpenIddictClientHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for extracting the logout endpoint address from the discovery document. /// Contains the logic responsible for extracting the logout endpoint URI from the discovery document.
/// </summary> /// </summary>
public sealed class ExtractLogoutEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext> public sealed class ExtractLogoutEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext>
{ {
@ -369,10 +369,10 @@ public static partial class OpenIddictClientHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
var address = (string?) context.Response[Metadata.EndSessionEndpoint]; var endpoint = (string?) context.Response[Metadata.EndSessionEndpoint];
if (!string.IsNullOrEmpty(address)) if (!string.IsNullOrEmpty(endpoint))
{ {
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(endpoint, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -390,7 +390,7 @@ public static partial class OpenIddictClientHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for extracting the token endpoint address from the discovery document. /// Contains the logic responsible for extracting the token endpoint URI from the discovery document.
/// </summary> /// </summary>
public sealed class ExtractTokenEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext> public sealed class ExtractTokenEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext>
{ {
@ -412,10 +412,10 @@ public static partial class OpenIddictClientHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
var address = (string?) context.Response[Metadata.TokenEndpoint]; var endpoint = (string?) context.Response[Metadata.TokenEndpoint];
if (!string.IsNullOrEmpty(address)) if (!string.IsNullOrEmpty(endpoint))
{ {
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(endpoint, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -433,7 +433,7 @@ public static partial class OpenIddictClientHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for extracting the userinfo endpoint address from the discovery document. /// Contains the logic responsible for extracting the userinfo endpoint URI from the discovery document.
/// </summary> /// </summary>
public sealed class ExtractUserinfoEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext> public sealed class ExtractUserinfoEndpoint : IOpenIddictClientHandler<HandleConfigurationResponseContext>
{ {
@ -455,10 +455,10 @@ public static partial class OpenIddictClientHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
var address = (string?) context.Response[Metadata.UserinfoEndpoint]; var endpoint = (string?) context.Response[Metadata.UserinfoEndpoint];
if (!string.IsNullOrEmpty(address)) if (!string.IsNullOrEmpty(endpoint))
{ {
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(endpoint, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,

19
src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs

@ -83,10 +83,10 @@ public static partial class OpenIddictClientHandlers
{ {
// When only state tokens are considered valid, use the token validation parameters of the client. // When only state tokens are considered valid, use the token validation parameters of the client.
1 when context.ValidTokenTypes.Contains(TokenTypeHints.StateToken) 1 when context.ValidTokenTypes.Contains(TokenTypeHints.StateToken)
=> GetClientTokenValidationParameters(context.BaseUri, context.Options), => GetClientTokenValidationParameters(),
// Otherwise, use the token validation parameters of the authorization server. // Otherwise, use the token validation parameters of the authorization server.
_ => GetServerTokenValidationParameters(context.Registration, context.Configuration) _ => GetServerTokenValidationParameters()
}; };
context.SecurityTokenHandler = context.Options.JsonWebTokenHandler; context.SecurityTokenHandler = context.Options.JsonWebTokenHandler;
@ -94,11 +94,11 @@ public static partial class OpenIddictClientHandlers
return default; return default;
static TokenValidationParameters GetClientTokenValidationParameters(Uri? address, OpenIddictClientOptions options) TokenValidationParameters GetClientTokenValidationParameters()
{ {
var parameters = options.TokenValidationParameters.Clone(); var parameters = context.Options.TokenValidationParameters.Clone();
parameters.ValidIssuers ??= (options.ClientUri ?? address) switch parameters.ValidIssuers ??= (context.Options.ClientUri ?? context.BaseUri) switch
{ {
null => null, null => null,
@ -122,12 +122,11 @@ public static partial class OpenIddictClientHandlers
return parameters; return parameters;
} }
static TokenValidationParameters GetServerTokenValidationParameters( TokenValidationParameters GetServerTokenValidationParameters()
OpenIddictClientRegistration registration, OpenIddictConfiguration configuration)
{ {
var parameters = registration!.TokenValidationParameters.Clone(); var parameters = context.Registration.TokenValidationParameters.Clone();
parameters.ValidIssuers ??= configuration.Issuer switch parameters.ValidIssuers ??= context.Configuration.Issuer switch
{ {
null => null, null => null,
@ -148,7 +147,7 @@ public static partial class OpenIddictClientHandlers
// Combine the signing keys registered statically in the token validation parameters // Combine the signing keys registered statically in the token validation parameters
// with the signing keys resolved from the OpenID Connect server configuration. // with the signing keys resolved from the OpenID Connect server configuration.
parameters.IssuerSigningKeys = parameters.IssuerSigningKeys =
parameters.IssuerSigningKeys?.Concat(configuration.SigningKeys) ?? configuration.SigningKeys; parameters.IssuerSigningKeys?.Concat(context.Configuration.SigningKeys) ?? context.Configuration.SigningKeys;
// For maximum compatibility, all "typ" values are accepted for all types of JSON Web Tokens, // For maximum compatibility, all "typ" values are accepted for all types of JSON Web Tokens,
// which typically includes identity tokens but can also include access tokens, authorization // which typically includes identity tokens but can also include access tokens, authorization

4
src/OpenIddict.Client/OpenIddictClientHandlers.Session.cs

@ -128,7 +128,7 @@ public static partial class OpenIddictClientHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for attaching the address of the authorization request to the request. /// Contains the logic responsible for attaching the URI of the authorization request to the request.
/// </summary> /// </summary>
public sealed class AttachLogoutEndpoint : IOpenIddictClientHandler<ApplyLogoutRequestContext> public sealed class AttachLogoutEndpoint : IOpenIddictClientHandler<ApplyLogoutRequestContext>
{ {
@ -149,7 +149,7 @@ public static partial class OpenIddictClientHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
// Ensure the end session endpoint is present and is a valid absolute URL. // Ensure the end session endpoint is present and is a valid absolute URI.
if (context.Configuration.EndSessionEndpoint is not { IsAbsoluteUri: true } || if (context.Configuration.EndSessionEndpoint is not { IsAbsoluteUri: true } ||
!context.Configuration.EndSessionEndpoint.IsWellFormedOriginalString()) !context.Configuration.EndSessionEndpoint.IsWellFormedOriginalString())
{ {

62
src/OpenIddict.Client/OpenIddictClientHandlers.cs

@ -142,7 +142,7 @@ public static partial class OpenIddictClientHandlers
.AddRange(Userinfo.DefaultHandlers); .AddRange(Userinfo.DefaultHandlers);
/// <summary> /// <summary>
/// Contains the logic responsible for inferring the endpoint type from the request address. /// Contains the logic responsible for inferring the endpoint type from the request URI.
/// </summary> /// </summary>
public sealed class InferEndpointType : IOpenIddictClientHandler<ProcessRequestContext> public sealed class InferEndpointType : IOpenIddictClientHandler<ProcessRequestContext>
{ {
@ -176,14 +176,14 @@ public static partial class OpenIddictClientHandlers
return default; return default;
bool Matches(IReadOnlyList<Uri> addresses) bool Matches(IReadOnlyList<Uri> candidates)
{ {
for (var index = 0; index < addresses.Count; index++) for (var index = 0; index < candidates.Count; index++)
{ {
var address = addresses[index]; var candidate = candidates[index];
if (address.IsAbsoluteUri) if (candidate.IsAbsoluteUri)
{ {
if (Equals(address, context.RequestUri)) if (Equals(candidate, context.RequestUri))
{ {
return true; return true;
} }
@ -191,7 +191,7 @@ public static partial class OpenIddictClientHandlers
else else
{ {
var uri = OpenIddictHelpers.CreateAbsoluteUri(context.BaseUri, address); var uri = OpenIddictHelpers.CreateAbsoluteUri(context.BaseUri, candidate);
if (uri.IsWellFormedOriginalString() && if (uri.IsWellFormedOriginalString() &&
OpenIddictHelpers.IsBaseOf(context.BaseUri, uri) && Equals(uri, context.RequestUri)) OpenIddictHelpers.IsBaseOf(context.BaseUri, uri) && Equals(uri, context.RequestUri))
{ {
@ -737,7 +737,7 @@ public static partial class OpenIddictClientHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for comparing the current request URL to the expected URL stored in the state token. /// Contains the logic responsible for comparing the current request URI to the expected URI stored in the state token.
/// </summary> /// </summary>
public sealed class ValidateEndpointUri : IOpenIddictClientHandler<ProcessAuthenticationContext> public sealed class ValidateEndpointUri : IOpenIddictClientHandler<ProcessAuthenticationContext>
{ {
@ -789,7 +789,7 @@ public static partial class OpenIddictClientHandlers
return default; return default;
} }
// Compare the current HTTP request address to the original endpoint URI. If the two don't // Compare the current HTTP request URI to the original endpoint URI. If the two don't
// match, this may indicate a mix-up attack. While the authorization server is expected to // match, this may indicate a mix-up attack. While the authorization server is expected to
// abort the authorization flow by rejecting the token request that may be eventually sent // abort the authorization flow by rejecting the token request that may be eventually sent
// with the original endpoint URI, many servers are known to incorrectly implement this // with the original endpoint URI, many servers are known to incorrectly implement this
@ -800,8 +800,8 @@ public static partial class OpenIddictClientHandlers
// //
// See https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-19#section-4.4.2.2 // See https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-19#section-4.4.2.2
// for more information. // for more information.
var address = new Uri(value, UriKind.Absolute); var uri = new Uri(value, UriKind.Absolute);
if (new UriBuilder(address) { Query = null }.Uri != if (new UriBuilder(uri) { Query = null }.Uri !=
new UriBuilder(context.RequestUri!) { Query = null }.Uri) new UriBuilder(context.RequestUri!) { Query = null }.Uri)
{ {
context.Reject( context.Reject(
@ -815,11 +815,11 @@ public static partial class OpenIddictClientHandlers
// Ensure all the query string parameters that were part of the original endpoint URI // Ensure all the query string parameters that were part of the original endpoint URI
// are present in the current request (parameters that were not part of the original // are present in the current request (parameters that were not part of the original
// endpoint URI are assumed to be authorization response parameters and are ignored). // endpoint URI are assumed to be authorization response parameters and are ignored).
if (!string.IsNullOrEmpty(address.Query)) if (!string.IsNullOrEmpty(uri.Query))
{ {
var parameters = OpenIddictHelpers.ParseQuery(context.RequestUri!.Query); var parameters = OpenIddictHelpers.ParseQuery(context.RequestUri!.Query);
foreach (var parameter in OpenIddictHelpers.ParseQuery(address.Query)) foreach (var parameter in OpenIddictHelpers.ParseQuery(uri.Query))
{ {
if (!parameters.TryGetValue(parameter.Key, out StringValues values) || if (!parameters.TryGetValue(parameter.Key, out StringValues values) ||
!parameter.Value.Equals(values)) !parameter.Value.Equals(values))
@ -1953,7 +1953,7 @@ public static partial class OpenIddictClientHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for resolving the address of the token endpoint. /// Contains the logic responsible for resolving the URI of the token endpoint.
/// </summary> /// </summary>
public sealed class ResolveTokenEndpoint : IOpenIddictClientHandler<ProcessAuthenticationContext> public sealed class ResolveTokenEndpoint : IOpenIddictClientHandler<ProcessAuthenticationContext>
{ {
@ -1975,11 +1975,11 @@ public static partial class OpenIddictClientHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
// If the address of the token endpoint wasn't explicitly set // If the URI of the token endpoint wasn't explicitly set at
// at this stage, try to extract it from the server configuration. // this stage, try to extract it from the server configuration.
context.TokenEndpoint ??= context.Configuration.TokenEndpoint switch context.TokenEndpoint ??= context.Configuration.TokenEndpoint switch
{ {
{ IsAbsoluteUri: true } address when address.IsWellFormedOriginalString() => address, { IsAbsoluteUri: true } uri when uri.IsWellFormedOriginalString() => uri,
_ => null _ => null
}; };
@ -2193,7 +2193,7 @@ public static partial class OpenIddictClientHandlers
principal.SetExpirationDate(principal.GetCreationDate() + lifetime.Value); principal.SetExpirationDate(principal.GetCreationDate() + lifetime.Value);
} }
// Use the address of the token endpoint as the audience, as recommended by the specifications. // Use the URI of the token endpoint as the audience, as recommended by the specifications.
// Applications that need to use a different value can register a custom event handler. // Applications that need to use a different value can register a custom event handler.
// //
// See https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication // See https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication
@ -2203,7 +2203,7 @@ public static partial class OpenIddictClientHandlers
principal.SetAudiences(context.TokenEndpoint.OriginalString); principal.SetAudiences(context.TokenEndpoint.OriginalString);
} }
// If the token endpoint address is not available, use the issuer address as the audience. // If the token endpoint URI is not available, use the issuer URI as the audience.
else else
{ {
principal.SetAudiences(context.Issuer.OriginalString); principal.SetAudiences(context.Issuer.OriginalString);
@ -2376,7 +2376,7 @@ public static partial class OpenIddictClientHandlers
Debug.Assert(context.TokenRequest is not null, SR.GetResourceString(SR.ID4008)); Debug.Assert(context.TokenRequest is not null, SR.GetResourceString(SR.ID4008));
// Ensure the token endpoint is present and is a valid absolute URL. // Ensure the token endpoint is present and is a valid absolute URI.
if (context.TokenEndpoint is not { IsAbsoluteUri: true } || if (context.TokenEndpoint is not { IsAbsoluteUri: true } ||
!context.TokenEndpoint.IsWellFormedOriginalString()) !context.TokenEndpoint.IsWellFormedOriginalString())
{ {
@ -3220,7 +3220,7 @@ public static partial class OpenIddictClientHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for resolving the address of the userinfo endpoint. /// Contains the logic responsible for resolving the URI of the userinfo endpoint.
/// </summary> /// </summary>
public sealed class ResolveUserinfoEndpoint : IOpenIddictClientHandler<ProcessAuthenticationContext> public sealed class ResolveUserinfoEndpoint : IOpenIddictClientHandler<ProcessAuthenticationContext>
{ {
@ -3242,11 +3242,11 @@ public static partial class OpenIddictClientHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
// If the address of the userinfo endpoint wasn't explicitly set // If the URI of the userinfo endpoint wasn't explicitly set at
// at this stage, try to extract it from the server configuration. // this stage, try to extract it from the server configuration.
context.UserinfoEndpoint ??= context.Configuration.UserinfoEndpoint switch context.UserinfoEndpoint ??= context.Configuration.UserinfoEndpoint switch
{ {
{ IsAbsoluteUri: true } address when address.IsWellFormedOriginalString() => address, { IsAbsoluteUri: true } uri when uri.IsWellFormedOriginalString() => uri,
_ => null _ => null
}; };
@ -3362,7 +3362,7 @@ public static partial class OpenIddictClientHandlers
Debug.Assert(context.UserinfoRequest is not null, SR.GetResourceString(SR.ID4008)); Debug.Assert(context.UserinfoRequest is not null, SR.GetResourceString(SR.ID4008));
// Ensure the userinfo endpoint is present and is a valid absolute URL. // Ensure the userinfo endpoint is present and is a valid absolute URI.
if (context.UserinfoEndpoint is not { IsAbsoluteUri: true } || if (context.UserinfoEndpoint is not { IsAbsoluteUri: true } ||
!context.UserinfoEndpoint.IsWellFormedOriginalString()) !context.UserinfoEndpoint.IsWellFormedOriginalString())
{ {
@ -4127,7 +4127,7 @@ public static partial class OpenIddictClientHandlers
// However, browser-based hosts like Blazor may typically want to use the fragment // However, browser-based hosts like Blazor may typically want to use the fragment
// response mode as it offers a better protection for SPA applications. // response mode as it offers a better protection for SPA applications.
// Unfortunately, server-side clients like ASP.NET Core applications cannot // Unfortunately, server-side clients like ASP.NET Core applications cannot
// natively use response_mode=fragment as URL fragments are never sent to servers. // natively use response_mode=fragment as URI fragments are never sent to servers.
// //
// As such, this handler will not choose response_mode=fragment by default and it is // As such, this handler will not choose response_mode=fragment by default and it is
// expected that specialized hosts like Blazor implement custom event handlers to // expected that specialized hosts like Blazor implement custom event handlers to
@ -4550,7 +4550,7 @@ public static partial class OpenIddictClientHandlers
// ensure the authorization response sent to the redirection endpoint is not forged. // ensure the authorization response sent to the redirection endpoint is not forged.
principal.SetClaim(Claims.RequestForgeryProtection, context.RequestForgeryProtection); principal.SetClaim(Claims.RequestForgeryProtection, context.RequestForgeryProtection);
// Store the optional return URL in the state token. // Store the optional target link URI in the state token.
principal.SetClaim(Claims.TargetLinkUri, context.TargetLinkUri); principal.SetClaim(Claims.TargetLinkUri, context.TargetLinkUri);
// Attach the negotiated grant type to the state token. // Attach the negotiated grant type to the state token.
@ -4718,7 +4718,7 @@ public static partial class OpenIddictClientHandlers
// Note: while the exact order of the parameters has typically no effect on how requests // Note: while the exact order of the parameters has typically no effect on how requests
// are handled by an authorization server, client_id and redirect_uri are deliberately // are handled by an authorization server, client_id and redirect_uri are deliberately
// set first so that they appear early in the URL (when GET requests are used), making // set first so that they appear early in the URI (when GET requests are used), making
// mistyped values easier to spot when an error is returned by the identity provider. // mistyped values easier to spot when an error is returned by the identity provider.
context.Request.ClientId = context.ClientId; context.Request.ClientId = context.ClientId;
context.Request.RedirectUri = context.RedirectUri; context.Request.RedirectUri = context.RedirectUri;
@ -5160,7 +5160,7 @@ public static partial class OpenIddictClientHandlers
// ensure the logout response sent to the post-logout redirection endpoint is not forged. // ensure the logout response sent to the post-logout redirection endpoint is not forged.
principal.SetClaim(Claims.RequestForgeryProtection, context.RequestForgeryProtection); principal.SetClaim(Claims.RequestForgeryProtection, context.RequestForgeryProtection);
// Store the optional return URL in the state token. // Store the optional target link URI in the state token.
principal.SetClaim(Claims.TargetLinkUri, context.TargetLinkUri); principal.SetClaim(Claims.TargetLinkUri, context.TargetLinkUri);
// Store the type of endpoint allowed to receive the generated state token. // Store the type of endpoint allowed to receive the generated state token.
@ -5168,7 +5168,7 @@ public static partial class OpenIddictClientHandlers
typeof(OpenIddictClientEndpointType), typeof(OpenIddictClientEndpointType),
OpenIddictClientEndpointType.PostLogoutRedirection)!.ToLowerInvariant()); OpenIddictClientEndpointType.PostLogoutRedirection)!.ToLowerInvariant());
// Store the post_logout_redirect_uri to allow comparing to the actual redirection URL. // Store the post_logout_redirect_uri to allow comparing to the actual redirection URI.
principal.SetClaim(Claims.Private.PostLogoutRedirectUri, context.PostLogoutRedirectUri); principal.SetClaim(Claims.Private.PostLogoutRedirectUri, context.PostLogoutRedirectUri);
// Store the nonce in the state token. // Store the nonce in the state token.
@ -5273,7 +5273,7 @@ public static partial class OpenIddictClientHandlers
// Note: while the exact order of the parameters has typically no effect on how requests // Note: while the exact order of the parameters has typically no effect on how requests
// are handled by an authorization server, client_id and post_logout_redirect_uri are // are handled by an authorization server, client_id and post_logout_redirect_uri are
// set first so that they appear early in the URL (when GET requests are used), making // set first so that they appear early in the URI (when GET requests are used), making
// mistyped values easier to spot when an error is returned by the identity provider. // mistyped values easier to spot when an error is returned by the identity provider.
context.Request.ClientId = context.ClientId; context.Request.ClientId = context.ClientId;
context.Request.PostLogoutRedirectUri = context.PostLogoutRedirectUri; context.Request.PostLogoutRedirectUri = context.PostLogoutRedirectUri;

2
src/OpenIddict.Client/OpenIddictClientOptions.cs

@ -16,7 +16,7 @@ namespace OpenIddict.Client;
public sealed class OpenIddictClientOptions public sealed class OpenIddictClientOptions
{ {
/// <summary> /// <summary>
/// Gets or sets the optional address used to uniquely identify the client/relying party. /// Gets or sets the optional URI used to uniquely identify the client/relying party.
/// The URI must be absolute and may contain a path, but no query string or fragment part. /// The URI must be absolute and may contain a path, but no query string or fragment part.
/// </summary> /// </summary>
public Uri? ClientUri { get; set; } public Uri? ClientUri { get; set; }

22
src/OpenIddict.Client/OpenIddictClientRegistration.cs

@ -27,12 +27,12 @@ public sealed class OpenIddictClientRegistration
public string? ClientSecret { get; set; } public string? ClientSecret { get; set; }
/// <summary> /// <summary>
/// Gets or sets the address of the redirection endpoint that will handle the callback. /// Gets or sets the URI of the redirection endpoint that will handle the callback.
/// </summary> /// </summary>
public Uri? RedirectUri { get; set; } public Uri? RedirectUri { get; set; }
/// <summary> /// <summary>
/// Gets or sets the address of the post-logout redirection endpoint that will handle the callback. /// Gets or sets the URI of the post-logout redirection endpoint that will handle the callback.
/// </summary> /// </summary>
public Uri? PostLogoutRedirectUri { get; set; } public Uri? PostLogoutRedirectUri { get; set; }
@ -91,7 +91,7 @@ public sealed class OpenIddictClientRegistration
public HashSet<string> ResponseModes { get; } = new(StringComparer.Ordinal); public HashSet<string> ResponseModes { get; } = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Gets or sets the address of the authorization server. /// Gets or sets the URI of the authorization server.
/// </summary> /// </summary>
public Uri? Issuer { get; set; } public Uri? Issuer { get; set; }
@ -120,14 +120,10 @@ public sealed class OpenIddictClientRegistration
public IConfigurationManager<OpenIddictConfiguration> ConfigurationManager { get; set; } = default!; public IConfigurationManager<OpenIddictConfiguration> ConfigurationManager { get; set; } = default!;
/// <summary> /// <summary>
/// Gets or sets the address of the authorization endpoint exposed by the server. /// Gets or sets the URI of the configuration endpoint exposed by the server.
/// When the URI is relative, <see cref="Issuer"/> must be set and absolute.
/// </summary> /// </summary>
public Uri? AuthorizationEndpoint { get; set; } public Uri? ConfigurationEndpoint { get; set; }
/// <summary>
/// Gets or sets the address of the token endpoint exposed by the server.
/// </summary>
public Uri? TokenEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the token validation parameters associated with the authorization server. /// Gets or sets the token validation parameters associated with the authorization server.
@ -143,12 +139,6 @@ public sealed class OpenIddictClientRegistration
ValidateLifetime = false ValidateLifetime = false
}; };
/// <summary>
/// Gets or sets the URL of the OAuth 2.0/OpenID Connect server discovery endpoint.
/// When the URL is relative, <see cref="Issuer"/> must be set and absolute.
/// </summary>
public Uri? MetadataAddress { get; set; }
/// <summary> /// <summary>
/// Gets the list of scopes sent by default as part of authorization requests. /// Gets the list of scopes sent by default as part of authorization requests.
/// </summary> /// </summary>

2
src/OpenIddict.Client/OpenIddictClientRetriever.cs

@ -29,7 +29,7 @@ public sealed class OpenIddictClientRetriever : IConfigurationRetriever<OpenIddi
} }
/// <summary> /// <summary>
/// Retrieves the OpenID Connect server configuration from the specified address. /// Retrieves the OpenID Connect server configuration from the specified URI.
/// </summary> /// </summary>
/// <param name="address">The address of the remote metadata endpoint.</param> /// <param name="address">The address of the remote metadata endpoint.</param>
/// <param name="retriever">The retriever used by IdentityModel.</param> /// <param name="retriever">The retriever used by IdentityModel.</param>

112
src/OpenIddict.Client/OpenIddictClientService.cs

@ -106,7 +106,7 @@ public sealed class OpenIddictClientService
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ?? var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
if (configuration.TokenEndpoint is not { IsAbsoluteUri: true } address || !address.IsWellFormedOriginalString()) if (configuration.TokenEndpoint is not { IsAbsoluteUri: true } uri || !uri.IsWellFormedOriginalString())
{ {
throw new InvalidOperationException(SR.FormatID0301(Metadata.TokenEndpoint)); throw new InvalidOperationException(SR.FormatID0301(Metadata.TokenEndpoint));
} }
@ -132,7 +132,7 @@ public sealed class OpenIddictClientService
GrantType = GrantTypes.ClientCredentials, GrantType = GrantTypes.ClientCredentials,
Issuer = registration.Issuer, Issuer = registration.Issuer,
Registration = registration, Registration = registration,
TokenEndpoint = address, TokenEndpoint = uri,
TokenRequest = parameters is not null ? new(parameters) : null, TokenRequest = parameters is not null ? new(parameters) : null,
}; };
@ -277,7 +277,7 @@ public sealed class OpenIddictClientService
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ?? var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
if (configuration.TokenEndpoint is not { IsAbsoluteUri: true } address || !address.IsWellFormedOriginalString()) if (configuration.TokenEndpoint is not { IsAbsoluteUri: true } uri || !uri.IsWellFormedOriginalString())
{ {
throw new InvalidOperationException(SR.FormatID0301(Metadata.TokenEndpoint)); throw new InvalidOperationException(SR.FormatID0301(Metadata.TokenEndpoint));
} }
@ -304,7 +304,7 @@ public sealed class OpenIddictClientService
Issuer = registration.Issuer, Issuer = registration.Issuer,
Password = password, Password = password,
Registration = registration, Registration = registration,
TokenEndpoint = address, TokenEndpoint = uri,
TokenRequest = parameters is not null ? new(parameters) : null, TokenRequest = parameters is not null ? new(parameters) : null,
Username = username Username = username
}; };
@ -442,7 +442,7 @@ public sealed class OpenIddictClientService
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ?? var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
if (configuration.TokenEndpoint is not { IsAbsoluteUri: true } address || !address.IsWellFormedOriginalString()) if (configuration.TokenEndpoint is not { IsAbsoluteUri: true } uri || !uri.IsWellFormedOriginalString())
{ {
throw new InvalidOperationException(SR.FormatID0301(Metadata.TokenEndpoint)); throw new InvalidOperationException(SR.FormatID0301(Metadata.TokenEndpoint));
} }
@ -469,7 +469,7 @@ public sealed class OpenIddictClientService
Issuer = registration.Issuer, Issuer = registration.Issuer,
RefreshToken = token, RefreshToken = token,
Registration = registration, Registration = registration,
TokenEndpoint = address, TokenEndpoint = uri,
TokenRequest = parameters is not null ? new(parameters) : null, TokenRequest = parameters is not null ? new(parameters) : null,
}; };
@ -519,28 +519,28 @@ public sealed class OpenIddictClientService
} }
/// <summary> /// <summary>
/// Retrieves the OpenID Connect server configuration from the specified address. /// Retrieves the OpenID Connect server configuration from the specified uri.
/// </summary> /// </summary>
/// <param name="registration">The client registration.</param> /// <param name="registration">The client registration.</param>
/// <param name="address">The address of the remote metadata endpoint.</param> /// <param name="uri">The uri of the remote metadata endpoint.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The OpenID Connect server configuration retrieved from the remote server.</returns> /// <returns>The OpenID Connect server configuration retrieved from the remote server.</returns>
internal async ValueTask<OpenIddictConfiguration> GetConfigurationAsync( internal async ValueTask<OpenIddictConfiguration> GetConfigurationAsync(
OpenIddictClientRegistration registration, Uri address, CancellationToken cancellationToken = default) OpenIddictClientRegistration registration, Uri uri, CancellationToken cancellationToken = default)
{ {
if (registration is null) if (registration is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
if (!address.IsAbsoluteUri || !address.IsWellFormedOriginalString()) if (!uri.IsAbsoluteUri || !uri.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
} }
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@ -570,7 +570,7 @@ public sealed class OpenIddictClientService
{ {
var context = new PrepareConfigurationRequestContext(transaction) var context = new PrepareConfigurationRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
}; };
@ -591,7 +591,7 @@ public sealed class OpenIddictClientService
{ {
var context = new ApplyConfigurationRequestContext(transaction) var context = new ApplyConfigurationRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
}; };
@ -605,7 +605,7 @@ public sealed class OpenIddictClientService
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.Address, context.Request); context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.RemoteUri, context.Request);
return context.Request; return context.Request;
} }
@ -614,7 +614,7 @@ public sealed class OpenIddictClientService
{ {
var context = new ExtractConfigurationResponseContext(transaction) var context = new ExtractConfigurationResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
}; };
@ -630,7 +630,7 @@ public sealed class OpenIddictClientService
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007));
context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.Address, context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.RemoteUri, context.Response);
return context.Response; return context.Response;
} }
@ -639,7 +639,7 @@ public sealed class OpenIddictClientService
{ {
var context = new HandleConfigurationResponseContext(transaction) var context = new HandleConfigurationResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request, Request = request,
Response = response Response = response
@ -676,25 +676,25 @@ public sealed class OpenIddictClientService
/// Retrieves the security keys exposed by the specified JWKS endpoint. /// Retrieves the security keys exposed by the specified JWKS endpoint.
/// </summary> /// </summary>
/// <param name="registration">The client registration.</param> /// <param name="registration">The client registration.</param>
/// <param name="address">The address of the remote metadata endpoint.</param> /// <param name="uri">The uri of the remote metadata endpoint.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The security keys retrieved from the remote server.</returns> /// <returns>The security keys retrieved from the remote server.</returns>
internal async ValueTask<JsonWebKeySet> GetSecurityKeysAsync( internal async ValueTask<JsonWebKeySet> GetSecurityKeysAsync(
OpenIddictClientRegistration registration, Uri address, CancellationToken cancellationToken = default) OpenIddictClientRegistration registration, Uri uri, CancellationToken cancellationToken = default)
{ {
if (registration is null) if (registration is null)
{ {
throw new ArgumentNullException(nameof(registration)); throw new ArgumentNullException(nameof(registration));
} }
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
if (!address.IsAbsoluteUri || !address.IsWellFormedOriginalString()) if (!uri.IsAbsoluteUri || !uri.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
} }
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@ -725,7 +725,7 @@ public sealed class OpenIddictClientService
{ {
var context = new PrepareCryptographyRequestContext(transaction) var context = new PrepareCryptographyRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
}; };
@ -746,7 +746,7 @@ public sealed class OpenIddictClientService
{ {
var context = new ApplyCryptographyRequestContext(transaction) var context = new ApplyCryptographyRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
}; };
@ -760,7 +760,7 @@ public sealed class OpenIddictClientService
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.Address, context.Request); context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.RemoteUri, context.Request);
return context.Request; return context.Request;
} }
@ -769,7 +769,7 @@ public sealed class OpenIddictClientService
{ {
var context = new ExtractCryptographyResponseContext(transaction) var context = new ExtractCryptographyResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
}; };
@ -785,7 +785,7 @@ public sealed class OpenIddictClientService
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007));
context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.Address, context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.RemoteUri, context.Response);
return context.Response; return context.Response;
} }
@ -794,7 +794,7 @@ public sealed class OpenIddictClientService
{ {
var context = new HandleCryptographyResponseContext(transaction) var context = new HandleCryptographyResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request, Request = request,
Response = response Response = response
@ -832,12 +832,12 @@ public sealed class OpenIddictClientService
/// </summary> /// </summary>
/// <param name="registration">The client registration.</param> /// <param name="registration">The client registration.</param>
/// <param name="request">The token request.</param> /// <param name="request">The token request.</param>
/// <param name="address">The address of the remote token endpoint.</param> /// <param name="uri">The uri of the remote token endpoint.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The token response.</returns> /// <returns>The token response.</returns>
internal async ValueTask<OpenIddictResponse> SendTokenRequestAsync( internal async ValueTask<OpenIddictResponse> SendTokenRequestAsync(
OpenIddictClientRegistration registration, OpenIddictRequest request, OpenIddictClientRegistration registration, OpenIddictRequest request,
Uri? address = null, CancellationToken cancellationToken = default) Uri? uri = null, CancellationToken cancellationToken = default)
{ {
if (registration is null) if (registration is null)
{ {
@ -849,14 +849,14 @@ public sealed class OpenIddictClientService
throw new ArgumentNullException(nameof(request)); throw new ArgumentNullException(nameof(request));
} }
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
if (!address.IsAbsoluteUri || !address.IsWellFormedOriginalString()) if (!uri.IsAbsoluteUri || !uri.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
} }
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ?? var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
@ -888,7 +888,7 @@ public sealed class OpenIddictClientService
{ {
var context = new PrepareTokenRequestContext(transaction) var context = new PrepareTokenRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
Request = request Request = request
@ -910,7 +910,7 @@ public sealed class OpenIddictClientService
{ {
var context = new ApplyTokenRequestContext(transaction) var context = new ApplyTokenRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
Request = request Request = request
@ -925,7 +925,7 @@ public sealed class OpenIddictClientService
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.Address, context.Request); context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request);
return context.Request; return context.Request;
} }
@ -934,7 +934,7 @@ public sealed class OpenIddictClientService
{ {
var context = new ExtractTokenResponseContext(transaction) var context = new ExtractTokenResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
Request = request Request = request
@ -951,7 +951,7 @@ public sealed class OpenIddictClientService
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007));
context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.Address, context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response);
return context.Response; return context.Response;
} }
@ -960,7 +960,7 @@ public sealed class OpenIddictClientService
{ {
var context = new HandleTokenResponseContext(transaction) var context = new HandleTokenResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
Request = request, Request = request,
@ -999,25 +999,25 @@ public sealed class OpenIddictClientService
/// </summary> /// </summary>
/// <param name="registration">The client registration.</param> /// <param name="registration">The client registration.</param>
/// <param name="request">The userinfo request.</param> /// <param name="request">The userinfo request.</param>
/// <param name="address">The address of the remote userinfo endpoint.</param> /// <param name="uri">The uri of the remote userinfo endpoint.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The response and the principal extracted from the userinfo response or the userinfo token.</returns> /// <returns>The response and the principal extracted from the userinfo response or the userinfo token.</returns>
internal async ValueTask<(OpenIddictResponse Response, (ClaimsPrincipal? Principal, string? Token))> SendUserinfoRequestAsync( internal async ValueTask<(OpenIddictResponse Response, (ClaimsPrincipal? Principal, string? Token))> SendUserinfoRequestAsync(
OpenIddictClientRegistration registration, OpenIddictRequest request, Uri address, CancellationToken cancellationToken = default) OpenIddictClientRegistration registration, OpenIddictRequest request, Uri uri, CancellationToken cancellationToken = default)
{ {
if (registration is null) if (registration is null)
{ {
throw new ArgumentNullException(nameof(registration)); throw new ArgumentNullException(nameof(registration));
} }
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
if (!address.IsAbsoluteUri || !address.IsWellFormedOriginalString()) if (!uri.IsAbsoluteUri || !uri.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
} }
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ?? var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
@ -1049,7 +1049,7 @@ public sealed class OpenIddictClientService
{ {
var context = new PrepareUserinfoRequestContext(transaction) var context = new PrepareUserinfoRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
Request = request Request = request
@ -1071,7 +1071,7 @@ public sealed class OpenIddictClientService
{ {
var context = new ApplyUserinfoRequestContext(transaction) var context = new ApplyUserinfoRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
Request = request Request = request
@ -1086,7 +1086,7 @@ public sealed class OpenIddictClientService
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID6194), context.Address, context.Request); context.Logger.LogInformation(SR.GetResourceString(SR.ID6194), context.RemoteUri, context.Request);
return context.Request; return context.Request;
} }
@ -1095,7 +1095,7 @@ public sealed class OpenIddictClientService
{ {
var context = new ExtractUserinfoResponseContext(transaction) var context = new ExtractUserinfoResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
Request = request Request = request
@ -1112,7 +1112,7 @@ public sealed class OpenIddictClientService
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007));
context.Logger.LogInformation(SR.GetResourceString(SR.ID6195), context.Address, context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID6195), context.RemoteUri, context.Response);
return (context.Response, context.UserinfoToken); return (context.Response, context.UserinfoToken);
} }
@ -1121,7 +1121,7 @@ public sealed class OpenIddictClientService
{ {
var context = new HandleUserinfoResponseContext(transaction) var context = new HandleUserinfoResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
Request = request, Request = request,

28
src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs

@ -57,21 +57,21 @@ public sealed class OpenIddictApplicationCache<TApplication> : IOpenIddictApplic
Identifier = await _store.GetIdAsync(application, cancellationToken) Identifier = await _store.GetIdAsync(application, cancellationToken)
}); });
foreach (var address in await _store.GetPostLogoutRedirectUrisAsync(application, cancellationToken)) foreach (var uri in await _store.GetPostLogoutRedirectUrisAsync(application, cancellationToken))
{ {
_cache.Remove(new _cache.Remove(new
{ {
Method = nameof(FindByPostLogoutRedirectUriAsync), Method = nameof(FindByPostLogoutRedirectUriAsync),
Address = address Uri = uri
}); });
} }
foreach (var address in await _store.GetRedirectUrisAsync(application, cancellationToken)) foreach (var uri in await _store.GetRedirectUrisAsync(application, cancellationToken))
{ {
_cache.Remove(new _cache.Remove(new
{ {
Method = nameof(FindByRedirectUriAsync), Method = nameof(FindByRedirectUriAsync),
Address = address Uri = uri
}); });
} }
@ -169,11 +169,11 @@ public sealed class OpenIddictApplicationCache<TApplication> : IOpenIddictApplic
/// <inheritdoc/> /// <inheritdoc/>
public IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync( public IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
return ExecuteAsync(cancellationToken); return ExecuteAsync(cancellationToken);
@ -183,14 +183,14 @@ public sealed class OpenIddictApplicationCache<TApplication> : IOpenIddictApplic
var parameters = new var parameters = new
{ {
Method = nameof(FindByPostLogoutRedirectUriAsync), Method = nameof(FindByPostLogoutRedirectUriAsync),
Address = address Uri = uri
}; };
if (!_cache.TryGetValue(parameters, out ImmutableArray<TApplication> applications)) if (!_cache.TryGetValue(parameters, out ImmutableArray<TApplication> applications))
{ {
var builder = ImmutableArray.CreateBuilder<TApplication>(); var builder = ImmutableArray.CreateBuilder<TApplication>();
await foreach (var application in _store.FindByPostLogoutRedirectUriAsync(address, cancellationToken)) await foreach (var application in _store.FindByPostLogoutRedirectUriAsync(uri, cancellationToken))
{ {
builder.Add(application); builder.Add(application);
@ -211,11 +211,11 @@ public sealed class OpenIddictApplicationCache<TApplication> : IOpenIddictApplic
/// <inheritdoc/> /// <inheritdoc/>
public IAsyncEnumerable<TApplication> FindByRedirectUriAsync( public IAsyncEnumerable<TApplication> FindByRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
return ExecuteAsync(cancellationToken); return ExecuteAsync(cancellationToken);
@ -225,14 +225,14 @@ public sealed class OpenIddictApplicationCache<TApplication> : IOpenIddictApplic
var parameters = new var parameters = new
{ {
Method = nameof(FindByRedirectUriAsync), Method = nameof(FindByRedirectUriAsync),
Address = address Uri = uri
}; };
if (!_cache.TryGetValue(parameters, out ImmutableArray<TApplication> applications)) if (!_cache.TryGetValue(parameters, out ImmutableArray<TApplication> applications))
{ {
var builder = ImmutableArray.CreateBuilder<TApplication>(); var builder = ImmutableArray.CreateBuilder<TApplication>();
await foreach (var application in _store.FindByRedirectUriAsync(address, cancellationToken)) await foreach (var application in _store.FindByRedirectUriAsync(uri, cancellationToken))
{ {
builder.Add(application); builder.Add(application);

130
src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs

@ -326,20 +326,20 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <summary> /// <summary>
/// Retrieves all the applications associated with the specified post_logout_redirect_uri. /// Retrieves all the applications associated with the specified post_logout_redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The post_logout_redirect_uri associated with the applications.</param> /// <param name="uri">The post_logout_redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The client applications corresponding to the specified post_logout_redirect_uri.</returns> /// <returns>The client applications corresponding to the specified post_logout_redirect_uri.</returns>
public virtual IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync( public virtual IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken = default) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken = default)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
var applications = Options.CurrentValue.DisableEntityCaching ? var applications = Options.CurrentValue.DisableEntityCaching ?
Store.FindByPostLogoutRedirectUriAsync(address, cancellationToken) : Store.FindByPostLogoutRedirectUriAsync(uri, cancellationToken) :
Cache.FindByPostLogoutRedirectUriAsync(address, cancellationToken); Cache.FindByPostLogoutRedirectUriAsync(uri, cancellationToken);
if (Options.CurrentValue.DisableAdditionalFiltering) if (Options.CurrentValue.DisableAdditionalFiltering)
{ {
@ -356,8 +356,8 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
{ {
await foreach (var application in applications) await foreach (var application in applications)
{ {
var addresses = await Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken); var uris = await Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken);
if (addresses.Contains(address, StringComparer.Ordinal)) if (uris.Contains(uri, StringComparer.Ordinal))
{ {
yield return application; yield return application;
} }
@ -368,20 +368,20 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <summary> /// <summary>
/// Retrieves all the applications associated with the specified redirect_uri. /// Retrieves all the applications associated with the specified redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The redirect_uri associated with the applications.</param> /// <param name="uri">The redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The client applications corresponding to the specified redirect_uri.</returns> /// <returns>The client applications corresponding to the specified redirect_uri.</returns>
public virtual IAsyncEnumerable<TApplication> FindByRedirectUriAsync( public virtual IAsyncEnumerable<TApplication> FindByRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken = default) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken = default)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
var applications = Options.CurrentValue.DisableEntityCaching ? var applications = Options.CurrentValue.DisableEntityCaching ?
Store.FindByRedirectUriAsync(address, cancellationToken) : Store.FindByRedirectUriAsync(uri, cancellationToken) :
Cache.FindByRedirectUriAsync(address, cancellationToken); Cache.FindByRedirectUriAsync(uri, cancellationToken);
if (Options.CurrentValue.DisableAdditionalFiltering) if (Options.CurrentValue.DisableAdditionalFiltering)
{ {
@ -398,8 +398,8 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
{ {
await foreach (var application in applications) await foreach (var application in applications)
{ {
var addresses = await Store.GetRedirectUrisAsync(application, cancellationToken); var uris = await Store.GetRedirectUrisAsync(application, cancellationToken);
if (addresses.Contains(address, StringComparer.Ordinal)) if (uris.Contains(uri, StringComparer.Ordinal))
{ {
yield return application; yield return application;
} }
@ -665,7 +665,7 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
} }
/// <summary> /// <summary>
/// Retrieves the logout callback addresses associated with an application. /// Retrieves the post-logout redirect URIs associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
@ -705,7 +705,7 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
} }
/// <summary> /// <summary>
/// Retrieves the callback addresses associated with an application. /// Retrieves the redirect URIs associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
@ -916,10 +916,10 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
await Store.SetDisplayNamesAsync(application, descriptor.DisplayNames.ToImmutableDictionary(), cancellationToken); await Store.SetDisplayNamesAsync(application, descriptor.DisplayNames.ToImmutableDictionary(), cancellationToken);
await Store.SetPermissionsAsync(application, descriptor.Permissions.ToImmutableArray(), cancellationToken); await Store.SetPermissionsAsync(application, descriptor.Permissions.ToImmutableArray(), cancellationToken);
await Store.SetPostLogoutRedirectUrisAsync(application, ImmutableArray.CreateRange( await Store.SetPostLogoutRedirectUrisAsync(application, ImmutableArray.CreateRange(
descriptor.PostLogoutRedirectUris.Select(address => address.OriginalString)), cancellationToken); descriptor.PostLogoutRedirectUris.Select(uri => uri.OriginalString)), cancellationToken);
await Store.SetPropertiesAsync(application, descriptor.Properties.ToImmutableDictionary(), cancellationToken); await Store.SetPropertiesAsync(application, descriptor.Properties.ToImmutableDictionary(), cancellationToken);
await Store.SetRedirectUrisAsync(application, ImmutableArray.CreateRange( await Store.SetRedirectUrisAsync(application, ImmutableArray.CreateRange(
descriptor.RedirectUris.Select(address => address.OriginalString)), cancellationToken); descriptor.RedirectUris.Select(uri => uri.OriginalString)), cancellationToken);
await Store.SetRequirementsAsync(application, descriptor.Requirements.ToImmutableArray(), cancellationToken); await Store.SetRequirementsAsync(application, descriptor.Requirements.ToImmutableArray(), cancellationToken);
} }
@ -963,21 +963,21 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
} }
descriptor.PostLogoutRedirectUris.Clear(); descriptor.PostLogoutRedirectUris.Clear();
foreach (var address in await Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken)) foreach (var uri in await Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken))
{ {
// Ensure the address is not null or empty. // Ensure the URI is not null or empty.
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0213)); throw new ArgumentException(SR.GetResourceString(SR.ID0213));
} }
// Ensure the address is a valid absolute URL. // Ensure the URI is a valid absolute URI.
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(uri, UriKind.Absolute, out Uri? value) || !value.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0214)); throw new ArgumentException(SR.GetResourceString(SR.ID0214));
} }
descriptor.PostLogoutRedirectUris.Add(uri); descriptor.PostLogoutRedirectUris.Add(value);
} }
descriptor.Properties.Clear(); descriptor.Properties.Clear();
@ -987,21 +987,21 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
} }
descriptor.RedirectUris.Clear(); descriptor.RedirectUris.Clear();
foreach (var address in await Store.GetRedirectUrisAsync(application, cancellationToken)) foreach (var uri in await Store.GetRedirectUrisAsync(application, cancellationToken))
{ {
// Ensure the address is not null or empty. // Ensure the URI is not null or empty.
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0213)); throw new ArgumentException(SR.GetResourceString(SR.ID0213));
} }
// Ensure the address is a valid absolute URL. // Ensure the URI is a valid absolute URI.
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(uri, UriKind.Absolute, out Uri? value) || !value.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0214)); throw new ArgumentException(SR.GetResourceString(SR.ID0214));
} }
descriptor.RedirectUris.Add(uri); descriptor.RedirectUris.Add(value);
} }
} }
@ -1192,30 +1192,30 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
} }
} }
// When callback URLs are specified, ensure they are valid and spec-compliant. // When callback URIs are specified, ensure they are valid and spec-compliant.
// See https://tools.ietf.org/html/rfc6749#section-3.1 for more information. // See https://tools.ietf.org/html/rfc6749#section-3.1 for more information.
foreach (var address in ImmutableArray.Create<string>() foreach (var uri in ImmutableArray.Create<string>()
.AddRange(await Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken)) .AddRange(await Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken))
.AddRange(await Store.GetRedirectUrisAsync(application, cancellationToken))) .AddRange(await Store.GetRedirectUrisAsync(application, cancellationToken)))
{ {
// Ensure the address is not null or empty. // Ensure the URI is not null or empty.
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
yield return new ValidationResult(SR.GetResourceString(SR.ID2061)); yield return new ValidationResult(SR.GetResourceString(SR.ID2061));
break; break;
} }
// Ensure the address is a valid absolute URL. // Ensure the URI is a valid absolute URI.
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(uri, UriKind.Absolute, out Uri? value) || !value.IsWellFormedOriginalString())
{ {
yield return new ValidationResult(SR.GetResourceString(SR.ID2062)); yield return new ValidationResult(SR.GetResourceString(SR.ID2062));
break; break;
} }
// Ensure the address doesn't contain a fragment. // Ensure the URI doesn't contain a fragment.
if (!string.IsNullOrEmpty(uri.Fragment)) if (!string.IsNullOrEmpty(value.Fragment))
{ {
yield return new ValidationResult(SR.GetResourceString(SR.ID2115)); yield return new ValidationResult(SR.GetResourceString(SR.ID2115));
@ -1223,10 +1223,10 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
} }
// To prevent issuer fixation attacks where a malicious client would specify an "iss" parameter // To prevent issuer fixation attacks where a malicious client would specify an "iss" parameter
// in the callback URL, ensure the query - if present - doesn't include an "iss" parameter. // in the callback URI, ensure the query - if present - doesn't include an "iss" parameter.
if (!string.IsNullOrEmpty(uri.Query)) if (!string.IsNullOrEmpty(value.Query))
{ {
var parameters = OpenIddictHelpers.ParseQuery(uri.Query); var parameters = OpenIddictHelpers.ParseQuery(value.Query);
if (parameters.ContainsKey(Parameters.Iss)) if (parameters.ContainsKey(Parameters.Iss))
{ {
yield return new ValidationResult(SR.FormatID2134(Parameters.Iss)); yield return new ValidationResult(SR.FormatID2134(Parameters.Iss));
@ -1289,7 +1289,7 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// Validates the post_logout_redirect_uri to ensure it's associated with an application. /// Validates the post_logout_redirect_uri to ensure it's associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="address">The address that should be compared to one of the post_logout_redirect_uri stored in the database.</param> /// <param name="uri">The URI that should be compared to one of the post_logout_redirect_uri stored in the database.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <remarks>Note: if no client_id parameter is specified in logout requests, this method may not be called.</remarks> /// <remarks>Note: if no client_id parameter is specified in logout requests, this method may not be called.</remarks>
/// <returns> /// <returns>
@ -1297,28 +1297,28 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns a boolean indicating whether the post_logout_redirect_uri was valid. /// whose result returns a boolean indicating whether the post_logout_redirect_uri was valid.
/// </returns> /// </returns>
public virtual async ValueTask<bool> ValidatePostLogoutRedirectUriAsync(TApplication application, public virtual async ValueTask<bool> ValidatePostLogoutRedirectUriAsync(TApplication application,
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken = default) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken = default)
{ {
if (application is null) if (application is null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
foreach (var uri in await Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken)) foreach (var candidate in await Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken))
{ {
// Note: the post_logout_redirect_uri must be compared using case-sensitive "Simple String Comparison". // Note: the post_logout_redirect_uri must be compared using case-sensitive "Simple String Comparison".
if (string.Equals(uri, address, StringComparison.Ordinal)) if (string.Equals(candidate, uri, StringComparison.Ordinal))
{ {
return true; return true;
} }
} }
Logger.LogInformation(SR.GetResourceString(SR.ID6202), address, await GetClientIdAsync(application, cancellationToken)); Logger.LogInformation(SR.GetResourceString(SR.ID6202), uri, await GetClientIdAsync(application, cancellationToken));
return false; return false;
} }
@ -1327,36 +1327,36 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// Validates the redirect_uri to ensure it's associated with an application. /// Validates the redirect_uri to ensure it's associated with an application.
/// </summary> /// </summary>
/// <param name="application">The application.</param> /// <param name="application">The application.</param>
/// <param name="address">The address that should be compared to one of the redirect_uri stored in the database.</param> /// <param name="uri">The URI that should be compared to one of the redirect_uri stored in the database.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation, /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation,
/// whose result returns a boolean indicating whether the redirect_uri was valid. /// whose result returns a boolean indicating whether the redirect_uri was valid.
/// </returns> /// </returns>
public virtual async ValueTask<bool> ValidateRedirectUriAsync(TApplication application, public virtual async ValueTask<bool> ValidateRedirectUriAsync(TApplication application,
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken = default) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken = default)
{ {
if (application is null) if (application is null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
foreach (var uri in await Store.GetRedirectUrisAsync(application, cancellationToken)) foreach (var candidate in await Store.GetRedirectUrisAsync(application, cancellationToken))
{ {
// Note: the redirect_uri must be compared using case-sensitive "Simple String Comparison". // Note: the redirect_uri must be compared using case-sensitive "Simple String Comparison".
// See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest for more information. // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest for more information.
if (string.Equals(uri, address, StringComparison.Ordinal)) if (string.Equals(candidate, uri, StringComparison.Ordinal))
{ {
return true; return true;
} }
} }
Logger.LogInformation(SR.GetResourceString(SR.ID6162), address, await GetClientIdAsync(application, cancellationToken)); Logger.LogInformation(SR.GetResourceString(SR.ID6162), uri, await GetClientIdAsync(application, cancellationToken));
return false; return false;
} }
@ -1567,12 +1567,12 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
=> await FindByIdAsync(identifier, cancellationToken); => await FindByIdAsync(identifier, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
IAsyncEnumerable<object> IOpenIddictApplicationManager.FindByPostLogoutRedirectUriAsync([StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) IAsyncEnumerable<object> IOpenIddictApplicationManager.FindByPostLogoutRedirectUriAsync([StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
=> FindByPostLogoutRedirectUriAsync(address, cancellationToken); => FindByPostLogoutRedirectUriAsync(uri, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
IAsyncEnumerable<object> IOpenIddictApplicationManager.FindByRedirectUriAsync([StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) IAsyncEnumerable<object> IOpenIddictApplicationManager.FindByRedirectUriAsync([StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
=> FindByRedirectUriAsync(address, cancellationToken); => FindByRedirectUriAsync(uri, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<TResult?> IOpenIddictApplicationManager.GetAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken) where TResult : default ValueTask<TResult?> IOpenIddictApplicationManager.GetAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken) where TResult : default
@ -1691,10 +1691,10 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
=> ValidateClientSecretAsync((TApplication) application, secret, cancellationToken); => ValidateClientSecretAsync((TApplication) application, secret, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<bool> IOpenIddictApplicationManager.ValidatePostLogoutRedirectUriAsync(object application, [StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) ValueTask<bool> IOpenIddictApplicationManager.ValidatePostLogoutRedirectUriAsync(object application, [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
=> ValidatePostLogoutRedirectUriAsync((TApplication) application, address, cancellationToken); => ValidatePostLogoutRedirectUriAsync((TApplication) application, uri, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<bool> IOpenIddictApplicationManager.ValidateRedirectUriAsync(object application, [StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) ValueTask<bool> IOpenIddictApplicationManager.ValidateRedirectUriAsync(object application, [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
=> ValidateRedirectUriAsync((TApplication) application, address, cancellationToken); => ValidateRedirectUriAsync((TApplication) application, uri, cancellationToken);
} }

4
src/OpenIddict.EntityFramework.Models/OpenIddictEntityFrameworkApplication.cs

@ -83,7 +83,7 @@ public class OpenIddictEntityFrameworkApplication<TKey, TAuthorization, TToken>
public virtual string? Permissions { get; set; } public virtual string? Permissions { get; set; }
/// <summary> /// <summary>
/// Gets or sets the logout callback URLs associated with /// Gets or sets the post-logout redirect URIs associated with
/// the current application, serialized as a JSON array. /// the current application, serialized as a JSON array.
/// </summary> /// </summary>
[StringSyntax(StringSyntaxAttribute.Json)] [StringSyntax(StringSyntaxAttribute.Json)]
@ -97,7 +97,7 @@ public class OpenIddictEntityFrameworkApplication<TKey, TAuthorization, TToken>
public virtual string? Properties { get; set; } public virtual string? Properties { get; set; }
/// <summary> /// <summary>
/// Gets or sets the callback URLs associated with the /// Gets or sets the redirect URIs associated with the
/// current application, serialized as a JSON array. /// current application, serialized as a JSON array.
/// </summary> /// </summary>
[StringSyntax(StringSyntaxAttribute.Json)] [StringSyntax(StringSyntaxAttribute.Json)]

56
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs

@ -237,15 +237,15 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
/// <inheritdoc/> /// <inheritdoc/>
public virtual IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync( public virtual IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
// To optimize the efficiency of the query a bit, only applications whose stringified // To optimize the efficiency of the query a bit, only applications whose stringified
// PostLogoutRedirectUris contains the specified URL are returned. Once the applications // PostLogoutRedirectUris contains the specified URI are returned. Once the applications
// are retrieved, a second pass is made to ensure only valid elements are returned. // are retrieved, a second pass is made to ensure only valid elements are returned.
// Implementers that use this method in a hot path may want to override this method // Implementers that use this method in a hot path may want to override this method
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient. // to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
@ -255,13 +255,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
async IAsyncEnumerable<TApplication> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken) async IAsyncEnumerable<TApplication> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken)
{ {
var applications = (from application in Applications var applications = (from application in Applications
where application.PostLogoutRedirectUris!.Contains(address) where application.PostLogoutRedirectUris!.Contains(uri)
select application).AsAsyncEnumerable(cancellationToken); select application).AsAsyncEnumerable(cancellationToken);
await foreach (var application in applications) await foreach (var application in applications)
{ {
var addresses = await GetPostLogoutRedirectUrisAsync(application, cancellationToken); var uris = await GetPostLogoutRedirectUrisAsync(application, cancellationToken);
if (addresses.Contains(address, StringComparer.Ordinal)) if (uris.Contains(uri, StringComparer.Ordinal))
{ {
yield return application; yield return application;
} }
@ -271,15 +271,15 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
/// <inheritdoc/> /// <inheritdoc/>
public virtual IAsyncEnumerable<TApplication> FindByRedirectUriAsync( public virtual IAsyncEnumerable<TApplication> FindByRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
// To optimize the efficiency of the query a bit, only applications whose stringified // To optimize the efficiency of the query a bit, only applications whose stringified
// RedirectUris property contains the specified URL are returned. Once the applications // RedirectUris property contains the specified URI are returned. Once the applications
// are retrieved, a second pass is made to ensure only valid elements are returned. // are retrieved, a second pass is made to ensure only valid elements are returned.
// Implementers that use this method in a hot path may want to override this method // Implementers that use this method in a hot path may want to override this method
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient. // to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
@ -289,13 +289,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
async IAsyncEnumerable<TApplication> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken) async IAsyncEnumerable<TApplication> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken)
{ {
var applications = (from application in Applications var applications = (from application in Applications
where application.RedirectUris!.Contains(address) where application.RedirectUris!.Contains(uri)
select application).AsAsyncEnumerable(cancellationToken); select application).AsAsyncEnumerable(cancellationToken);
await foreach (var application in applications) await foreach (var application in applications)
{ {
var addresses = await GetRedirectUrisAsync(application, cancellationToken); var uris = await GetRedirectUrisAsync(application, cancellationToken);
if (addresses.Contains(address, StringComparer.Ordinal)) if (uris.Contains(uri, StringComparer.Ordinal))
{ {
yield return application; yield return application;
} }
@ -477,10 +477,10 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
return new(ImmutableArray.Create<string>()); return new(ImmutableArray.Create<string>());
} }
// Note: parsing the stringified addresses is an expensive operation. // Note: parsing the stringified URIs is an expensive operation.
// To mitigate that, the resulting array is stored in the memory cache. // To mitigate that, the resulting array is stored in the memory cache.
var key = string.Concat("fb14dfb9-9216-4b77-bfa9-7e85f8201ff4", "\x1e", application.PostLogoutRedirectUris); var key = string.Concat("fb14dfb9-9216-4b77-bfa9-7e85f8201ff4", "\x1e", application.PostLogoutRedirectUris);
var addresses = Cache.GetOrCreate(key, entry => var uris = Cache.GetOrCreate(key, entry =>
{ {
entry.SetPriority(CacheItemPriority.High) entry.SetPriority(CacheItemPriority.High)
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
@ -502,7 +502,7 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
return builder.ToImmutable(); return builder.ToImmutable();
}); });
return new(addresses); return new(uris);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -553,10 +553,10 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
return new(ImmutableArray.Create<string>()); return new(ImmutableArray.Create<string>());
} }
// Note: parsing the stringified addresses is an expensive operation. // Note: parsing the stringified URIs is an expensive operation.
// To mitigate that, the resulting array is stored in the memory cache. // To mitigate that, the resulting array is stored in the memory cache.
var key = string.Concat("851d6f08-2ee0-4452-bbe5-ab864611ecaa", "\x1e", application.RedirectUris); var key = string.Concat("851d6f08-2ee0-4452-bbe5-ab864611ecaa", "\x1e", application.RedirectUris);
var addresses = Cache.GetOrCreate(key, entry => var uris = Cache.GetOrCreate(key, entry =>
{ {
entry.SetPriority(CacheItemPriority.High) entry.SetPriority(CacheItemPriority.High)
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
@ -578,7 +578,7 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
return builder.ToImmutable(); return builder.ToImmutable();
}); });
return new(addresses); return new(uris);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -812,14 +812,14 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
/// <inheritdoc/> /// <inheritdoc/>
public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application, public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken) ImmutableArray<string> uris, CancellationToken cancellationToken)
{ {
if (application is null) if (application is null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
if (addresses.IsDefaultOrEmpty) if (uris.IsDefaultOrEmpty)
{ {
application.PostLogoutRedirectUris = null; application.PostLogoutRedirectUris = null;
@ -835,9 +835,9 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
writer.WriteStartArray(); writer.WriteStartArray();
foreach (var address in addresses) foreach (var uri in uris)
{ {
writer.WriteStringValue(address); writer.WriteStringValue(uri);
} }
writer.WriteEndArray(); writer.WriteEndArray();
@ -889,14 +889,14 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
/// <inheritdoc/> /// <inheritdoc/>
public virtual ValueTask SetRedirectUrisAsync(TApplication application, public virtual ValueTask SetRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken) ImmutableArray<string> uris, CancellationToken cancellationToken)
{ {
if (application is null) if (application is null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
if (addresses.IsDefaultOrEmpty) if (uris.IsDefaultOrEmpty)
{ {
application.RedirectUris = null; application.RedirectUris = null;
@ -912,9 +912,9 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
writer.WriteStartArray(); writer.WriteStartArray();
foreach (var address in addresses) foreach (var uri in uris)
{ {
writer.WriteStringValue(address); writer.WriteStringValue(uri);
} }
writer.WriteEndArray(); writer.WriteEndArray();

4
src/OpenIddict.EntityFrameworkCore.Models/OpenIddictEntityFrameworkCoreApplication.cs

@ -91,7 +91,7 @@ public class OpenIddictEntityFrameworkCoreApplication<TKey, TAuthorization, TTok
public virtual string? Permissions { get; set; } public virtual string? Permissions { get; set; }
/// <summary> /// <summary>
/// Gets or sets the logout callback URLs associated with /// Gets or sets the post-logout redirect URIs associated with
/// the current application, serialized as a JSON array. /// the current application, serialized as a JSON array.
/// </summary> /// </summary>
[StringSyntax(StringSyntaxAttribute.Json)] [StringSyntax(StringSyntaxAttribute.Json)]
@ -105,7 +105,7 @@ public class OpenIddictEntityFrameworkCoreApplication<TKey, TAuthorization, TTok
public virtual string? Properties { get; set; } public virtual string? Properties { get; set; }
/// <summary> /// <summary>
/// Gets or sets the callback URLs associated with the /// Gets or sets the redirect URIs associated with the
/// current application, serialized as a JSON array. /// current application, serialized as a JSON array.
/// </summary> /// </summary>
[StringSyntax(StringSyntaxAttribute.Json)] [StringSyntax(StringSyntaxAttribute.Json)]

56
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs

@ -279,15 +279,15 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
/// <inheritdoc/> /// <inheritdoc/>
public virtual IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync( public virtual IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
// To optimize the efficiency of the query a bit, only applications whose stringified // To optimize the efficiency of the query a bit, only applications whose stringified
// PostLogoutRedirectUris contains the specified URL are returned. Once the applications // PostLogoutRedirectUris contains the specified URI are returned. Once the applications
// are retrieved, a second pass is made to ensure only valid elements are returned. // are retrieved, a second pass is made to ensure only valid elements are returned.
// Implementers that use this method in a hot path may want to override this method // Implementers that use this method in a hot path may want to override this method
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient. // to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
@ -297,13 +297,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
async IAsyncEnumerable<TApplication> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken) async IAsyncEnumerable<TApplication> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken)
{ {
var applications = (from application in Applications.AsTracking() var applications = (from application in Applications.AsTracking()
where application.PostLogoutRedirectUris!.Contains(address) where application.PostLogoutRedirectUris!.Contains(uri)
select application).AsAsyncEnumerable(cancellationToken); select application).AsAsyncEnumerable(cancellationToken);
await foreach (var application in applications) await foreach (var application in applications)
{ {
var addresses = await GetPostLogoutRedirectUrisAsync(application, cancellationToken); var uris = await GetPostLogoutRedirectUrisAsync(application, cancellationToken);
if (addresses.Contains(address, StringComparer.Ordinal)) if (uris.Contains(uri, StringComparer.Ordinal))
{ {
yield return application; yield return application;
} }
@ -313,15 +313,15 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
/// <inheritdoc/> /// <inheritdoc/>
public virtual IAsyncEnumerable<TApplication> FindByRedirectUriAsync( public virtual IAsyncEnumerable<TApplication> FindByRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
// To optimize the efficiency of the query a bit, only applications whose stringified // To optimize the efficiency of the query a bit, only applications whose stringified
// RedirectUris property contains the specified URL are returned. Once the applications // RedirectUris property contains the specified URI are returned. Once the applications
// are retrieved, a second pass is made to ensure only valid elements are returned. // are retrieved, a second pass is made to ensure only valid elements are returned.
// Implementers that use this method in a hot path may want to override this method // Implementers that use this method in a hot path may want to override this method
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient. // to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
@ -331,13 +331,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
async IAsyncEnumerable<TApplication> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken) async IAsyncEnumerable<TApplication> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken)
{ {
var applications = (from application in Applications.AsTracking() var applications = (from application in Applications.AsTracking()
where application.RedirectUris!.Contains(address) where application.RedirectUris!.Contains(uri)
select application).AsAsyncEnumerable(cancellationToken); select application).AsAsyncEnumerable(cancellationToken);
await foreach (var application in applications) await foreach (var application in applications)
{ {
var addresses = await GetRedirectUrisAsync(application, cancellationToken); var uris = await GetRedirectUrisAsync(application, cancellationToken);
if (addresses.Contains(address, StringComparer.Ordinal)) if (uris.Contains(uri, StringComparer.Ordinal))
{ {
yield return application; yield return application;
} }
@ -519,10 +519,10 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
return new(ImmutableArray.Create<string>()); return new(ImmutableArray.Create<string>());
} }
// Note: parsing the stringified addresses is an expensive operation. // Note: parsing the stringified URIs is an expensive operation.
// To mitigate that, the resulting array is stored in the memory cache. // To mitigate that, the resulting array is stored in the memory cache.
var key = string.Concat("fb14dfb9-9216-4b77-bfa9-7e85f8201ff4", "\x1e", application.PostLogoutRedirectUris); var key = string.Concat("fb14dfb9-9216-4b77-bfa9-7e85f8201ff4", "\x1e", application.PostLogoutRedirectUris);
var addresses = Cache.GetOrCreate(key, entry => var uris = Cache.GetOrCreate(key, entry =>
{ {
entry.SetPriority(CacheItemPriority.High) entry.SetPriority(CacheItemPriority.High)
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
@ -544,7 +544,7 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
return builder.ToImmutable(); return builder.ToImmutable();
}); });
return new(addresses); return new(uris);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -595,10 +595,10 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
return new(ImmutableArray.Create<string>()); return new(ImmutableArray.Create<string>());
} }
// Note: parsing the stringified addresses is an expensive operation. // Note: parsing the stringified URIs is an expensive operation.
// To mitigate that, the resulting array is stored in the memory cache. // To mitigate that, the resulting array is stored in the memory cache.
var key = string.Concat("851d6f08-2ee0-4452-bbe5-ab864611ecaa", "\x1e", application.RedirectUris); var key = string.Concat("851d6f08-2ee0-4452-bbe5-ab864611ecaa", "\x1e", application.RedirectUris);
var addresses = Cache.GetOrCreate(key, entry => var uris = Cache.GetOrCreate(key, entry =>
{ {
entry.SetPriority(CacheItemPriority.High) entry.SetPriority(CacheItemPriority.High)
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
@ -620,7 +620,7 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
return builder.ToImmutable(); return builder.ToImmutable();
}); });
return new(addresses); return new(uris);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -853,14 +853,14 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
/// <inheritdoc/> /// <inheritdoc/>
public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application, public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken) ImmutableArray<string> uris, CancellationToken cancellationToken)
{ {
if (application is null) if (application is null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
if (addresses.IsDefaultOrEmpty) if (uris.IsDefaultOrEmpty)
{ {
application.PostLogoutRedirectUris = null; application.PostLogoutRedirectUris = null;
@ -876,9 +876,9 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
writer.WriteStartArray(); writer.WriteStartArray();
foreach (var address in addresses) foreach (var uri in uris)
{ {
writer.WriteStringValue(address); writer.WriteStringValue(uri);
} }
writer.WriteEndArray(); writer.WriteEndArray();
@ -930,14 +930,14 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
/// <inheritdoc/> /// <inheritdoc/>
public virtual ValueTask SetRedirectUrisAsync(TApplication application, public virtual ValueTask SetRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken) ImmutableArray<string> uris, CancellationToken cancellationToken)
{ {
if (application is null) if (application is null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
if (addresses.IsDefaultOrEmpty) if (uris.IsDefaultOrEmpty)
{ {
application.RedirectUris = null; application.RedirectUris = null;
@ -953,9 +953,9 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
writer.WriteStartArray(); writer.WriteStartArray();
foreach (var address in addresses) foreach (var uri in uris)
{ {
writer.WriteStringValue(address); writer.WriteStringValue(uri);
} }
writer.WriteEndArray(); writer.WriteEndArray();

4
src/OpenIddict.MongoDb.Models/OpenIddictMongoDbApplication.cs

@ -67,7 +67,7 @@ public class OpenIddictMongoDbApplication
public virtual IReadOnlyList<string>? Permissions { get; set; } = ImmutableList.Create<string>(); public virtual IReadOnlyList<string>? Permissions { get; set; } = ImmutableList.Create<string>();
/// <summary> /// <summary>
/// Gets or sets the logout callback URLs associated with the current application. /// Gets or sets the post-logout redirect URIs associated with the current application.
/// </summary> /// </summary>
[BsonElement("post_logout_redirect_uris"), BsonIgnoreIfNull] [BsonElement("post_logout_redirect_uris"), BsonIgnoreIfNull]
public virtual IReadOnlyList<string>? PostLogoutRedirectUris { get; set; } = ImmutableList.Create<string>(); public virtual IReadOnlyList<string>? PostLogoutRedirectUris { get; set; } = ImmutableList.Create<string>();
@ -79,7 +79,7 @@ public class OpenIddictMongoDbApplication
public virtual BsonDocument? Properties { get; set; } public virtual BsonDocument? Properties { get; set; }
/// <summary> /// <summary>
/// Gets or sets the callback URLs associated with the current application. /// Gets or sets the redirect URIs associated with the current application.
/// </summary> /// </summary>
[BsonElement("redirect_uris"), BsonIgnoreIfNull] [BsonElement("redirect_uris"), BsonIgnoreIfNull]
public virtual IReadOnlyList<string>? RedirectUris { get; set; } = ImmutableList.Create<string>(); public virtual IReadOnlyList<string>? RedirectUris { get; set; } = ImmutableList.Create<string>();

28
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs

@ -138,11 +138,11 @@ public class OpenIddictMongoDbApplicationStore<TApplication> : IOpenIddictApplic
/// <inheritdoc/> /// <inheritdoc/>
public virtual IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync( public virtual IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
return ExecuteAsync(cancellationToken); return ExecuteAsync(cancellationToken);
@ -153,7 +153,7 @@ public class OpenIddictMongoDbApplicationStore<TApplication> : IOpenIddictApplic
var collection = database.GetCollection<TApplication>(Options.CurrentValue.ApplicationsCollectionName); var collection = database.GetCollection<TApplication>(Options.CurrentValue.ApplicationsCollectionName);
await foreach (var application in collection.Find(application => await foreach (var application in collection.Find(application =>
application.PostLogoutRedirectUris!.Contains(address)).ToAsyncEnumerable(cancellationToken)) application.PostLogoutRedirectUris!.Contains(uri)).ToAsyncEnumerable(cancellationToken))
{ {
yield return application; yield return application;
} }
@ -162,11 +162,11 @@ public class OpenIddictMongoDbApplicationStore<TApplication> : IOpenIddictApplic
/// <inheritdoc/> /// <inheritdoc/>
public virtual IAsyncEnumerable<TApplication> FindByRedirectUriAsync( public virtual IAsyncEnumerable<TApplication> FindByRedirectUriAsync(
[StringSyntax(StringSyntaxAttribute.Uri)] string address, CancellationToken cancellationToken) [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(uri));
} }
return ExecuteAsync(cancellationToken); return ExecuteAsync(cancellationToken);
@ -177,7 +177,7 @@ public class OpenIddictMongoDbApplicationStore<TApplication> : IOpenIddictApplic
var collection = database.GetCollection<TApplication>(Options.CurrentValue.ApplicationsCollectionName); var collection = database.GetCollection<TApplication>(Options.CurrentValue.ApplicationsCollectionName);
await foreach (var application in collection.Find(application => await foreach (var application in collection.Find(application =>
application.RedirectUris!.Contains(address)).ToAsyncEnumerable(cancellationToken)) application.RedirectUris!.Contains(uri)).ToAsyncEnumerable(cancellationToken))
{ {
yield return application; yield return application;
} }
@ -554,21 +554,21 @@ public class OpenIddictMongoDbApplicationStore<TApplication> : IOpenIddictApplic
/// <inheritdoc/> /// <inheritdoc/>
public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application, public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken) ImmutableArray<string> uris, CancellationToken cancellationToken)
{ {
if (application is null) if (application is null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
if (addresses.IsDefaultOrEmpty) if (uris.IsDefaultOrEmpty)
{ {
application.PostLogoutRedirectUris = null; application.PostLogoutRedirectUris = null;
return default; return default;
} }
application.PostLogoutRedirectUris = addresses.ToImmutableList(); application.PostLogoutRedirectUris = uris.ToImmutableList();
return default; return default;
} }
@ -614,21 +614,21 @@ public class OpenIddictMongoDbApplicationStore<TApplication> : IOpenIddictApplic
/// <inheritdoc/> /// <inheritdoc/>
public virtual ValueTask SetRedirectUrisAsync(TApplication application, public virtual ValueTask SetRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken) ImmutableArray<string> uris, CancellationToken cancellationToken)
{ {
if (application is null) if (application is null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
if (addresses.IsDefaultOrEmpty) if (uris.IsDefaultOrEmpty)
{ {
application.RedirectUris = null; application.RedirectUris = null;
return default; return default;
} }
application.RedirectUris = addresses.ToImmutableList(); application.RedirectUris = uris.ToImmutableList();
return default; return default;
} }

2
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs

@ -149,7 +149,7 @@ public sealed class OpenIddictServerAspNetCoreBuilder
/// <summary> /// <summary>
/// Sets the realm returned to the caller as part of the WWW-Authenticate header. /// Sets the realm returned to the caller as part of the WWW-Authenticate header.
/// </summary> /// </summary>
/// <param name="realm">The issuer address.</param> /// <param name="realm">The realm.</param>
/// <returns>The <see cref="OpenIddictServerAspNetCoreBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerAspNetCoreBuilder"/> instance.</returns>
public OpenIddictServerAspNetCoreBuilder SetRealm(string realm) public OpenIddictServerAspNetCoreBuilder SetRealm(string realm)
{ {

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

@ -245,12 +245,12 @@ public static partial class OpenIddictServerAspNetCoreHandlers
token, _options.CurrentValue.AuthorizationRequestCachingPolicy); token, _options.CurrentValue.AuthorizationRequestCachingPolicy);
// Create a new GET authorization request containing only the request_id parameter. // Create a new GET authorization request containing only the request_id parameter.
var address = QueryHelpers.AddQueryString( var location = QueryHelpers.AddQueryString(
uri: request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + request.Path, uri: request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + request.Path,
name: Parameters.RequestId, name: Parameters.RequestId,
value: context.Request.RequestId); value: context.Request.RequestId);
request.HttpContext.Response.Redirect(address); request.HttpContext.Response.Redirect(location);
// Mark the response as handled to skip the rest of the pipeline. // Mark the response as handled to skip the rest of the pipeline.
context.HandleRequest(); context.HandleRequest();

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

@ -81,8 +81,8 @@ public static partial class OpenIddictServerAspNetCoreHandlers
var response = context.Transaction.GetHttpRequest()?.HttpContext.Response ?? var response = context.Transaction.GetHttpRequest()?.HttpContext.Response ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0114)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0114));
// Note: this handler only redirects the user agent to the address specified in // Note: this handler only redirects the user agent to the URI specified in the
// the properties when there's no error or if the error is an access_denied error. // properties when there's no error or if the error is an access_denied error.
if (!string.IsNullOrEmpty(context.Response.Error) && if (!string.IsNullOrEmpty(context.Response.Error) &&
!string.Equals(context.Response.Error, Errors.AccessDenied, StringComparison.Ordinal)) !string.Equals(context.Response.Error, Errors.AccessDenied, StringComparison.Ordinal))
{ {

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

@ -242,12 +242,12 @@ public static partial class OpenIddictServerAspNetCoreHandlers
token, _options.CurrentValue.LogoutRequestCachingPolicy); token, _options.CurrentValue.LogoutRequestCachingPolicy);
// Create a new GET logout request containing only the request_id parameter. // Create a new GET logout request containing only the request_id parameter.
var address = QueryHelpers.AddQueryString( var location = QueryHelpers.AddQueryString(
uri: request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + request.Path, uri: request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + request.Path,
name: Parameters.RequestId, name: Parameters.RequestId,
value: context.Request.RequestId); value: context.Request.RequestId);
request.HttpContext.Response.Redirect(address); request.HttpContext.Response.Redirect(location);
// Mark the response as handled to skip the rest of the pipeline. // Mark the response as handled to skip the rest of the pipeline.
context.HandleRequest(); context.HandleRequest();

2
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs

@ -96,7 +96,7 @@ public static partial class OpenIddictServerAspNetCoreHandlers
// sent by the HTTP client) is not desirable as it would affect all requests, including requests // sent by the HTTP client) is not desirable as it would affect all requests, including requests
// that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily // that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily
// used to build an absolute base URI and a request URI that will be used to determine whether the // used to build an absolute base URI and a request URI that will be used to determine whether the
// received request matches one of the addresses assigned to an OpenIddict endpoint. If the request // received request matches one of the URIs assigned to an OpenIddict endpoint. If the request
// is later handled by OpenIddict, an additional check will be made to require the Host header. // is later handled by OpenIddict, an additional check will be made to require the Host header.
(context.BaseUri, context.RequestUri) = request.Host switch (context.BaseUri, context.RequestUri) = request.Host switch

2
src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs

@ -138,7 +138,7 @@ public sealed class OpenIddictServerOwinBuilder
/// <summary> /// <summary>
/// Sets the realm returned to the caller as part of the WWW-Authenticate header. /// Sets the realm returned to the caller as part of the WWW-Authenticate header.
/// </summary> /// </summary>
/// <param name="realm">The issuer address.</param> /// <param name="realm">The realm.</param>
/// <returns>The <see cref="OpenIddictServerOwinBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerOwinBuilder"/> instance.</returns>
public OpenIddictServerOwinBuilder SetRealm(string realm) public OpenIddictServerOwinBuilder SetRealm(string realm)
{ {

4
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs

@ -241,12 +241,12 @@ public static partial class OpenIddictServerOwinHandlers
token, _options.CurrentValue.AuthorizationRequestCachingPolicy); token, _options.CurrentValue.AuthorizationRequestCachingPolicy);
// Create a new GET authorization request containing only the request_id parameter. // Create a new GET authorization request containing only the request_id parameter.
var address = WebUtilities.AddQueryString( var location = WebUtilities.AddQueryString(
uri: request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + request.Path, uri: request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + request.Path,
name: Parameters.RequestId, name: Parameters.RequestId,
value: context.Request.RequestId); value: context.Request.RequestId);
request.Context.Response.Redirect(address); request.Context.Response.Redirect(location);
// Mark the response as handled to skip the rest of the pipeline. // Mark the response as handled to skip the rest of the pipeline.
context.HandleRequest(); context.HandleRequest();

4
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Device.cs

@ -84,8 +84,8 @@ public static partial class OpenIddictServerOwinHandlers
var response = context.Transaction.GetOwinRequest()?.Context.Response ?? var response = context.Transaction.GetOwinRequest()?.Context.Response ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0120)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0120));
// Note: this handler only redirects the user agent to the address specified in // Note: this handler only redirects the user agent to the URI specified in the
// the properties when there's no error or if the error is an access_denied error. // properties when there's no error or if the error is an access_denied error.
if (!string.IsNullOrEmpty(context.Response.Error) && if (!string.IsNullOrEmpty(context.Response.Error) &&
!string.Equals(context.Response.Error, Errors.AccessDenied, StringComparison.Ordinal)) !string.Equals(context.Response.Error, Errors.AccessDenied, StringComparison.Ordinal))
{ {

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

@ -239,12 +239,12 @@ public static partial class OpenIddictServerOwinHandlers
token, _options.CurrentValue.LogoutRequestCachingPolicy); token, _options.CurrentValue.LogoutRequestCachingPolicy);
// Create a new GET logout request containing only the request_id parameter. // Create a new GET logout request containing only the request_id parameter.
var address = WebUtilities.AddQueryString( var location = WebUtilities.AddQueryString(
uri: request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + request.Path, uri: request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + request.Path,
name: Parameters.RequestId, name: Parameters.RequestId,
value: context.Request.RequestId); value: context.Request.RequestId);
request.Context.Response.Redirect(address); request.Context.Response.Redirect(location);
// Mark the response as handled to skip the rest of the pipeline. // Mark the response as handled to skip the rest of the pipeline.
context.HandleRequest(); context.HandleRequest();

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

@ -91,7 +91,7 @@ public static partial class OpenIddictServerOwinHandlers
// sent by the HTTP client) is not desirable as it would affect all requests, including requests // sent by the HTTP client) is not desirable as it would affect all requests, including requests
// that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily // that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily
// used to build an absolute base URI and a request URI that will be used to determine whether the // used to build an absolute base URI and a request URI that will be used to determine whether the
// received request matches one of the addresses assigned to an OpenIddict endpoint. If the request // received request matches one of the URIs assigned to an OpenIddict endpoint. If the request
// is later handled by OpenIddict, an additional check will be made to require the Host header. // is later handled by OpenIddict, an additional check will be made to require the Host header.
(context.BaseUri, context.RequestUri) = request.Host switch (context.BaseUri, context.RequestUri) = request.Host switch

372
src/OpenIddict.Server/OpenIddictServerBuilder.cs

@ -1002,492 +1002,492 @@ public sealed class OpenIddictServerBuilder
}); });
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the authorization endpoint. /// Sets the relative or absolute URIs associated to the authorization endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetAuthorizationEndpointUris( public OpenIddictServerBuilder SetAuthorizationEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetAuthorizationEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetAuthorizationEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the authorization endpoint. /// Sets the relative or absolute URIs associated to the authorization endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetAuthorizationEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetAuthorizationEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.AuthorizationEndpointUris.Clear(); options.AuthorizationEndpointUris.Clear();
options.AuthorizationEndpointUris.AddRange(addresses); options.AuthorizationEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the configuration endpoint. /// Sets the relative or absolute URIs associated to the configuration endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetConfigurationEndpointUris( public OpenIddictServerBuilder SetConfigurationEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetConfigurationEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetConfigurationEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the configuration endpoint. /// Sets the relative or absolute URIs associated to the configuration endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetConfigurationEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetConfigurationEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.ConfigurationEndpointUris.Clear(); options.ConfigurationEndpointUris.Clear();
options.ConfigurationEndpointUris.AddRange(addresses); options.ConfigurationEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the cryptography endpoint. /// Sets the relative or absolute URIs associated to the cryptography endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetCryptographyEndpointUris( public OpenIddictServerBuilder SetCryptographyEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetCryptographyEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetCryptographyEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the cryptography endpoint. /// Sets the relative or absolute URIs associated to the cryptography endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetCryptographyEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetCryptographyEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.CryptographyEndpointUris.Clear(); options.CryptographyEndpointUris.Clear();
options.CryptographyEndpointUris.AddRange(addresses); options.CryptographyEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the device endpoint. /// Sets the relative or absolute URIs associated to the device endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetDeviceEndpointUris( public OpenIddictServerBuilder SetDeviceEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetDeviceEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetDeviceEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the device endpoint. /// Sets the relative or absolute URIs associated to the device endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetDeviceEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetDeviceEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.DeviceEndpointUris.Clear(); options.DeviceEndpointUris.Clear();
options.DeviceEndpointUris.AddRange(addresses); options.DeviceEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the introspection endpoint. /// Sets the relative or absolute URIs associated to the introspection endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetIntrospectionEndpointUris( public OpenIddictServerBuilder SetIntrospectionEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetIntrospectionEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetIntrospectionEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the introspection endpoint. /// Sets the relative or absolute URIs associated to the introspection endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetIntrospectionEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetIntrospectionEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.IntrospectionEndpointUris.Clear(); options.IntrospectionEndpointUris.Clear();
options.IntrospectionEndpointUris.AddRange(addresses); options.IntrospectionEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the logout endpoint. /// Sets the relative or absolute URIs associated to the logout endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetLogoutEndpointUris( public OpenIddictServerBuilder SetLogoutEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetLogoutEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetLogoutEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the logout endpoint. /// Sets the relative or absolute URIs associated to the logout endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetLogoutEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetLogoutEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.LogoutEndpointUris.Clear(); options.LogoutEndpointUris.Clear();
options.LogoutEndpointUris.AddRange(addresses); options.LogoutEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the revocation endpoint. /// Sets the relative or absolute URIs associated to the revocation endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetRevocationEndpointUris( public OpenIddictServerBuilder SetRevocationEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetRevocationEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetRevocationEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the revocation endpoint. /// Sets the relative or absolute URIs associated to the revocation endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetRevocationEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetRevocationEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.RevocationEndpointUris.Clear(); options.RevocationEndpointUris.Clear();
options.RevocationEndpointUris.AddRange(addresses); options.RevocationEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the token endpoint. /// Sets the relative or absolute URIs associated to the token endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetTokenEndpointUris( public OpenIddictServerBuilder SetTokenEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetTokenEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetTokenEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the token endpoint. /// Sets the relative or absolute URIs associated to the token endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetTokenEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetTokenEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.TokenEndpointUris.Clear(); options.TokenEndpointUris.Clear();
options.TokenEndpointUris.AddRange(addresses); options.TokenEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the userinfo endpoint. /// Sets the relative or absolute URIs associated to the userinfo endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetUserinfoEndpointUris( public OpenIddictServerBuilder SetUserinfoEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetUserinfoEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetUserinfoEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the userinfo endpoint. /// Sets the relative or absolute URIs associated to the userinfo endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned as part of the discovery document. /// Note: only the first URI will be returned as part of the discovery document.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetUserinfoEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetUserinfoEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.UserinfoEndpointUris.Clear(); options.UserinfoEndpointUris.Clear();
options.UserinfoEndpointUris.AddRange(addresses); options.UserinfoEndpointUris.AddRange(uris);
}); });
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the verification endpoint. /// Sets the relative or absolute URIs associated to the verification endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned by the device endpoint. /// Note: only the first URI will be returned by the device endpoint.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetVerificationEndpointUris( public OpenIddictServerBuilder SetVerificationEndpointUris(
[StringSyntax(StringSyntaxAttribute.Uri)] params string[] addresses) [StringSyntax(StringSyntaxAttribute.Uri)] params string[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
return SetVerificationEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray()); return SetVerificationEndpointUris(uris.Select(uri => new Uri(uri, UriKind.RelativeOrAbsolute)).ToArray());
} }
/// <summary> /// <summary>
/// Sets the relative or absolute URLs associated to the verification endpoint. /// Sets the relative or absolute URIs associated to the verification endpoint.
/// If an empty array is specified, the endpoint will be considered disabled. /// If an empty array is specified, the endpoint will be considered disabled.
/// Note: only the first address will be returned by the device endpoint. /// Note: only the first URI will be returned by the device endpoint.
/// </summary> /// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param> /// <param name="uris">The URIs associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetVerificationEndpointUris(params Uri[] addresses) public OpenIddictServerBuilder SetVerificationEndpointUris(params Uri[] uris)
{ {
if (addresses is null) if (uris is null)
{ {
throw new ArgumentNullException(nameof(addresses)); throw new ArgumentNullException(nameof(uris));
} }
if (addresses.Any(address => !address.IsWellFormedOriginalString())) if (uris.Any(uri => !uri.IsWellFormedOriginalString()))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses)); throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(uris));
} }
if (addresses.Any(address => address.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase))) if (uris.Any(uri => uri.OriginalString.StartsWith("~", StringComparison.OrdinalIgnoreCase)))
{ {
throw new ArgumentException(SR.FormatID0081("~"), nameof(addresses)); throw new ArgumentException(SR.FormatID0081("~"), nameof(uris));
} }
return Configure(options => return Configure(options =>
{ {
options.VerificationEndpointUris.Clear(); options.VerificationEndpointUris.Clear();
options.VerificationEndpointUris.AddRange(addresses); options.VerificationEndpointUris.AddRange(uris);
}); });
} }
@ -1714,19 +1714,19 @@ public sealed class OpenIddictServerBuilder
=> Configure(options => options.UserCodeLifetime = lifetime); => Configure(options => options.UserCodeLifetime = lifetime);
/// <summary> /// <summary>
/// Sets the issuer address, which is used as the value for the "issuer" claim and /// Sets the issuer URI, which is used as the value of the "issuer" claim and
/// is returned from the discovery endpoint to identify the authorization server. /// is returned from the discovery endpoint to identify the authorization server.
/// </summary> /// </summary>
/// <param name="address">The issuer address.</param> /// <param name="uri">The issuer uri.</param>
/// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictServerBuilder"/> instance.</returns>
public OpenIddictServerBuilder SetIssuer(Uri address) public OpenIddictServerBuilder SetIssuer(Uri uri)
{ {
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
return Configure(options => options.Issuer = address); return Configure(options => options.Issuer = uri);
} }
/// <summary> /// <summary>

6
src/OpenIddict.Server/OpenIddictServerConfiguration.cs

@ -57,7 +57,7 @@ public sealed class OpenIddictServerConfiguration : IPostConfigureOptions<OpenId
throw new InvalidOperationException(SR.GetResourceString(SR.ID0076)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0076));
} }
var addresses = options.AuthorizationEndpointUris.Distinct() var uris = options.AuthorizationEndpointUris.Distinct()
.Concat(options.ConfigurationEndpointUris.Distinct()) .Concat(options.ConfigurationEndpointUris.Distinct())
.Concat(options.CryptographyEndpointUris.Distinct()) .Concat(options.CryptographyEndpointUris.Distinct())
.Concat(options.DeviceEndpointUris.Distinct()) .Concat(options.DeviceEndpointUris.Distinct())
@ -69,8 +69,8 @@ public sealed class OpenIddictServerConfiguration : IPostConfigureOptions<OpenId
.Concat(options.VerificationEndpointUris.Distinct()) .Concat(options.VerificationEndpointUris.Distinct())
.ToList(); .ToList();
// Ensure endpoint addresses are unique across endpoints. // Ensure endpoint URIs are unique across endpoints.
if (addresses.Count != addresses.Distinct().Count()) if (uris.Count != uris.Distinct().Count())
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID0285)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0285));
} }

18
src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs

@ -80,23 +80,23 @@ public static partial class OpenIddictServerEvents
/// <summary> /// <summary>
/// Populates the <see cref="RedirectUri"/> property with the specified redirect_uri. /// Populates the <see cref="RedirectUri"/> property with the specified redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The redirect_uri to use when redirecting the user agent.</param> /// <param name="uri">The redirect_uri to use when redirecting the user agent.</param>
public void SetRedirectUri([StringSyntax(StringSyntaxAttribute.Uri)] string address) public void SetRedirectUri([StringSyntax(StringSyntaxAttribute.Uri)] string uri)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0100), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0100), nameof(uri));
} }
// Don't allow validation to alter the redirect_uri parameter extracted // Don't allow validation to alter the redirect_uri parameter extracted
// from the request if the address was explicitly provided by the client. // from the request if the URI was explicitly provided by the client.
if (!string.IsNullOrEmpty(Request?.RedirectUri) && if (!string.IsNullOrEmpty(Request?.RedirectUri) &&
!string.Equals(Request.RedirectUri, address, StringComparison.Ordinal)) !string.Equals(Request.RedirectUri, uri, StringComparison.Ordinal))
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID0101)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0101));
} }
RedirectUri = address; RedirectUri = uri;
} }
} }
@ -206,10 +206,10 @@ public static partial class OpenIddictServerEvents
public string? Error => Response?.Error; public string? Error => Response?.Error;
/// <summary> /// <summary>
/// Gets or sets the callback URL the user agent will be redirected to, if applicable. /// Gets or sets the redirect URI the user agent will be redirected to, if applicable.
/// Note: manually changing the value of this property is generally not recommended /// Note: manually changing the value of this property is generally not recommended
/// and extreme caution must be taken to ensure the user agent is not redirected to /// and extreme caution must be taken to ensure the user agent is not redirected to
/// an untrusted address, which would result in an "open redirection" vulnerability. /// an untrusted URI, which would result in an "open redirection" vulnerability.
/// </summary> /// </summary>
public string? RedirectUri { get; set; } public string? RedirectUri { get; set; }

18
src/OpenIddict.Server/OpenIddictServerEvents.Discovery.cs

@ -87,47 +87,47 @@ public static partial class OpenIddictServerEvents
public Dictionary<string, OpenIddictParameter> Metadata { get; } = new(StringComparer.Ordinal); public Dictionary<string, OpenIddictParameter> Metadata { get; } = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Gets or sets the issuer address. /// Gets or sets the issuer URI.
/// </summary> /// </summary>
public Uri? Issuer { get; set; } public Uri? Issuer { get; set; }
/// <summary> /// <summary>
/// Gets or sets the authorization endpoint address. /// Gets or sets the authorization endpoint URI.
/// </summary> /// </summary>
public Uri? AuthorizationEndpoint { get; set; } public Uri? AuthorizationEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the JWKS endpoint address. /// Gets or sets the JWKS endpoint URI.
/// </summary> /// </summary>
public Uri? CryptographyEndpoint { get; set; } public Uri? CryptographyEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the device endpoint address. /// Gets or sets the device endpoint URI.
/// </summary> /// </summary>
public Uri? DeviceEndpoint { get; set; } public Uri? DeviceEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the introspection endpoint address. /// Gets or sets the introspection endpoint URI.
/// </summary> /// </summary>
public Uri? IntrospectionEndpoint { get; set; } public Uri? IntrospectionEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the logout endpoint address. /// Gets or sets the logout endpoint URI.
/// </summary> /// </summary>
public Uri? LogoutEndpoint { get; set; } public Uri? LogoutEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the revocation endpoint address. /// Gets or sets the revocation endpoint URI.
/// </summary> /// </summary>
public Uri? RevocationEndpoint { get; set; } public Uri? RevocationEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the token endpoint address. /// Gets or sets the token endpoint URI.
/// </summary> /// </summary>
public Uri? TokenEndpoint { get; set; } public Uri? TokenEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the userinfo endpoint address. /// Gets or sets the userinfo endpoint URI.
/// </summary> /// </summary>
public Uri? UserinfoEndpoint { get; set; } public Uri? UserinfoEndpoint { get; set; }

18
src/OpenIddict.Server/OpenIddictServerEvents.Session.cs

@ -78,23 +78,23 @@ public static partial class OpenIddictServerEvents
/// <summary> /// <summary>
/// Populates the <see cref="PostLogoutRedirectUri"/> property with the specified redirect_uri. /// Populates the <see cref="PostLogoutRedirectUri"/> property with the specified redirect_uri.
/// </summary> /// </summary>
/// <param name="address">The post_logout_redirect_uri to use when redirecting the user agent.</param> /// <param name="uri">The post_logout_redirect_uri to use when redirecting the user agent.</param>
public void SetPostLogoutRedirectUri([StringSyntax(StringSyntaxAttribute.Uri)] string address) public void SetPostLogoutRedirectUri([StringSyntax(StringSyntaxAttribute.Uri)] string uri)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0102), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0102), nameof(uri));
} }
// Don't allow validation to alter the post_logout_redirect_uri parameter extracted // Don't allow validation to alter the post_logout_redirect_uri parameter extracted
// from the request if the address was explicitly provided by the client application. // from the request if the URI was explicitly provided by the client application.
if (!string.IsNullOrEmpty(Request?.PostLogoutRedirectUri) && if (!string.IsNullOrEmpty(Request?.PostLogoutRedirectUri) &&
!string.Equals(Request.PostLogoutRedirectUri, address, StringComparison.Ordinal)) !string.Equals(Request.PostLogoutRedirectUri, uri, StringComparison.Ordinal))
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID0103)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0103));
} }
PostLogoutRedirectUri = address; PostLogoutRedirectUri = uri;
} }
} }
@ -193,10 +193,10 @@ public static partial class OpenIddictServerEvents
public string? Error => Response.Error; public string? Error => Response.Error;
/// <summary> /// <summary>
/// Gets or sets the callback URL the user agent will be redirected to, if applicable. /// Gets or sets the post-logout redirect URI the user agent will be redirected to, if applicable.
/// Note: manually changing the value of this property is generally not recommended /// Note: manually changing the value of this property is generally not recommended
/// and extreme caution must be taken to ensure the user agent is not redirected to /// and extreme caution must be taken to ensure the user agent is not redirected to
/// an untrusted address, which would result in an "open redirection" vulnerability. /// an untrusted URI, which would result in an "open redirection" vulnerability.
/// </summary> /// </summary>
public string? PostLogoutRedirectUri { get; set; } public string? PostLogoutRedirectUri { get; set; }
} }

2
src/OpenIddict.Server/OpenIddictServerEvents.cs

@ -266,7 +266,7 @@ public static partial class OpenIddictServerEvents
public string? ErrorDescription { get; set; } public string? ErrorDescription { get; set; }
/// <summary> /// <summary>
/// Gets or sets the error URL returned to the caller. /// Gets or sets the error URI returned to the caller.
/// </summary> /// </summary>
public string? ErrorUri { get; set; } public string? ErrorUri { get; set; }

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

@ -510,7 +510,7 @@ public static partial class OpenIddictServerHandlers
// See http://tools.ietf.org/html/rfc6749#section-3.1.2 // See http://tools.ietf.org/html/rfc6749#section-3.1.2
// and http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest. // and http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest.
// //
// Note: on Linux/macOS, "/path" URLs are treated as valid absolute file URLs. // Note: on Linux/macOS, "/path" URIs are treated as valid absolute file URIs.
// To ensure relative redirect_uris are correctly rejected on these platforms, // To ensure relative redirect_uris are correctly rejected on these platforms,
// an additional check using IsWellFormedOriginalString() is made here. // an additional check using IsWellFormedOriginalString() is made here.
// See https://github.com/dotnet/corefx/issues/22098 for more information. // See https://github.com/dotnet/corefx/issues/22098 for more information.
@ -1168,12 +1168,12 @@ public static partial class OpenIddictServerHandlers
var application = await _applicationManager.FindByClientIdAsync(context.ClientId) ?? var application = await _applicationManager.FindByClientIdAsync(context.ClientId) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// If no explicit redirect_uri was specified, retrieve the addresses associated with // If no explicit redirect_uri was specified, retrieve the URI associated with the
// the client and ensure exactly one redirect_uri was attached to the client definition. // client and ensure exactly one redirect_uri was attached to the client definition.
if (string.IsNullOrEmpty(context.RedirectUri)) if (string.IsNullOrEmpty(context.RedirectUri))
{ {
var addresses = await _applicationManager.GetRedirectUrisAsync(application); var uris = await _applicationManager.GetRedirectUrisAsync(application);
if (addresses.Length is not 1) if (uris.Length is not 1)
{ {
context.Logger.LogInformation(SR.GetResourceString(SR.ID6033), Parameters.RedirectUri); context.Logger.LogInformation(SR.GetResourceString(SR.ID6033), Parameters.RedirectUri);
@ -1185,7 +1185,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
context.SetRedirectUri(addresses[0]); context.SetRedirectUri(uris[0]);
return; return;
} }
@ -1782,7 +1782,7 @@ public static partial class OpenIddictServerHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for inferring the redirect URL /// Contains the logic responsible for inferring the redirect URI
/// used to send the response back to the client application. /// used to send the response back to the client application.
/// </summary> /// </summary>
public sealed class AttachRedirectUri : IOpenIddictServerHandler<ApplyAuthorizationResponseContext> public sealed class AttachRedirectUri : IOpenIddictServerHandler<ApplyAuthorizationResponseContext>
@ -1905,7 +1905,7 @@ public static partial class OpenIddictServerHandlers
/// <summary> /// <summary>
/// Contains the logic responsible for attaching an "iss" parameter /// Contains the logic responsible for attaching an "iss" parameter
/// containing the address of the authorization server to the response. /// containing the URI of the authorization server to the response.
/// </summary> /// </summary>
public sealed class AttachIssuer : IOpenIddictServerHandler<ApplyAuthorizationResponseContext> public sealed class AttachIssuer : IOpenIddictServerHandler<ApplyAuthorizationResponseContext>
{ {
@ -1928,7 +1928,7 @@ public static partial class OpenIddictServerHandlers
} }
// If the user agent is expected to be redirected to the client application, attach the // If the user agent is expected to be redirected to the client application, attach the
// issuer address to the authorization response to help the client detect mix-up attacks. // issuer URI to the authorization response to help the client detect mix-up attacks.
// //
// Note: this applies to all authorization responses, whether they represent valid or errored responses. // Note: this applies to all authorization responses, whether they represent valid or errored responses.
// For more information, see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-iss-auth-resp-05. // For more information, see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-iss-auth-resp-05.

8
src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs

@ -341,7 +341,7 @@ public static partial class OpenIddictServerHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for attaching the endpoint URLs to the provider discovery document. /// Contains the logic responsible for attaching the endpoint URIs to the provider discovery document.
/// </summary> /// </summary>
public sealed class AttachEndpoints : IOpenIddictServerHandler<HandleConfigurationRequestContext> public sealed class AttachEndpoints : IOpenIddictServerHandler<HandleConfigurationRequestContext>
{ {
@ -363,8 +363,8 @@ public static partial class OpenIddictServerHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
// Note: while OpenIddict allows specifying multiple endpoint addresses, the OAuth 2.0 // Note: while OpenIddict allows specifying multiple endpoint URIs, the OAuth 2.0
// and OpenID Connect discovery specifications only allow a single address per endpoint. // and OpenID Connect discovery specifications only allow a single URI per endpoint.
context.AuthorizationEndpoint ??= OpenIddictHelpers.CreateAbsoluteUri( context.AuthorizationEndpoint ??= OpenIddictHelpers.CreateAbsoluteUri(
context.BaseUri, context.Options.AuthorizationEndpointUris.FirstOrDefault()); context.BaseUri, context.Options.AuthorizationEndpointUris.FirstOrDefault());
@ -739,7 +739,7 @@ public static partial class OpenIddictServerHandlers
context.Metadata[Metadata.RequestParameterSupported] = false; context.Metadata[Metadata.RequestParameterSupported] = false;
context.Metadata[Metadata.RequestUriParameterSupported] = false; context.Metadata[Metadata.RequestUriParameterSupported] = false;
// As of 3.2.0, OpenIddict automatically returns an "iss" parameter containing its own address as // As of 3.2.0, OpenIddict automatically returns an "iss" parameter containing its identity as
// part of authorization responses to help clients mitigate mix-up attacks. For more information, // part of authorization responses to help clients mitigate mix-up attacks. For more information,
// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-iss-auth-resp-05. // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-iss-auth-resp-05.
context.Metadata[Metadata.AuthorizationResponseIssParameterSupported] = true; context.Metadata[Metadata.AuthorizationResponseIssParameterSupported] = true;

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

@ -1486,8 +1486,8 @@ public static partial class OpenIddictServerHandlers
// if the authorization request didn't contain an explicit redirect_uri. // if the authorization request didn't contain an explicit redirect_uri.
// See https://tools.ietf.org/html/rfc6749#section-4.1.3 // See https://tools.ietf.org/html/rfc6749#section-4.1.3
// and http://openid.net/specs/openid-connect-core-1_0.html#TokenRequestValidation. // and http://openid.net/specs/openid-connect-core-1_0.html#TokenRequestValidation.
var address = context.Principal.GetClaim(Claims.Private.RedirectUri); var uri = context.Principal.GetClaim(Claims.Private.RedirectUri);
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
return default; return default;
} }
@ -1504,7 +1504,7 @@ public static partial class OpenIddictServerHandlers
return default; return default;
} }
if (!string.Equals(address, context.Request.RedirectUri, StringComparison.Ordinal)) if (!string.Equals(uri, context.Request.RedirectUri, StringComparison.Ordinal))
{ {
context.Logger.LogInformation(SR.GetResourceString(SR.ID6092), Parameters.RedirectUri); context.Logger.LogInformation(SR.GetResourceString(SR.ID6092), Parameters.RedirectUri);

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

@ -472,7 +472,7 @@ public static partial class OpenIddictServerHandlers
// //
// * The client_id parameter is supported by the client and was explicitly sent: // * The client_id parameter is supported by the client and was explicitly sent:
// in this case, the post_logout_redirect_uris allowed for this client application // in this case, the post_logout_redirect_uris allowed for this client application
// are retrieved from the database: if one of them matches the specified address, // are retrieved from the database: if one of them matches the specified URI,
// the request is considered valid. Otherwise, it's automatically rejected. // the request is considered valid. Otherwise, it's automatically rejected.
// //
// * The client_id parameter is not supported by the client or was not explicitly sent: // * The client_id parameter is not supported by the client or was not explicitly sent:
@ -514,12 +514,12 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
async ValueTask<bool> ValidatePostLogoutRedirectUriAsync([StringSyntax(StringSyntaxAttribute.Uri)] string address) async ValueTask<bool> ValidatePostLogoutRedirectUriAsync([StringSyntax(StringSyntaxAttribute.Uri)] string uri)
{ {
// To be considered valid, a post_logout_redirect_uri must correspond to an existing client application // To be considered valid, a post_logout_redirect_uri must correspond to an existing client application
// that was granted the ept:logout permission, unless endpoint permissions checking was explicitly disabled. // that was granted the ept:logout permission, unless endpoint permissions checking was explicitly disabled.
await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync(address)) await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync(uri))
{ {
if (context.Options.IgnoreEndpointPermissions || if (context.Options.IgnoreEndpointPermissions ||
await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Logout)) await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Logout))
@ -755,12 +755,12 @@ public static partial class OpenIddictServerHandlers
} }
async ValueTask<bool> ValidateAuthorizedParty(ClaimsPrincipal principal, async ValueTask<bool> ValidateAuthorizedParty(ClaimsPrincipal principal,
[StringSyntax(StringSyntaxAttribute.Uri)] string address) [StringSyntax(StringSyntaxAttribute.Uri)] string uri)
{ {
// To be considered valid, one of the clients matching the specified post_logout_redirect_uri // To be considered valid, one of the clients matching the specified post_logout_redirect_uri
// must be listed either as an audience or as a presenter in the identity token hint. // must be listed either as an audience or as a presenter in the identity token hint.
await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync(address)) await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync(uri))
{ {
var identifier = await _applicationManager.GetClientIdAsync(application); var identifier = await _applicationManager.GetClientIdAsync(application);
if (!string.IsNullOrEmpty(identifier) && (principal.HasAudience(identifier) || if (!string.IsNullOrEmpty(identifier) && (principal.HasAudience(identifier) ||
@ -810,7 +810,7 @@ public static partial class OpenIddictServerHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for inferring the redirect URL /// Contains the logic responsible for inferring the redirect URI
/// used to send the response back to the client application. /// used to send the response back to the client application.
/// </summary> /// </summary>
public sealed class AttachPostLogoutRedirectUri : IOpenIddictServerHandler<ApplyLogoutResponseContext> public sealed class AttachPostLogoutRedirectUri : IOpenIddictServerHandler<ApplyLogoutResponseContext>

23
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -106,7 +106,7 @@ public static partial class OpenIddictServerHandlers
.AddRange(Userinfo.DefaultHandlers); .AddRange(Userinfo.DefaultHandlers);
/// <summary> /// <summary>
/// Contains the logic responsible for inferring the endpoint type from the request address. /// Contains the logic responsible for inferring the endpoint type from the request URI.
/// </summary> /// </summary>
public sealed class InferEndpointType : IOpenIddictServerHandler<ProcessRequestContext> public sealed class InferEndpointType : IOpenIddictServerHandler<ProcessRequestContext>
{ {
@ -153,14 +153,14 @@ public static partial class OpenIddictServerHandlers
return default; return default;
bool Matches(IReadOnlyList<Uri> addresses) bool Matches(IReadOnlyList<Uri> candidates)
{ {
for (var index = 0; index < addresses.Count; index++) for (var index = 0; index < candidates.Count; index++)
{ {
var address = addresses[index]; var candidate = candidates[index];
if (address.IsAbsoluteUri) if (candidate.IsAbsoluteUri)
{ {
if (Equals(address, context.RequestUri)) if (Equals(candidate, context.RequestUri))
{ {
return true; return true;
} }
@ -168,7 +168,7 @@ public static partial class OpenIddictServerHandlers
else else
{ {
var uri = OpenIddictHelpers.CreateAbsoluteUri(context.BaseUri, address); var uri = OpenIddictHelpers.CreateAbsoluteUri(context.BaseUri, candidate);
if (uri.IsWellFormedOriginalString() && if (uri.IsWellFormedOriginalString() &&
OpenIddictHelpers.IsBaseOf(context.BaseUri, uri) && Equals(uri, context.RequestUri)) OpenIddictHelpers.IsBaseOf(context.BaseUri, uri) && Equals(uri, context.RequestUri))
{ {
@ -3073,16 +3073,15 @@ public static partial class OpenIddictServerHandlers
{ {
context.Response.UserCode = context.UserCode; context.Response.UserCode = context.UserCode;
var address = OpenIddictHelpers.CreateAbsoluteUri(context.BaseUri, if (OpenIddictHelpers.CreateAbsoluteUri(context.BaseUri,
context.Options.VerificationEndpointUris.FirstOrDefault()); context.Options.VerificationEndpointUris.FirstOrDefault()) is Uri uri)
if (address is not null)
{ {
var builder = new UriBuilder(address) var builder = new UriBuilder(uri)
{ {
Query = string.Concat(Parameters.UserCode, "=", context.UserCode) Query = string.Concat(Parameters.UserCode, "=", context.UserCode)
}; };
context.Response[Parameters.VerificationUri] = address.AbsoluteUri; context.Response[Parameters.VerificationUri] = uri.AbsoluteUri;
context.Response[Parameters.VerificationUriComplete] = builder.Uri.AbsoluteUri; context.Response[Parameters.VerificationUriComplete] = builder.Uri.AbsoluteUri;
} }
} }

2
src/OpenIddict.Server/OpenIddictServerOptions.cs

@ -16,7 +16,7 @@ namespace OpenIddict.Server;
public sealed class OpenIddictServerOptions public sealed class OpenIddictServerOptions
{ {
/// <summary> /// <summary>
/// Gets or sets the optional address used to uniquely identify the authorization server. /// Gets or sets the optional URI used to uniquely identify the authorization server.
/// The URI must be absolute and may contain a path, but no query string or fragment part. /// The URI must be absolute and may contain a path, but no query string or fragment part.
/// </summary> /// </summary>
public Uri? Issuer { get; set; } public Uri? Issuer { get; set; }

2
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreBuilder.cs

@ -49,7 +49,7 @@ public sealed class OpenIddictValidationAspNetCoreBuilder
/// <summary> /// <summary>
/// Sets the realm returned to the caller as part of the WWW-Authenticate header. /// Sets the realm returned to the caller as part of the WWW-Authenticate header.
/// </summary> /// </summary>
/// <param name="realm">The issuer address.</param> /// <param name="realm">The realm.</param>
/// <returns>The <see cref="OpenIddictValidationAspNetCoreBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictValidationAspNetCoreBuilder"/> instance.</returns>
public OpenIddictValidationAspNetCoreBuilder SetRealm(string realm) public OpenIddictValidationAspNetCoreBuilder SetRealm(string realm)
{ {

2
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs

@ -96,7 +96,7 @@ public static partial class OpenIddictValidationAspNetCoreHandlers
// sent by the HTTP client) is not desirable as it would affect all requests, including requests // sent by the HTTP client) is not desirable as it would affect all requests, including requests
// that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily // that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily
// used to build an absolute base URI and a request URI that will be used to determine whether the // used to build an absolute base URI and a request URI that will be used to determine whether the
// received request matches one of the addresses assigned to an OpenIddict endpoint. If the request // received request matches one of the URIs assigned to an OpenIddict endpoint. If the request
// is later handled by OpenIddict, an additional check will be made to require the Host header. // is later handled by OpenIddict, an additional check will be made to require the Host header.
(context.BaseUri, context.RequestUri) = request.Host switch (context.BaseUri, context.RequestUri) = request.Host switch

2
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinBuilder.cs

@ -64,7 +64,7 @@ public sealed class OpenIddictValidationOwinBuilder
/// <summary> /// <summary>
/// Sets the realm returned to the caller as part of the WWW-Authenticate header. /// Sets the realm returned to the caller as part of the WWW-Authenticate header.
/// </summary> /// </summary>
/// <param name="realm">The issuer address.</param> /// <param name="realm">The realm.</param>
/// <returns>The <see cref="OpenIddictValidationOwinBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictValidationOwinBuilder"/> instance.</returns>
public OpenIddictValidationOwinBuilder SetRealm(string realm) public OpenIddictValidationOwinBuilder SetRealm(string realm)
{ {

2
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs

@ -94,7 +94,7 @@ public static partial class OpenIddictValidationOwinHandlers
// sent by the HTTP client) is not desirable as it would affect all requests, including requests // sent by the HTTP client) is not desirable as it would affect all requests, including requests
// that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily // that are not meant to be handled by OpenIddict itself. To avoid that, a fake host is temporarily
// used to build an absolute base URI and a request URI that will be used to determine whether the // used to build an absolute base URI and a request URI that will be used to determine whether the
// received request matches one of the addresses assigned to an OpenIddict endpoint. If the request // received request matches one of the URIs assigned to an OpenIddict endpoint. If the request
// is later handled by OpenIddict, an additional check will be made to require the Host header. // is later handled by OpenIddict, an additional check will be made to require the Host header.
(context.BaseUri, context.RequestUri) = request.Host switch (context.BaseUri, context.RequestUri) = request.Host switch

2
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpExtensions.cs

@ -37,7 +37,7 @@ public static class OpenIddictValidationSystemNetHttpExtensions
builder.Services.TryAdd(OpenIddictValidationSystemNetHttpHandlers.DefaultHandlers.Select(descriptor => descriptor.ServiceDescriptor)); builder.Services.TryAdd(OpenIddictValidationSystemNetHttpHandlers.DefaultHandlers.Select(descriptor => descriptor.ServiceDescriptor));
// Register the built-in filters used by the default OpenIddict System.Net.Http event handlers. // Register the built-in filters used by the default OpenIddict System.Net.Http event handlers.
builder.Services.TryAddSingleton<RequireHttpMetadataAddress>(); builder.Services.TryAddSingleton<RequireHttpMetadataUri>();
// Note: TryAddEnumerable() is used here to ensure the initializers are registered only once. // Note: TryAddEnumerable() is used here to ensure the initializers are registered only once.
builder.Services.TryAddEnumerable(new[] builder.Services.TryAddEnumerable(new[]

8
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlerFilters.cs

@ -12,9 +12,9 @@ namespace OpenIddict.Validation.SystemNetHttp;
public static class OpenIddictValidationSystemNetHttpHandlerFilters public static class OpenIddictValidationSystemNetHttpHandlerFilters
{ {
/// <summary> /// <summary>
/// Represents a filter that excludes the associated handlers if the metadata address of the issuer is not available. /// Represents a filter that excludes the associated handlers if the metadata URI of the issuer is not available.
/// </summary> /// </summary>
public sealed class RequireHttpMetadataAddress : IOpenIddictValidationHandlerFilter<BaseExternalContext> public sealed class RequireHttpMetadataUri : IOpenIddictValidationHandlerFilter<BaseExternalContext>
{ {
public ValueTask<bool> IsActiveAsync(BaseExternalContext context) public ValueTask<bool> IsActiveAsync(BaseExternalContext context)
{ {
@ -24,8 +24,8 @@ public static class OpenIddictValidationSystemNetHttpHandlerFilters
} }
return new( return new(
string.Equals(context.Address?.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) || string.Equals(context.RemoteUri?.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.Address?.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)); string.Equals(context.RemoteUri?.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase));
} }
} }
} }

2
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs

@ -46,7 +46,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<PrepareIntrospectionRequestContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<PrepareIntrospectionRequestContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachBasicAuthenticationCredentials>() .UseSingletonHandler<AttachBasicAuthenticationCredentials>()
.SetOrder(AttachFormParameters<PrepareIntrospectionRequestContext>.Descriptor.Order - 500) .SetOrder(AttachFormParameters<PrepareIntrospectionRequestContext>.Descriptor.Order - 500)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)

30
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs

@ -35,7 +35,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<PrepareGetHttpRequest<TContext>>() .UseSingletonHandler<PrepareGetHttpRequest<TContext>>()
.SetOrder(int.MinValue + 100_000) .SetOrder(int.MinValue + 100_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -51,7 +51,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
// Store the HttpRequestMessage in the transaction properties. // Store the HttpRequestMessage in the transaction properties.
context.Transaction.SetProperty(typeof(HttpRequestMessage).FullName!, context.Transaction.SetProperty(typeof(HttpRequestMessage).FullName!,
new HttpRequestMessage(HttpMethod.Get, context.Address)); new HttpRequestMessage(HttpMethod.Get, context.RemoteUri));
return default; return default;
} }
@ -67,7 +67,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<PreparePostHttpRequest<TContext>>() .UseSingletonHandler<PreparePostHttpRequest<TContext>>()
.SetOrder(PrepareGetHttpRequest<TContext>.Descriptor.Order + 1_000) .SetOrder(PrepareGetHttpRequest<TContext>.Descriptor.Order + 1_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -83,7 +83,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
// Store the HttpRequestMessage in the transaction properties. // Store the HttpRequestMessage in the transaction properties.
context.Transaction.SetProperty(typeof(HttpRequestMessage).FullName!, context.Transaction.SetProperty(typeof(HttpRequestMessage).FullName!,
new HttpRequestMessage(HttpMethod.Post, context.Address)); new HttpRequestMessage(HttpMethod.Post, context.RemoteUri));
return default; return default;
} }
@ -100,7 +100,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachJsonAcceptHeaders<TContext>>() .UseSingletonHandler<AttachJsonAcceptHeaders<TContext>>()
.SetOrder(PreparePostHttpRequest<TContext>.Descriptor.Order + 1_000) .SetOrder(PreparePostHttpRequest<TContext>.Descriptor.Order + 1_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -145,7 +145,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachUserAgentHeader<TContext>>() .UseSingletonHandler<AttachUserAgentHeader<TContext>>()
.SetOrder(AttachJsonAcceptHeaders<TContext>.Descriptor.Order + 1_000) .SetOrder(AttachJsonAcceptHeaders<TContext>.Descriptor.Order + 1_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -196,7 +196,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachQueryStringParameters<TContext>>() .UseSingletonHandler<AttachQueryStringParameters<TContext>>()
.SetOrder(AttachFormParameters<TContext>.Descriptor.Order - 1_000) .SetOrder(AttachFormParameters<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -241,7 +241,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachFormParameters<TContext>>() .UseSingletonHandler<AttachFormParameters<TContext>>()
.SetOrder(int.MaxValue - 100_000) .SetOrder(int.MaxValue - 100_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -288,7 +288,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<SendHttpRequest<TContext>>() .UseSingletonHandler<SendHttpRequest<TContext>>()
.SetOrder(DisposeHttpRequest<TContext>.Descriptor.Order - 50_000) .SetOrder(DisposeHttpRequest<TContext>.Descriptor.Order - 50_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -361,7 +361,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<DisposeHttpRequest<TContext>>() .UseSingletonHandler<DisposeHttpRequest<TContext>>()
.SetOrder(int.MaxValue - 100_000) .SetOrder(int.MaxValue - 100_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -399,7 +399,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<DecompressResponseContent<TContext>>() .UseSingletonHandler<DecompressResponseContent<TContext>>()
.SetOrder(ExtractJsonHttpResponse<TContext>.Descriptor.Order - 1_000) .SetOrder(ExtractJsonHttpResponse<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -538,7 +538,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<ExtractJsonHttpResponse<TContext>>() .UseSingletonHandler<ExtractJsonHttpResponse<TContext>>()
.SetOrder(ExtractWwwAuthenticateHeader<TContext>.Descriptor.Order - 1_000) .SetOrder(ExtractWwwAuthenticateHeader<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -606,7 +606,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<ExtractWwwAuthenticateHeader<TContext>>() .UseSingletonHandler<ExtractWwwAuthenticateHeader<TContext>>()
.SetOrder(ValidateHttpResponse<TContext>.Descriptor.Order - 1_000) .SetOrder(ValidateHttpResponse<TContext>.Descriptor.Order - 1_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -689,7 +689,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<ValidateHttpResponse<TContext>>() .UseSingletonHandler<ValidateHttpResponse<TContext>>()
.SetOrder(DisposeHttpResponse<TContext>.Descriptor.Order - 50_000) .SetOrder(DisposeHttpResponse<TContext>.Descriptor.Order - 50_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
@ -759,7 +759,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
/// </summary> /// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; } public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>() = OpenIddictValidationHandlerDescriptor.CreateBuilder<TContext>()
.AddFilter<RequireHttpMetadataAddress>() .AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<DisposeHttpResponse<TContext>>() .UseSingletonHandler<DisposeHttpResponse<TContext>>()
.SetOrder(int.MaxValue - 100_000) .SetOrder(int.MaxValue - 100_000)
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)

28
src/OpenIddict.Validation/OpenIddictValidationBuilder.cs

@ -433,40 +433,40 @@ public sealed class OpenIddictValidationBuilder
} }
/// <summary> /// <summary>
/// Sets the issuer address, which is used to determine the actual location of the /// Sets the issuer URI, which is used to determine the actual location of the
/// OAuth 2.0/OpenID Connect configuration document when using provider discovery. /// OAuth 2.0/OpenID Connect configuration document when using provider discovery.
/// </summary> /// </summary>
/// <param name="address">The issuer address.</param> /// <param name="uri">The issuer URI.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/> instance.</returns>
public OpenIddictValidationBuilder SetIssuer(Uri address) public OpenIddictValidationBuilder SetIssuer(Uri uri)
{ {
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
return Configure(options => options.Issuer = address); return Configure(options => options.Issuer = uri);
} }
/// <summary> /// <summary>
/// Sets the issuer address, which is used to determine the actual location of the /// Sets the issuer URI, which is used to determine the actual location of the
/// OAuth 2.0/OpenID Connect configuration document when using provider discovery. /// OAuth 2.0/OpenID Connect configuration document when using provider discovery.
/// </summary> /// </summary>
/// <param name="address">The issuer address.</param> /// <param name="uri">The issuer URI.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/> instance.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/> instance.</returns>
public OpenIddictValidationBuilder SetIssuer([StringSyntax(StringSyntaxAttribute.Uri)] string address) public OpenIddictValidationBuilder SetIssuer([StringSyntax(StringSyntaxAttribute.Uri)] string uri)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0126), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0126), nameof(uri));
} }
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(uri, UriKind.Absolute, out Uri? value) || !value.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0023), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0023), nameof(uri));
} }
return SetIssuer(uri); return SetIssuer(value);
} }
/// <summary> /// <summary>

31
src/OpenIddict.Validation/OpenIddictValidationConfiguration.cs

@ -40,11 +40,17 @@ public sealed class OpenIddictValidationConfiguration : IPostConfigureOptions<Op
} }
if (options.Configuration is null && options.ConfigurationManager is null && if (options.Configuration is null && options.ConfigurationManager is null &&
options.Issuer is null && options.MetadataAddress is null) options.Issuer is null && options.ConfigurationEndpoint is null)
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID0128)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0128));
} }
if (options.Issuer is not null && (!string.IsNullOrEmpty(options.Issuer.Fragment) ||
!string.IsNullOrEmpty(options.Issuer.Query)))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0137));
}
if (options.ValidationType is OpenIddictValidationType.Introspection) if (options.ValidationType is OpenIddictValidationType.Introspection)
{ {
if (!options.Handlers.Exists(static descriptor => descriptor.ContextType == typeof(ApplyIntrospectionRequestContext))) if (!options.Handlers.Exists(static descriptor => descriptor.ContextType == typeof(ApplyIntrospectionRequestContext)))
@ -52,7 +58,7 @@ public sealed class OpenIddictValidationConfiguration : IPostConfigureOptions<Op
throw new InvalidOperationException(SR.GetResourceString(SR.ID0129)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0129));
} }
if (options.Issuer is null && options.MetadataAddress is null) if (options.Issuer is null && options.ConfigurationEndpoint is null)
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID0130)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0130));
} }
@ -102,25 +108,12 @@ public sealed class OpenIddictValidationConfiguration : IPostConfigureOptions<Op
throw new InvalidOperationException(SR.GetResourceString(SR.ID0135)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0135));
} }
options.MetadataAddress ??= new Uri(".well-known/openid-configuration", UriKind.Relative); options.ConfigurationEndpoint = OpenIddictHelpers.CreateAbsoluteUri(
options.Issuer,
if (!options.MetadataAddress.IsAbsoluteUri) options.ConfigurationEndpoint ?? new Uri(".well-known/openid-configuration", UriKind.Relative));
{
if (options.Issuer is not { IsAbsoluteUri: true })
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0136));
}
if (!string.IsNullOrEmpty(options.Issuer.Fragment) || !string.IsNullOrEmpty(options.Issuer.Query))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0137));
}
options.MetadataAddress = OpenIddictHelpers.CreateAbsoluteUri(options.Issuer, options.MetadataAddress);
}
options.ConfigurationManager = new ConfigurationManager<OpenIddictConfiguration>( options.ConfigurationManager = new ConfigurationManager<OpenIddictConfiguration>(
options.MetadataAddress.AbsoluteUri, new OpenIddictValidationRetriever(_service)) options.ConfigurationEndpoint.AbsoluteUri, new OpenIddictValidationRetriever(_service))
{ {
AutomaticRefreshInterval = ConfigurationManager<OpenIddictConfiguration>.DefaultAutomaticRefreshInterval, AutomaticRefreshInterval = ConfigurationManager<OpenIddictConfiguration>.DefaultAutomaticRefreshInterval,
RefreshInterval = ConfigurationManager<OpenIddictConfiguration>.DefaultRefreshInterval RefreshInterval = ConfigurationManager<OpenIddictConfiguration>.DefaultRefreshInterval

6
src/OpenIddict.Validation/OpenIddictValidationEvents.cs

@ -130,9 +130,9 @@ public static partial class OpenIddictValidationEvents
} }
/// <summary> /// <summary>
/// Gets or sets the address of the external endpoint to communicate with. /// Gets or sets the URI of the external endpoint to communicate with.
/// </summary> /// </summary>
public Uri? Address { get; set; } public Uri? RemoteUri { get; set; }
} }
/// <summary> /// <summary>
@ -241,7 +241,7 @@ public static partial class OpenIddictValidationEvents
public string? ErrorDescription { get; set; } public string? ErrorDescription { get; set; }
/// <summary> /// <summary>
/// Gets or sets the error URL returned to the caller. /// Gets or sets the error URI returned to the caller.
/// </summary> /// </summary>
public string? ErrorUri { get; set; } public string? ErrorUri { get; set; }

24
src/OpenIddict.Validation/OpenIddictValidationHandlers.Discovery.cs

@ -179,7 +179,7 @@ public static partial class OpenIddictValidationHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
// Note: the issuer returned in the discovery document must exactly match the URL used to access it. // Note: the issuer returned in the discovery document must exactly match the URI used to access it.
// See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation. // See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation.
var issuer = (string?) context.Response[Metadata.Issuer]; var issuer = (string?) context.Response[Metadata.Issuer];
@ -193,7 +193,7 @@ public static partial class OpenIddictValidationHandlers
return default; return default;
} }
if (!Uri.TryCreate(issuer, UriKind.Absolute, out Uri? address)) if (!Uri.TryCreate(issuer, UriKind.Absolute, out Uri? uri))
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -204,7 +204,7 @@ public static partial class OpenIddictValidationHandlers
} }
// Ensure the issuer matches the expected value. // Ensure the issuer matches the expected value.
if (address != context.Options.Issuer) if (uri != context.Options.Issuer)
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -214,14 +214,14 @@ public static partial class OpenIddictValidationHandlers
return default; return default;
} }
context.Configuration.Issuer = address; context.Configuration.Issuer = uri;
return default; return default;
} }
} }
/// <summary> /// <summary>
/// Contains the logic responsible for extracting the JWKS endpoint address from the discovery document. /// Contains the logic responsible for extracting the JWKS endpoint URI from the discovery document.
/// </summary> /// </summary>
public sealed class ExtractCryptographyEndpoint : IOpenIddictValidationHandler<HandleConfigurationResponseContext> public sealed class ExtractCryptographyEndpoint : IOpenIddictValidationHandler<HandleConfigurationResponseContext>
{ {
@ -245,8 +245,8 @@ public static partial class OpenIddictValidationHandlers
// Note: the jwks_uri node is required by the OpenID Connect discovery specification. // Note: the jwks_uri node is required by the OpenID Connect discovery specification.
// See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation. // See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation.
var address = (string?) context.Response[Metadata.JwksUri]; var endpoint = (string?) context.Response[Metadata.JwksUri];
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(endpoint))
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -256,7 +256,7 @@ public static partial class OpenIddictValidationHandlers
return default; return default;
} }
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(endpoint, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -273,7 +273,7 @@ public static partial class OpenIddictValidationHandlers
} }
/// <summary> /// <summary>
/// Contains the logic responsible for extracting the introspection endpoint address from the discovery document. /// Contains the logic responsible for extracting the introspection endpoint URI from the discovery document.
/// </summary> /// </summary>
public sealed class ExtractIntrospectionEndpoint : IOpenIddictValidationHandler<HandleConfigurationResponseContext> public sealed class ExtractIntrospectionEndpoint : IOpenIddictValidationHandler<HandleConfigurationResponseContext>
{ {
@ -295,10 +295,10 @@ public static partial class OpenIddictValidationHandlers
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
var address = (string?) context.Response[Metadata.IntrospectionEndpoint]; var endpoint = (string?) context.Response[Metadata.IntrospectionEndpoint];
if (!string.IsNullOrEmpty(address)) if (!string.IsNullOrEmpty(endpoint))
{ {
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(endpoint, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,

2
src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs

@ -320,7 +320,7 @@ public static partial class OpenIddictValidationHandlers
Debug.Assert(!string.IsNullOrEmpty(context.Token), SR.GetResourceString(SR.ID4010)); Debug.Assert(!string.IsNullOrEmpty(context.Token), SR.GetResourceString(SR.ID4010));
// Ensure the introspection endpoint is present and is a valid absolute URL. // Ensure the introspection endpoint is present and is a valid absolute URI.
if (context.Configuration.IntrospectionEndpoint is not { IsAbsoluteUri: true } || if (context.Configuration.IntrospectionEndpoint is not { IsAbsoluteUri: true } ||
!context.Configuration.IntrospectionEndpoint.IsWellFormedOriginalString()) !context.Configuration.IntrospectionEndpoint.IsWellFormedOriginalString())
{ {

8
src/OpenIddict.Validation/OpenIddictValidationOptions.cs

@ -79,15 +79,15 @@ public sealed class OpenIddictValidationOptions
public bool EnableTokenEntryValidation { get; set; } public bool EnableTokenEntryValidation { get; set; }
/// <summary> /// <summary>
/// Gets or sets the absolute URL of the OAuth 2.0/OpenID Connect server. /// Gets or sets the absolute URI of the OAuth 2.0/OpenID Connect server.
/// </summary> /// </summary>
public Uri? Issuer { get; set; } public Uri? Issuer { get; set; }
/// <summary> /// <summary>
/// Gets or sets the URL of the OAuth 2.0/OpenID Connect server discovery endpoint. /// Gets or sets the URI of the configuration endpoint exposed by the server.
/// When the URL is relative, <see cref="Issuer"/> must be set and absolute. /// When the URI is relative, <see cref="Issuer"/> must be set and absolute.
/// </summary> /// </summary>
public Uri? MetadataAddress { get; set; } public Uri? ConfigurationEndpoint { get; set; }
/// <summary> /// <summary>
/// Gets or sets the OAuth 2.0/OpenID Connect static server configuration, if applicable. /// Gets or sets the OAuth 2.0/OpenID Connect static server configuration, if applicable.

74
src/OpenIddict.Validation/OpenIddictValidationService.cs

@ -93,21 +93,21 @@ public sealed class OpenIddictValidationService
} }
/// <summary> /// <summary>
/// Retrieves the OpenID Connect server configuration from the specified address. /// Retrieves the OpenID Connect server configuration from the specified URI.
/// </summary> /// </summary>
/// <param name="address">The address of the remote metadata endpoint.</param> /// <param name="uri">The URI of the remote metadata endpoint.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The OpenID Connect server configuration retrieved from the remote server.</returns> /// <returns>The OpenID Connect server configuration retrieved from the remote server.</returns>
internal async ValueTask<OpenIddictConfiguration> GetConfigurationAsync(Uri address, CancellationToken cancellationToken = default) internal async ValueTask<OpenIddictConfiguration> GetConfigurationAsync(Uri uri, CancellationToken cancellationToken = default)
{ {
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
if (!address.IsAbsoluteUri) if (!uri.IsAbsoluteUri)
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
} }
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@ -137,7 +137,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new PrepareConfigurationRequestContext(transaction) var context = new PrepareConfigurationRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Request = request Request = request
}; };
@ -157,7 +157,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new ApplyConfigurationRequestContext(transaction) var context = new ApplyConfigurationRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Request = request Request = request
}; };
@ -170,7 +170,7 @@ public sealed class OpenIddictValidationService
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.Address, context.Request); context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.RemoteUri, context.Request);
return context.Request; return context.Request;
} }
@ -179,7 +179,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new ExtractConfigurationResponseContext(transaction) var context = new ExtractConfigurationResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Request = request Request = request
}; };
@ -194,7 +194,7 @@ public sealed class OpenIddictValidationService
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007));
context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.Address, context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.RemoteUri, context.Response);
return context.Response; return context.Response;
} }
@ -203,7 +203,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new HandleConfigurationResponseContext(transaction) var context = new HandleConfigurationResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Request = request, Request = request,
Response = response Response = response
}; };
@ -238,19 +238,19 @@ public sealed class OpenIddictValidationService
/// <summary> /// <summary>
/// Retrieves the security keys exposed by the specified JWKS endpoint. /// Retrieves the security keys exposed by the specified JWKS endpoint.
/// </summary> /// </summary>
/// <param name="address">The address of the remote metadata endpoint.</param> /// <param name="uri">The URI of the remote metadata endpoint.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The security keys retrieved from the remote server.</returns> /// <returns>The security keys retrieved from the remote server.</returns>
internal async ValueTask<JsonWebKeySet> GetSecurityKeysAsync(Uri address, CancellationToken cancellationToken = default) internal async ValueTask<JsonWebKeySet> GetSecurityKeysAsync(Uri uri, CancellationToken cancellationToken = default)
{ {
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
if (!address.IsAbsoluteUri) if (!uri.IsAbsoluteUri)
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
} }
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@ -281,7 +281,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new PrepareCryptographyRequestContext(transaction) var context = new PrepareCryptographyRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Request = request Request = request
}; };
@ -301,7 +301,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new ApplyCryptographyRequestContext(transaction) var context = new ApplyCryptographyRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Request = request Request = request
}; };
@ -314,7 +314,7 @@ public sealed class OpenIddictValidationService
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.Address, context.Request); context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.RemoteUri, context.Request);
return context.Request; return context.Request;
} }
@ -323,7 +323,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new ExtractCryptographyResponseContext(transaction) var context = new ExtractCryptographyResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Request = request Request = request
}; };
@ -338,7 +338,7 @@ public sealed class OpenIddictValidationService
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007));
context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.Address, context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.RemoteUri, context.Response);
return context.Response; return context.Response;
} }
@ -379,24 +379,24 @@ public sealed class OpenIddictValidationService
} }
/// <summary> /// <summary>
/// Sends an introspection request to the specified address and returns the corresponding principal. /// Sends an introspection request to the specified URI and returns the corresponding principal.
/// </summary> /// </summary>
/// <param name="address">The address of the remote metadata endpoint.</param> /// <param name="uri">The URI of the remote metadata endpoint.</param>
/// <param name="token">The token to introspect.</param> /// <param name="token">The token to introspect.</param>
/// <param name="hint">The token type to introspect, used as a hint by the authorization server.</param> /// <param name="hint">The token type to introspect, used as a hint by the authorization server.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The claims principal created from the claim retrieved from the remote server.</returns> /// <returns>The claims principal created from the claim retrieved from the remote server.</returns>
internal async ValueTask<ClaimsPrincipal> IntrospectTokenAsync( internal async ValueTask<ClaimsPrincipal> IntrospectTokenAsync(
Uri address, string token, string? hint, CancellationToken cancellationToken = default) Uri uri, string token, string? hint, CancellationToken cancellationToken = default)
{ {
if (address is null) if (uri is null)
{ {
throw new ArgumentNullException(nameof(address)); throw new ArgumentNullException(nameof(uri));
} }
if (!address.IsAbsoluteUri || !address.IsWellFormedOriginalString()) if (!uri.IsAbsoluteUri || !uri.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
} }
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
@ -435,7 +435,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new PrepareIntrospectionRequestContext(transaction) var context = new PrepareIntrospectionRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Request = request, Request = request,
Token = token, Token = token,
@ -458,7 +458,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new ApplyIntrospectionRequestContext(transaction) var context = new ApplyIntrospectionRequestContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Request = request Request = request
}; };
@ -472,7 +472,7 @@ public sealed class OpenIddictValidationService
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID6190), context.Address, context.Request); context.Logger.LogInformation(SR.GetResourceString(SR.ID6190), context.RemoteUri, context.Request);
return context.Request; return context.Request;
} }
@ -481,7 +481,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new ExtractIntrospectionResponseContext(transaction) var context = new ExtractIntrospectionResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Request = request Request = request
}; };
@ -497,7 +497,7 @@ public sealed class OpenIddictValidationService
Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007));
context.Logger.LogInformation(SR.GetResourceString(SR.ID6191), context.Address, context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID6191), context.RemoteUri, context.Response);
return context.Response; return context.Response;
} }
@ -506,7 +506,7 @@ public sealed class OpenIddictValidationService
{ {
var context = new HandleIntrospectionResponseContext(transaction) var context = new HandleIntrospectionResponseContext(transaction)
{ {
Address = address, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Request = request, Request = request,
Response = response, Response = response,

12
test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs

@ -269,7 +269,7 @@ public partial class OpenIddictServerAspNetCoreIntegrationTests : OpenIddictServ
[InlineData("/connect/token")] [InlineData("/connect/token")]
[InlineData("/connect/userinfo")] [InlineData("/connect/userinfo")]
[InlineData("/connect/verification")] [InlineData("/connect/verification")]
public async Task ProcessRequest_RejectsInsecureHttpRequests(string address) public async Task ProcessRequest_RejectsInsecureHttpRequests(string uri)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(options => await using var server = await CreateServerAsync(options =>
@ -283,7 +283,7 @@ public partial class OpenIddictServerAspNetCoreIntegrationTests : OpenIddictServ
await using var client = await server.CreateClientAsync(); await using var client = await server.CreateClientAsync();
// Act // Act
var response = await client.PostAsync(address, new OpenIddictRequest()); var response = await client.PostAsync(uri, new OpenIddictRequest());
// Assert // Assert
Assert.Equal(Errors.InvalidRequest, response.Error); Assert.Equal(Errors.InvalidRequest, response.Error);
@ -303,7 +303,7 @@ public partial class OpenIddictServerAspNetCoreIntegrationTests : OpenIddictServ
[InlineData("/connect/token")] [InlineData("/connect/token")]
[InlineData("/connect/userinfo")] [InlineData("/connect/userinfo")]
[InlineData("/connect/verification")] [InlineData("/connect/verification")]
public async Task ProcessRequest_AllowsHandlingResponse(string address) public async Task ProcessRequest_AllowsHandlingResponse(string uri)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(options => await using var server = await CreateServerAsync(options =>
@ -327,7 +327,7 @@ public partial class OpenIddictServerAspNetCoreIntegrationTests : OpenIddictServ
await using var client = await server.CreateClientAsync(); await using var client = await server.CreateClientAsync();
// Act // Act
var response = await client.PostAsync(address, new OpenIddictRequest()); var response = await client.PostAsync(uri, new OpenIddictRequest());
// Assert // Assert
Assert.Equal("Bob le Bricoleur", (string?) response["name"]); Assert.Equal("Bob le Bricoleur", (string?) response["name"]);
@ -345,7 +345,7 @@ public partial class OpenIddictServerAspNetCoreIntegrationTests : OpenIddictServ
[InlineData("/connect/token")] [InlineData("/connect/token")]
[InlineData("/connect/userinfo")] [InlineData("/connect/userinfo")]
[InlineData("/connect/verification")] [InlineData("/connect/verification")]
public async Task ProcessRequest_AllowsSkippingHandler(string address) public async Task ProcessRequest_AllowsSkippingHandler(string uri)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(options => await using var server = await CreateServerAsync(options =>
@ -364,7 +364,7 @@ public partial class OpenIddictServerAspNetCoreIntegrationTests : OpenIddictServ
await using var client = await server.CreateClientAsync(); await using var client = await server.CreateClientAsync();
// Act // Act
var response = await client.PostAsync(address, new OpenIddictRequest()); var response = await client.PostAsync(uri, new OpenIddictRequest());
// Assert // Assert
Assert.Equal("Bob le Magnifique", (string?) response["name"]); Assert.Equal("Bob le Magnifique", (string?) response["name"]);

10
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs

@ -91,7 +91,7 @@ public class OpenIddictServerIntegrationTestClient : IAsyncDisposable
if (string.IsNullOrEmpty(uri)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException("The URL cannot be null or empty.", nameof(uri)); throw new ArgumentException("The URI cannot be null or empty.", nameof(uri));
} }
return GetAsync(new Uri(uri, UriKind.RelativeOrAbsolute), request); return GetAsync(new Uri(uri, UriKind.RelativeOrAbsolute), request);
@ -123,7 +123,7 @@ public class OpenIddictServerIntegrationTestClient : IAsyncDisposable
if (string.IsNullOrEmpty(uri)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException("The URL cannot be null or empty.", nameof(uri)); throw new ArgumentException("The URI cannot be null or empty.", nameof(uri));
} }
return PostAsync(new Uri(uri, UriKind.RelativeOrAbsolute), request); return PostAsync(new Uri(uri, UriKind.RelativeOrAbsolute), request);
@ -161,7 +161,7 @@ public class OpenIddictServerIntegrationTestClient : IAsyncDisposable
if (string.IsNullOrEmpty(uri)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException("The URL cannot be null or empty.", nameof(uri)); throw new ArgumentException("The URI cannot be null or empty.", nameof(uri));
} }
return SendAsync(new HttpMethod(method), uri, request); return SendAsync(new HttpMethod(method), uri, request);
@ -189,7 +189,7 @@ public class OpenIddictServerIntegrationTestClient : IAsyncDisposable
if (string.IsNullOrEmpty(uri)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException("The URL cannot be null or empty.", nameof(uri)); throw new ArgumentException("The URI cannot be null or empty.", nameof(uri));
} }
return SendAsync(method, new Uri(uri, UriKind.RelativeOrAbsolute), request); return SendAsync(method, new Uri(uri, UriKind.RelativeOrAbsolute), request);
@ -222,7 +222,7 @@ public class OpenIddictServerIntegrationTestClient : IAsyncDisposable
if (HttpClient.BaseAddress is null && !uri.IsAbsoluteUri) if (HttpClient.BaseAddress is null && !uri.IsAbsoluteUri)
{ {
throw new ArgumentException("The address cannot be a relative URI when no base address " + throw new ArgumentException("The URI cannot be a relative URI when no base URI " +
"is associated with the HTTP client.", nameof(uri)); "is associated with the HTTP client.", nameof(uri));
} }

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

@ -222,7 +222,7 @@ public abstract partial class OpenIddictServerIntegrationTests
[InlineData("/tmp/file.xml", SR.ID2030)] [InlineData("/tmp/file.xml", SR.ID2030)]
[InlineData("C:\\tmp\\file.xml", SR.ID2030)] [InlineData("C:\\tmp\\file.xml", SR.ID2030)]
[InlineData("http://www.fabrikam.com/path#param=value", SR.ID2031)] [InlineData("http://www.fabrikam.com/path#param=value", SR.ID2031)]
public async Task ValidateAuthorizationRequest_InvalidRedirectUriCausesAnError(string address, string message) public async Task ValidateAuthorizationRequest_InvalidRedirectUriCausesAnError(string uri, string message)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(options => options.EnableDegradedMode()); await using var server = await CreateServerAsync(options => options.EnableDegradedMode());
@ -232,7 +232,7 @@ public abstract partial class OpenIddictServerIntegrationTests
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{ {
ClientId = "Fabrikam", ClientId = "Fabrikam",
RedirectUri = address, RedirectUri = uri,
Scope = Scopes.OpenId Scope = Scopes.OpenId
}); });
@ -257,7 +257,7 @@ public abstract partial class OpenIddictServerIntegrationTests
[InlineData("http://www.fabrikam.com/path?state=abc;iss=value")] [InlineData("http://www.fabrikam.com/path?state=abc;iss=value")]
[InlineData("http://www.fabrikam.com/path?state=abc&iss")] [InlineData("http://www.fabrikam.com/path?state=abc&iss")]
[InlineData("http://www.fabrikam.com/path?state=abc&iss=value")] [InlineData("http://www.fabrikam.com/path?state=abc&iss=value")]
public async Task ValidateAuthorizationRequest_RedirectUriWithIssuerParameterCausesAnError(string address) public async Task ValidateAuthorizationRequest_RedirectUriWithIssuerParameterCausesAnError(string uri)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(options => options.EnableDegradedMode()); await using var server = await CreateServerAsync(options => options.EnableDegradedMode());
@ -267,7 +267,7 @@ public abstract partial class OpenIddictServerIntegrationTests
var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest
{ {
ClientId = "Fabrikam", ClientId = "Fabrikam",
RedirectUri = address, RedirectUri = uri,
Scope = Scopes.OpenId Scope = Scopes.OpenId
}); });

4
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Session.cs

@ -134,7 +134,7 @@ public abstract partial class OpenIddictServerIntegrationTests
[InlineData("/tmp/file.xml", SR.ID2030)] [InlineData("/tmp/file.xml", SR.ID2030)]
[InlineData("C:\\tmp\\file.xml", SR.ID2030)] [InlineData("C:\\tmp\\file.xml", SR.ID2030)]
[InlineData("http://www.fabrikam.com/path#param=value", SR.ID2031)] [InlineData("http://www.fabrikam.com/path#param=value", SR.ID2031)]
public async Task ValidateLogoutRequest_InvalidRedirectUriCausesAnError(string address, string message) public async Task ValidateLogoutRequest_InvalidRedirectUriCausesAnError(string uri, string message)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(); await using var server = await CreateServerAsync();
@ -143,7 +143,7 @@ public abstract partial class OpenIddictServerIntegrationTests
// Act // Act
var response = await client.PostAsync("/connect/logout", new OpenIddictRequest var response = await client.PostAsync("/connect/logout", new OpenIddictRequest
{ {
PostLogoutRedirectUri = address PostLogoutRedirectUri = uri
}); });
// Assert // Assert

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

@ -391,7 +391,7 @@ public abstract partial class OpenIddictServerIntegrationTests
[InlineData("/custom/connect/token", OpenIddictServerEndpointType.Token)] [InlineData("/custom/connect/token", OpenIddictServerEndpointType.Token)]
[InlineData("/custom/connect/userinfo", OpenIddictServerEndpointType.Userinfo)] [InlineData("/custom/connect/userinfo", OpenIddictServerEndpointType.Userinfo)]
[InlineData("/custom/connect/verification", OpenIddictServerEndpointType.Verification)] [InlineData("/custom/connect/verification", OpenIddictServerEndpointType.Verification)]
public async Task ProcessRequest_AllowsOverridingEndpoint(string address, OpenIddictServerEndpointType type) public async Task ProcessRequest_AllowsOverridingEndpoint(string uri, OpenIddictServerEndpointType type)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(options => await using var server = await CreateServerAsync(options =>
@ -434,7 +434,7 @@ public abstract partial class OpenIddictServerIntegrationTests
await using var client = await server.CreateClientAsync(); await using var client = await server.CreateClientAsync();
// Act // Act
await client.PostAsync(address, new OpenIddictRequest()); await client.PostAsync(uri, new OpenIddictRequest());
} }
[Fact] [Fact]

12
test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs

@ -254,7 +254,7 @@ public partial class OpenIddictServerOwinIntegrationTests : OpenIddictServerInte
[InlineData("/connect/token")] [InlineData("/connect/token")]
[InlineData("/connect/userinfo")] [InlineData("/connect/userinfo")]
[InlineData("/connect/verification")] [InlineData("/connect/verification")]
public async Task ProcessRequest_RejectsInsecureHttpRequests(string address) public async Task ProcessRequest_RejectsInsecureHttpRequests(string uri)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(options => await using var server = await CreateServerAsync(options =>
@ -268,7 +268,7 @@ public partial class OpenIddictServerOwinIntegrationTests : OpenIddictServerInte
await using var client = await server.CreateClientAsync(); await using var client = await server.CreateClientAsync();
// Act // Act
var response = await client.PostAsync(address, new OpenIddictRequest()); var response = await client.PostAsync(uri, new OpenIddictRequest());
// Assert // Assert
Assert.Equal(Errors.InvalidRequest, response.Error); Assert.Equal(Errors.InvalidRequest, response.Error);
@ -288,7 +288,7 @@ public partial class OpenIddictServerOwinIntegrationTests : OpenIddictServerInte
[InlineData("/connect/token")] [InlineData("/connect/token")]
[InlineData("/connect/userinfo")] [InlineData("/connect/userinfo")]
[InlineData("/connect/verification")] [InlineData("/connect/verification")]
public async Task ProcessRequest_AllowsHandlingResponse(string address) public async Task ProcessRequest_AllowsHandlingResponse(string uri)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(options => await using var server = await CreateServerAsync(options =>
@ -312,7 +312,7 @@ public partial class OpenIddictServerOwinIntegrationTests : OpenIddictServerInte
await using var client = await server.CreateClientAsync(); await using var client = await server.CreateClientAsync();
// Act // Act
var response = await client.PostAsync(address, new OpenIddictRequest()); var response = await client.PostAsync(uri, new OpenIddictRequest());
// Assert // Assert
Assert.Equal("Bob le Bricoleur", (string?) response["name"]); Assert.Equal("Bob le Bricoleur", (string?) response["name"]);
@ -330,7 +330,7 @@ public partial class OpenIddictServerOwinIntegrationTests : OpenIddictServerInte
[InlineData("/connect/token")] [InlineData("/connect/token")]
[InlineData("/connect/userinfo")] [InlineData("/connect/userinfo")]
[InlineData("/connect/verification")] [InlineData("/connect/verification")]
public async Task ProcessRequest_AllowsSkippingHandler(string address) public async Task ProcessRequest_AllowsSkippingHandler(string uri)
{ {
// Arrange // Arrange
await using var server = await CreateServerAsync(options => await using var server = await CreateServerAsync(options =>
@ -349,7 +349,7 @@ public partial class OpenIddictServerOwinIntegrationTests : OpenIddictServerInte
await using var client = await server.CreateClientAsync(); await using var client = await server.CreateClientAsync();
// Act // Act
var response = await client.PostAsync(address, new OpenIddictRequest()); var response = await client.PostAsync(uri, new OpenIddictRequest());
// Assert // Assert
Assert.Equal("Bob le Magnifique", (string?) response["name"]); Assert.Equal("Bob le Magnifique", (string?) response["name"]);

164
test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs

@ -753,27 +753,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetAuthorizationEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetAuthorizationEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetAuthorizationEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetAuthorizationEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetAuthorizationEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetAuthorizationEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetAuthorizationEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetAuthorizationEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -786,7 +786,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetAuthorizationEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetAuthorizationEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -800,7 +800,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetAuthorizationEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetAuthorizationEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -837,27 +837,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetConfigurationEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetConfigurationEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetConfigurationEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetConfigurationEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetConfigurationEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetConfigurationEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetConfigurationEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetConfigurationEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -870,7 +870,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetConfigurationEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetConfigurationEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -884,7 +884,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetConfigurationEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetConfigurationEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -921,27 +921,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetCryptographyEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetCryptographyEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetCryptographyEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetCryptographyEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetCryptographyEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetCryptographyEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetCryptographyEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetCryptographyEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -954,7 +954,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetCryptographyEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetCryptographyEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -968,7 +968,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetCryptographyEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetCryptographyEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -1005,27 +1005,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetDeviceEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetDeviceEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetDeviceEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetDeviceEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetDeviceEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetDeviceEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetDeviceEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetDeviceEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -1038,7 +1038,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetDeviceEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetDeviceEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -1052,7 +1052,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetDeviceEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetDeviceEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -1089,27 +1089,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetIntrospectionEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetIntrospectionEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetIntrospectionEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetIntrospectionEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetIntrospectionEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetIntrospectionEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetIntrospectionEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetIntrospectionEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -1122,7 +1122,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetIntrospectionEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetIntrospectionEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -1136,7 +1136,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetIntrospectionEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetIntrospectionEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -1173,27 +1173,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetLogoutEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetLogoutEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetLogoutEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetLogoutEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetLogoutEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetLogoutEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetLogoutEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetLogoutEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -1206,7 +1206,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetLogoutEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetLogoutEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -1220,7 +1220,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetLogoutEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetLogoutEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -1257,27 +1257,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetRevocationEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetRevocationEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetRevocationEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetRevocationEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetRevocationEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetRevocationEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetRevocationEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetRevocationEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -1290,7 +1290,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetRevocationEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetRevocationEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -1304,7 +1304,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetRevocationEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetRevocationEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -1341,27 +1341,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetTokenEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetTokenEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetTokenEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetTokenEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetTokenEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetTokenEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetTokenEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetTokenEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -1374,7 +1374,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetTokenEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetTokenEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -1388,7 +1388,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetTokenEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetTokenEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -1425,27 +1425,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetUserinfoEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetUserinfoEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetUserinfoEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetUserinfoEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetUserinfoEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetUserinfoEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetUserinfoEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetUserinfoEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -1458,7 +1458,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetUserinfoEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetUserinfoEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -1472,7 +1472,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetUserinfoEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetUserinfoEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -1509,27 +1509,27 @@ public class OpenIddictServerBuilderTests
} }
[Fact] [Fact]
public void SetVerificationEndpointUris_ThrowsExceptionWhenAddressesIsNull() public void SetVerificationEndpointUris_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetVerificationEndpointUris(addresses: (null as Uri[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetVerificationEndpointUris(uris: (null as Uri[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Fact] [Fact]
public void SetVerificationEndpointUris_Strings_ThrowsExceptionWhenAddressesIsNull() public void SetVerificationEndpointUris_Strings_ThrowsExceptionWhenUrisIsNull()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();
var builder = CreateBuilder(services); var builder = CreateBuilder(services);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetVerificationEndpointUris(addresses: (null as string[])!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetVerificationEndpointUris(uris: (null as string[])!));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
} }
[Theory] [Theory]
@ -1542,7 +1542,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetVerificationEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetVerificationEndpointUris(new Uri(uri)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message);
} }
@ -1556,7 +1556,7 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetVerificationEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetVerificationEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("addresses", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message);
} }
@ -1810,11 +1810,11 @@ public class OpenIddictServerBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => builder.SetIssuer(null!)); var exception = Assert.Throws<ArgumentNullException>(() => builder.SetIssuer(null!));
Assert.Equal("address", exception.ParamName); Assert.Equal("uri", exception.ParamName);
} }
[Fact] [Fact]
public void SetIssuer_AddressIsReplaced() public void SetIssuer_IssuerIsReplaced()
{ {
// Arrange // Arrange
var services = CreateServices(); var services = CreateServices();

10
test/OpenIddict.Validation.IntegrationTests/OpenIddictValidationIntegrationTestClient.cs

@ -91,7 +91,7 @@ public class OpenIddictValidationIntegrationTestClient : IAsyncDisposable
if (string.IsNullOrEmpty(uri)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException("The URL cannot be null or empty.", nameof(uri)); throw new ArgumentException("The URI cannot be null or empty.", nameof(uri));
} }
return GetAsync(new Uri(uri, UriKind.RelativeOrAbsolute), request); return GetAsync(new Uri(uri, UriKind.RelativeOrAbsolute), request);
@ -123,7 +123,7 @@ public class OpenIddictValidationIntegrationTestClient : IAsyncDisposable
if (string.IsNullOrEmpty(uri)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException("The URL cannot be null or empty.", nameof(uri)); throw new ArgumentException("The URI cannot be null or empty.", nameof(uri));
} }
return PostAsync(new Uri(uri, UriKind.RelativeOrAbsolute), request); return PostAsync(new Uri(uri, UriKind.RelativeOrAbsolute), request);
@ -161,7 +161,7 @@ public class OpenIddictValidationIntegrationTestClient : IAsyncDisposable
if (string.IsNullOrEmpty(uri)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException("The URL cannot be null or empty.", nameof(uri)); throw new ArgumentException("The URI cannot be null or empty.", nameof(uri));
} }
return SendAsync(new HttpMethod(method), uri, request); return SendAsync(new HttpMethod(method), uri, request);
@ -189,7 +189,7 @@ public class OpenIddictValidationIntegrationTestClient : IAsyncDisposable
if (string.IsNullOrEmpty(uri)) if (string.IsNullOrEmpty(uri))
{ {
throw new ArgumentException("The URL cannot be null or empty.", nameof(uri)); throw new ArgumentException("The URI cannot be null or empty.", nameof(uri));
} }
return SendAsync(method, new Uri(uri, UriKind.RelativeOrAbsolute), request); return SendAsync(method, new Uri(uri, UriKind.RelativeOrAbsolute), request);
@ -222,7 +222,7 @@ public class OpenIddictValidationIntegrationTestClient : IAsyncDisposable
if (HttpClient.BaseAddress is null && !uri.IsAbsoluteUri) if (HttpClient.BaseAddress is null && !uri.IsAbsoluteUri)
{ {
throw new ArgumentException("The address cannot be a relative URI when no base address " + throw new ArgumentException("The URI cannot be a relative URI when no base URI " +
"is associated with the HTTP client.", nameof(uri)); "is associated with the HTTP client.", nameof(uri));
} }

Loading…
Cancel
Save