Browse Source

Reference Meziantou.Analyzer globally and address the existing warnings

pull/2521/head
Kévin Chalet 2 months ago
parent
commit
e7a5611891
  1. 14
      .editorconfig
  2. 7
      Directory.Packages.props
  3. 4
      gen/OpenIddict.Client.WebIntegration.Generators/OpenIddictClientWebIntegrationGenerator.cs
  4. 8
      sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/AuthenticationController.cs
  5. 2
      sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthenticationController.cs
  6. 16
      sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthorizationController.cs
  7. 2
      sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ManageController.cs
  8. 7
      sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ResourceController.cs
  9. 6
      sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/AuthenticationController.cs
  10. 40
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AccountController.cs
  11. 37
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AuthorizationController.cs
  12. 2
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ManageController.cs
  13. 4
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ResourceController.cs
  14. 2
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/UserinfoController.cs
  15. 4
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/Program.cs
  16. 18
      sandbox/OpenIddict.Sandbox.Console.Client/InteractiveService.cs
  17. 2
      sandbox/OpenIddict.Sandbox.Maui.Client/MainPage.xaml.cs
  18. 2
      sandbox/OpenIddict.Sandbox.Maui.Client/MauiProgram.cs
  19. 2
      sandbox/OpenIddict.Sandbox.WinForms.Client/MainForm.cs
  20. 2
      sandbox/OpenIddict.Sandbox.Wpf.Client/MainWindow.xaml.cs
  21. 10
      shared/OpenIddict.Extensions/OpenIddictHelpers.cs
  22. 1
      src/OpenIddict.Abstractions/OpenIddictConstants.cs
  23. 18
      src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
  24. 2
      src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs
  25. 14
      src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs
  26. 4
      src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs
  27. 6
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs
  28. 6
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreForwarder.cs
  29. 12
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs
  30. 3
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs
  31. 2
      src/OpenIddict.Client.DataProtection/OpenIddictClientDataProtectionFormatter.cs
  32. 4
      src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs
  33. 16
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs
  34. 3
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs
  35. 12
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
  36. 12
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
  37. 4
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs
  38. 2
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationMarshal.cs
  39. 7
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
  40. 2
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationExtensions.cs
  41. 2
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs
  42. 2
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Introspection.cs
  43. 32
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
  44. 2
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationOptions.cs
  45. 24
      src/OpenIddict.Client/OpenIddictClientHandlers.Authentication.cs
  46. 4
      src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs
  47. 24
      src/OpenIddict.Client/OpenIddictClientHandlers.Session.cs
  48. 92
      src/OpenIddict.Client/OpenIddictClientHandlers.cs
  49. 76
      src/OpenIddict.Client/OpenIddictClientService.cs
  50. 10
      src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
  51. 2
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  52. 21
      src/OpenIddict.Core/Managers/OpenIddictResourceManager.cs
  53. 22
      src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
  54. 32
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
  55. 28
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
  56. 30
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkResourceStore.cs
  57. 30
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs
  58. 28
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkSessionStore.cs
  59. 32
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs
  60. 16
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs
  61. 16
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs
  62. 18
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreResourceStore.cs
  63. 20
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs
  64. 16
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreSessionStore.cs
  65. 20
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs
  66. 2
      src/OpenIddict.MongoDb.Models/OpenIddictMongoDbSession.cs
  67. 6
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs
  68. 6
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs
  69. 8
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbResourceStore.cs
  70. 8
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs
  71. 6
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbSessionStore.cs
  72. 10
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs
  73. 14
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs
  74. 6
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs
  75. 2
      src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs
  76. 14
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs
  77. 6
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs
  78. 48
      src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
  79. 44
      src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs
  80. 30
      src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
  81. 30
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  82. 22
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  83. 6
      src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs
  84. 18
      src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
  85. 26
      src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs
  86. 18
      src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs
  87. 94
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  88. 10
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs
  89. 4
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs
  90. 10
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs
  91. 4
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs
  92. 7
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs
  93. 2
      src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs
  94. 8
      src/OpenIddict.Validation/OpenIddictValidationHandlers.cs
  95. 2
      test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs
  96. 164
      test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs
  97. 8
      test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs
  98. 22
      test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs
  99. 8
      test/OpenIddict.Client.Tests/OpenIddictClientBuilderTests.cs
  100. 30
      test/OpenIddict.Client.Tests/OpenIddictClientConfigurationTests.cs

14
.editorconfig

@ -95,10 +95,22 @@ csharp_using_directive_placement = outside_namespace
[*.{cs,vb}] [*.{cs,vb}]
dotnet_code_quality_unused_parameters = all dotnet_code_quality_unused_parameters = all
dotnet_diagnostic.CA1510.severity = suggestion dotnet_diagnostic.CA1510.severity = none
dotnet_diagnostic.CA1873.severity = none
dotnet_diagnostic.CA2254.severity = none dotnet_diagnostic.CA2254.severity = none
dotnet_diagnostic.IDE0002.severity = none dotnet_diagnostic.IDE0002.severity = none
dotnet_diagnostic.IDE0042.severity = none
dotnet_diagnostic.IDE0305.severity = none dotnet_diagnostic.IDE0305.severity = none
dotnet_diagnostic.MA0003.severity = none
dotnet_diagnostic.MA0004.severity = none
dotnet_diagnostic.MA0007.severity = none
dotnet_diagnostic.MA0016.severity = none
dotnet_diagnostic.MA0029.severity = none
dotnet_diagnostic.MA0048.severity = none
dotnet_diagnostic.MA0051.severity = none
dotnet_diagnostic.MA0056.severity = none
dotnet_diagnostic.MA0084.severity = none
dotnet_diagnostic.MA0100.severity = none
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface

7
Directory.Packages.props

@ -4,17 +4,14 @@
Note: to cover as many platforms as possible and reduce the number of package references, Note: to cover as many platforms as possible and reduce the number of package references,
OpenIddict extensively uses multi-targeting and per-framework package references. As such, OpenIddict extensively uses multi-targeting and per-framework package references. As such,
package versions must be carefully chosen to ensure they are consistent and compatible with package versions must be carefully chosen to ensure they are consistent and compatible with
the TFMs supported by OpenIddict (e.g for .NET 10, only Microsoft.AspNetCore.* packages within the TFMs supported by OpenIddict (e.g for .NET 10, only Microsoft.Extensions.* packages within
the [10.0.0,11.0.0) range are allowed). Special care must also be taken when selecting versions the [10.0.0,11.0.0) range are allowed). Special care must also be taken when selecting versions
to ensure that transitive references also respect the same constraints (e.g for the .NET 10 TFM, to ensure that transitive references also respect the same constraints (e.g for the .NET 10 TFM,
a package must only depend on Microsoft.Extensions.* packages within the [10.0.0,11.0.0) range). a package must only depend on Microsoft.Extensions.* packages within the [10.0.0,11.0.0) range).
--> -->
<!--
Note: OpenIddict uses Meziantou.Polyfill to dynamically generate polyfills for types that are not available
on some of the targeted TFMs (e.g Index, Range or nullable attributes on .NET Framework/.NET Standard).
-->
<ItemGroup Label="Package versions for all targets"> <ItemGroup Label="Package versions for all targets">
<GlobalPackageReference Include="Meziantou.Analyzer" Version="3.0.136" />
<GlobalPackageReference Include="Meziantou.Polyfill" Version="1.0.158" /> <GlobalPackageReference Include="Meziantou.Polyfill" Version="1.0.158" />
</ItemGroup> </ItemGroup>

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

@ -897,7 +897,7 @@ public static partial class OpenIddictClientWebIntegrationConstants
Name = (string) constant.Attribute("Name"), Name = (string) constant.Attribute("Name"),
Value = (string) constant.Attribute("Value") Value = (string) constant.Attribute("Value")
}) })
.GroupBy(static constant => constant.Class) .GroupBy(static constant => constant.Class, StringComparer.Ordinal)
.ToList(), .ToList(),
}) })
.ToList() .ToList()
@ -1600,7 +1600,7 @@ public sealed partial class OpenIddictClientWebIntegrationSettings
static TemplateContext CreateTemplateContext(object model) static TemplateContext CreateTemplateContext(object model)
{ {
var context = new TemplateContext var context = new TemplateContext(StringComparer.OrdinalIgnoreCase)
{ {
LimitToString = 128 * 1024 * 1024, LimitToString = 128 * 1024 * 1024,
LoopLimit = 100_000 LoopLimit = 100_000

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

@ -31,7 +31,7 @@ public class AuthenticationController : Controller
// the user is directly redirected to GitHub (in this case, no login page is shown). // the user is directly redirected to GitHub (in this case, no login page is shown).
if (string.Equals(provider, "Local+GitHub", StringComparison.Ordinal)) if (string.Equals(provider, "Local+GitHub", StringComparison.Ordinal))
{ {
var properties = new AuthenticationProperties(new Dictionary<string, string?> var properties = new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
// Note: when only one client is registered in the client options, // Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required. // specifying the issuer URI or the provider name is not required.
@ -61,7 +61,7 @@ public class AuthenticationController : Controller
return new HttpStatusCodeResult(400); return new HttpStatusCodeResult(400);
} }
var properties = new AuthenticationProperties(new Dictionary<string, string?> var properties = new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
// Note: when only one client is registered in the client options, // Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required. // specifying the issuer URI or the provider name is not required.
@ -100,7 +100,7 @@ public class AuthenticationController : Controller
if (identity.FindFirst(Claims.Private.RegistrationId)?.Value is string identifier && if (identity.FindFirst(Claims.Private.RegistrationId)?.Value is string identifier &&
await _service.GetServerConfigurationByRegistrationIdAsync(identifier) is { EndSessionEndpoint: Uri }) await _service.GetServerConfigurationByRegistrationIdAsync(identifier) is { EndSessionEndpoint: Uri })
{ {
var properties = new AuthenticationProperties(new Dictionary<string, string?> var properties = new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictClientOwinConstants.Properties.RegistrationId] = identifier, [OpenIddictClientOwinConstants.Properties.RegistrationId] = identifier,
@ -195,7 +195,7 @@ public class AuthenticationController : Controller
OpenIddictClientOwinConstants.Tokens.BackchannelAccessToken or OpenIddictClientOwinConstants.Tokens.BackchannelAccessToken or
OpenIddictClientOwinConstants.Tokens.BackchannelIdentityToken or OpenIddictClientOwinConstants.Tokens.BackchannelIdentityToken or
OpenIddictClientOwinConstants.Tokens.RefreshToken) OpenIddictClientOwinConstants.Tokens.RefreshToken)
.ToDictionary(pair => pair.Key, pair => pair.Value)) .ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.Ordinal))
{ {
// Set the creation and expiration dates of the ticket to null to decorrelate the lifetime // Set the creation and expiration dates of the ticket to null to decorrelate the lifetime
// of the resulting authentication cookie from the lifetime of the identity token returned by // of the resulting authentication cookie from the lifetime of the identity token returned by

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

@ -86,7 +86,7 @@ public class AuthenticationController : Controller
// 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.
OpenIddictClientOwinConstants.Tokens.BackchannelAccessToken or OpenIddictClientOwinConstants.Tokens.BackchannelAccessToken or
OpenIddictClientOwinConstants.Tokens.RefreshToken) OpenIddictClientOwinConstants.Tokens.RefreshToken)
.ToDictionary(pair => pair.Key, pair => pair.Value)) .ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.Ordinal))
{ {
// Set the creation and expiration dates of the ticket to null to decorrelate the lifetime // Set the creation and expiration dates of the ticket to null to decorrelate the lifetime
// of the resulting authentication cookie from the lifetime of the identity token returned by // of the resulting authentication cookie from the lifetime of the identity token returned by

16
sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthorizationController.cs

@ -92,7 +92,7 @@ public class AuthorizationController : Controller
{ {
context.Authentication.Challenge( context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidRequest, [OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidRequest,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] = [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@ -102,7 +102,7 @@ public class AuthorizationController : Controller
return new EmptyResult(); return new EmptyResult();
} }
var properties = new AuthenticationProperties(new Dictionary<string, string?> var properties = new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
// Note: when only one client is registered in the client options, // Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required. // specifying the issuer URI or the provider name is not required.
@ -154,7 +154,7 @@ public class AuthorizationController : Controller
case ConsentTypes.External when authorizations.Count is 0: case ConsentTypes.External when authorizations.Count is 0:
context.Authentication.Challenge( context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] = [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@ -231,7 +231,7 @@ public class AuthorizationController : Controller
case ConsentTypes.Systematic when request.HasPromptValue(PromptValues.None): case ConsentTypes.Systematic when request.HasPromptValue(PromptValues.None):
context.Authentication.Challenge( context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] = [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@ -277,7 +277,7 @@ public class AuthorizationController : Controller
{ {
context.Authentication.Challenge( context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerOwinConstants.Properties.Error] = Errors.LoginRequired, [OpenIddictServerOwinConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] = [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@ -307,7 +307,7 @@ public class AuthorizationController : Controller
{ {
context.Authentication.Challenge( context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] = [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@ -425,7 +425,7 @@ public class AuthorizationController : Controller
{ {
context.Authentication.Challenge( context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant, [OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The token is no longer valid." [OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The token is no longer valid."
@ -439,7 +439,7 @@ public class AuthorizationController : Controller
{ {
context.Authentication.Challenge( context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant, [OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in." [OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."

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

@ -289,7 +289,7 @@ public class ManageController : Controller
return View("Error"); return View("Error");
} }
var userLogins = await UserManager.GetLoginsAsync(User.Identity.GetUserId()); var userLogins = await UserManager.GetLoginsAsync(User.Identity.GetUserId());
var otherLogins = AuthenticationManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList(); var otherLogins = AuthenticationManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => !string.Equals(auth.AuthenticationType, ul.LoginProvider, System.StringComparison.Ordinal))).ToList();
ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1; ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1;
return View(new ManageLoginsViewModel return View(new ManageLoginsViewModel
{ {

7
sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ResourceController.cs

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Security.Claims; using System.Security.Claims;
@ -27,7 +28,7 @@ public class ResourceController : ApiController
{ {
context.Authentication.Challenge( context.Authentication.Challenge(
authenticationTypes: OpenIddictValidationOwinDefaults.AuthenticationType, authenticationTypes: OpenIddictValidationOwinDefaults.AuthenticationType,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictValidationOwinConstants.Properties.Scope] = "demo_api", [OpenIddictValidationOwinConstants.Properties.Scope] = "demo_api",
[OpenIddictValidationOwinConstants.Properties.Error] = Errors.InsufficientScope, [OpenIddictValidationOwinConstants.Properties.Error] = Errors.InsufficientScope,
@ -43,7 +44,7 @@ public class ResourceController : ApiController
{ {
context.Authentication.Challenge( context.Authentication.Challenge(
authenticationTypes: OpenIddictValidationOwinDefaults.AuthenticationType, authenticationTypes: OpenIddictValidationOwinDefaults.AuthenticationType,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictValidationOwinConstants.Properties.Error] = Errors.InvalidToken, [OpenIddictValidationOwinConstants.Properties.Error] = Errors.InvalidToken,
[OpenIddictValidationOwinConstants.Properties.ErrorDescription] = [OpenIddictValidationOwinConstants.Properties.ErrorDescription] =

6
sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/AuthenticationController.cs

@ -24,7 +24,7 @@ public class AuthenticationController : Controller
// the user is directly redirected to GitHub (in this case, no login page is shown). // the user is directly redirected to GitHub (in this case, no login page is shown).
if (string.Equals(provider, "Local+GitHub", StringComparison.Ordinal)) if (string.Equals(provider, "Local+GitHub", StringComparison.Ordinal))
{ {
var properties = new AuthenticationProperties(new Dictionary<string, string?> var properties = new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
// Note: when only one client is registered in the client options, // Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required. // specifying the issuer URI or the provider name is not required.
@ -54,7 +54,7 @@ public class AuthenticationController : Controller
return BadRequest(); return BadRequest();
} }
var properties = new AuthenticationProperties(new Dictionary<string, string?> var properties = new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
// Note: when only one client is registered in the client options, // Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required. // specifying the issuer URI or the provider name is not required.
@ -96,7 +96,7 @@ public class AuthenticationController : Controller
if (identity.FindFirst(Claims.Private.RegistrationId)?.Value is string identifier && if (identity.FindFirst(Claims.Private.RegistrationId)?.Value is string identifier &&
await _service.GetServerConfigurationByRegistrationIdAsync(identifier) is { EndSessionEndpoint: Uri }) await _service.GetServerConfigurationByRegistrationIdAsync(identifier) is { EndSessionEndpoint: Uri })
{ {
var properties = new AuthenticationProperties(new Dictionary<string, string?> var properties = new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictClientAspNetCoreConstants.Properties.RegistrationId] = identifier, [OpenIddictClientAspNetCoreConstants.Properties.RegistrationId] = identifier,

40
sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AccountController.cs

@ -71,11 +71,9 @@ public class AccountController : Controller
{ {
return View("Lockout"); return View("Lockout");
} }
else
{ ModelState.AddModelError(string.Empty, "Invalid login attempt.");
ModelState.AddModelError(string.Empty, "Invalid login attempt."); return View(model);
return View(model);
}
} }
// If we got this far, something failed, redisplay form // If we got this far, something failed, redisplay form
@ -173,14 +171,12 @@ public class AccountController : Controller
{ {
return View("Lockout"); return View("Lockout");
} }
else
{ // If the user does not have an account, then ask the user to create an account.
// If the user does not have an account, then ask the user to create an account. ViewData["ReturnUrl"] = returnUrl;
ViewData["ReturnUrl"] = returnUrl; ViewData["LoginProvider"] = info.LoginProvider;
ViewData["LoginProvider"] = info.LoginProvider; var email = info.Principal.FindFirstValue(ClaimTypes.Email);
var email = info.Principal.FindFirstValue(ClaimTypes.Email); return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
}
} }
// //
@ -367,11 +363,11 @@ public class AccountController : Controller
} }
var message = "Your security code is: " + code; var message = "Your security code is: " + code;
if (model.SelectedProvider == "Email") if (string.Equals(model.SelectedProvider, "Email", StringComparison.Ordinal))
{ {
await _emailSender.SendEmailAsync(await _userManager.GetEmailAsync(user), "Security Code", message); await _emailSender.SendEmailAsync(await _userManager.GetEmailAsync(user), "Security Code", message);
} }
else if (model.SelectedProvider == "Phone") else if (string.Equals(model.SelectedProvider, "Phone", StringComparison.Ordinal))
{ {
await _smsSender.SendSmsAsync(await _userManager.GetPhoneNumberAsync(user), message); await _smsSender.SendSmsAsync(await _userManager.GetPhoneNumberAsync(user), message);
} }
@ -418,11 +414,9 @@ public class AccountController : Controller
{ {
return View("Lockout"); return View("Lockout");
} }
else
{ ModelState.AddModelError("", "Invalid code.");
ModelState.AddModelError("", "Invalid code."); return View(model);
return View(model);
}
} }
#region Helpers #region Helpers
@ -460,10 +454,8 @@ public class AccountController : Controller
{ {
return Redirect(returnUrl); return Redirect(returnUrl);
} }
else
{ return RedirectToAction(nameof(HomeController.Index), "Home");
return RedirectToAction(nameof(HomeController.Index), "Home");
}
} }
#endregion #endregion

37
sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AuthorizationController.cs

@ -4,6 +4,7 @@
* the license and the contributors participating to this project. * the license and the contributors participating to this project.
*/ */
using System.Globalization;
using System.Security.Claims; using System.Security.Claims;
using System.Text.Json.Nodes; using System.Text.Json.Nodes;
using Microsoft.AspNetCore; using Microsoft.AspNetCore;
@ -91,7 +92,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in." [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in."
@ -117,7 +118,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidRequest, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidRequest,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@ -181,7 +182,7 @@ public class AuthorizationController : Controller
case ConsentTypes.External when authorizations.Count is 0: case ConsentTypes.External when authorizations.Count is 0:
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@ -255,7 +256,7 @@ public class AuthorizationController : Controller
case ConsentTypes.Systematic when request.HasPromptValue(PromptValues.None): case ConsentTypes.Systematic when request.HasPromptValue(PromptValues.None):
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@ -265,7 +266,7 @@ public class AuthorizationController : Controller
// In every other case, render the consent form. // In every other case, render the consent form.
default: return View(new AuthorizeViewModel default: return View(new AuthorizeViewModel
{ {
ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application), ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application, CultureInfo.CurrentCulture),
Scope = request.Scope Scope = request.Scope
}); });
} }
@ -289,7 +290,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@ -317,7 +318,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@ -406,15 +407,13 @@ public class AuthorizationController : Controller
// Render a form asking the user to confirm the authorization demand. // Render a form asking the user to confirm the authorization demand.
return View(new VerifyViewModel return View(new VerifyViewModel
{ {
ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application), ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application, CultureInfo.CurrentCulture),
Scope = string.Join(" ", result.Principal.GetScopes()), Scope = string.Join(Separators.Space[0], result.Principal.GetScopes()),
UserCode = result.Properties.GetTokenValue(OpenIddictServerAspNetCoreConstants.Tokens.UserCode) UserCode = result.Properties.GetTokenValue(OpenIddictServerAspNetCoreConstants.Tokens.UserCode)
}); });
} }
// If a user code was specified (e.g as part of the verification_uri_complete) if (!string.IsNullOrEmpty(result.Properties?.GetTokenValue(OpenIddictServerAspNetCoreConstants.Tokens.UserCode)))
// but is not valid, render a form asking the user to enter the user code manually.
else if (!string.IsNullOrEmpty(result.Properties?.GetTokenValue(OpenIddictServerAspNetCoreConstants.Tokens.UserCode)))
{ {
return View(new VerifyViewModel return View(new VerifyViewModel
{ {
@ -437,7 +436,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@ -544,7 +543,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The username/password couple is invalid." [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The username/password couple is invalid."
@ -557,7 +556,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The username/password couple is invalid." [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The username/password couple is invalid."
@ -599,7 +598,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid." [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid."
@ -611,7 +610,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in." [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."
@ -657,7 +656,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid." [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid."
@ -669,7 +668,7 @@ public class AuthorizationController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in." [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."

2
sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ManageController.cs

@ -271,7 +271,7 @@ public class ManageController : Controller
return View("Error"); return View("Error");
} }
var userLogins = await _userManager.GetLoginsAsync(user); var userLogins = await _userManager.GetLoginsAsync(user);
var otherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).Where(auth => userLogins.All(ul => auth.Name != ul.LoginProvider)).ToList(); var otherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).Where(auth => userLogins.All(ul => !string.Equals(auth.Name, ul.LoginProvider, StringComparison.Ordinal))).ToList();
ViewData["ShowRemoveButton"] = user.PasswordHash is not null || userLogins.Count > 1; ViewData["ShowRemoveButton"] = user.PasswordHash is not null || userLogins.Count > 1;
return View(new ManageLoginsViewModel return View(new ManageLoginsViewModel
{ {

4
sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ResourceController.cs

@ -28,7 +28,7 @@ public class ResourceController : Controller
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictValidationAspNetCoreConstants.Properties.Scope] = "demo_api", [OpenIddictValidationAspNetCoreConstants.Properties.Scope] = "demo_api",
[OpenIddictValidationAspNetCoreConstants.Properties.Error] = Errors.InsufficientScope, [OpenIddictValidationAspNetCoreConstants.Properties.Error] = Errors.InsufficientScope,
@ -42,7 +42,7 @@ public class ResourceController : Controller
{ {
return Challenge( return Challenge(
authenticationSchemes: OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictValidationAspNetCoreConstants.Properties.Error] = Errors.InvalidToken, [OpenIddictValidationAspNetCoreConstants.Properties.Error] = Errors.InvalidToken,
[OpenIddictValidationAspNetCoreConstants.Properties.ErrorDescription] = [OpenIddictValidationAspNetCoreConstants.Properties.ErrorDescription] =

2
sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/UserinfoController.cs

@ -26,7 +26,7 @@ public class UserInfoController : Controller
{ {
return Challenge( return Challenge(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidToken, [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidToken,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =

4
sandbox/OpenIddict.Sandbox.AspNetCore.Server/Program.cs

@ -370,8 +370,8 @@ builder.Services.Configure<KestrelServerOptions>(options => options.ListenAnyIP(
ServerCertificate = store.Certificates ServerCertificate = store.Certificates
.Find(X509FindType.FindByExtension, "1.3.6.1.4.1.311.84.1.1", validOnly: false) .Find(X509FindType.FindByExtension, "1.3.6.1.4.1.311.84.1.1", validOnly: false)
.Cast<X509Certificate2>() .Cast<X509Certificate2>()
.Where(static certificate => certificate.NotBefore < TimeProvider.System.GetLocalNow()) .Where(static certificate => new DateTimeOffset(certificate.NotBefore) < TimeProvider.System.GetLocalNow())
.Where(static certificate => certificate.NotAfter > TimeProvider.System.GetLocalNow()) .Where(static certificate => new DateTimeOffset(certificate.NotAfter) > TimeProvider.System.GetLocalNow())
.OrderByDescending(static certificate => certificate.NotAfter) .OrderByDescending(static certificate => certificate.NotAfter)
.FirstOrDefault() .FirstOrDefault()
?? throw new InvalidOperationException("The ASP.NET Core HTTPS development certificate was not found.") ?? throw new InvalidOperationException("The ASP.NET Core HTTPS development certificate was not found.")

18
sandbox/OpenIddict.Sandbox.Console.Client/InteractiveService.cs

@ -502,13 +502,13 @@ public class InteractiveService : BackgroundService
List<((string? GrantType, string? ResponseType), string DisplayName)> choices = []; List<((string? GrantType, string? ResponseType), string DisplayName)> choices = [];
var types = configuration.ResponseTypesSupported.Select(static type => var types = configuration.ResponseTypesSupported.Select(static type =>
new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))); new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal));
if (configuration.GrantTypesSupported.Contains(GrantTypes.AuthorizationCode) && if (configuration.GrantTypesSupported.Contains(GrantTypes.AuthorizationCode) &&
(registration.GrantTypes.Count is 0 || registration.GrantTypes.Contains(GrantTypes.AuthorizationCode)) && (registration.GrantTypes.Count is 0 || registration.GrantTypes.Contains(GrantTypes.AuthorizationCode)) &&
types.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.Code)) && types.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.Code)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes (registration.ResponseTypes.Count is 0 || registration.ResponseTypes
.Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))) .Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.Code)))) .Any(static type => type.Count is 1 && type.Contains(ResponseTypes.Code))))
{ {
choices.Add((( choices.Add(((
@ -521,7 +521,7 @@ public class InteractiveService : BackgroundService
{ {
if (types.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.IdToken)) && if (types.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.IdToken)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes (registration.ResponseTypes.Count is 0 || registration.ResponseTypes
.Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))) .Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.IdToken)))) .Any(static type => type.Count is 1 && type.Contains(ResponseTypes.IdToken))))
{ {
choices.Add((( choices.Add(((
@ -532,7 +532,7 @@ public class InteractiveService : BackgroundService
if (types.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.IdToken) && if (types.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.IdToken) &&
type.Contains(ResponseTypes.Token)) && type.Contains(ResponseTypes.Token)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes (registration.ResponseTypes.Count is 0 || registration.ResponseTypes
.Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))) .Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.IdToken) && .Any(static type => type.Count is 2 && type.Contains(ResponseTypes.IdToken) &&
type.Contains(ResponseTypes.Token)))) type.Contains(ResponseTypes.Token))))
{ {
@ -550,7 +550,7 @@ public class InteractiveService : BackgroundService
if (types.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) && if (types.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.IdToken)) && type.Contains(ResponseTypes.IdToken)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes (registration.ResponseTypes.Count is 0 || registration.ResponseTypes
.Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))) .Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) && .Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.IdToken)))) type.Contains(ResponseTypes.IdToken))))
{ {
@ -563,7 +563,7 @@ public class InteractiveService : BackgroundService
type.Contains(ResponseTypes.IdToken) && type.Contains(ResponseTypes.IdToken) &&
type.Contains(ResponseTypes.Token)) && type.Contains(ResponseTypes.Token)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes (registration.ResponseTypes.Count is 0 || registration.ResponseTypes
.Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))) .Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 3 && type.Contains(ResponseTypes.Code) && .Any(static type => type.Count is 3 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.IdToken) && type.Contains(ResponseTypes.IdToken) &&
type.Contains(ResponseTypes.Token)))) type.Contains(ResponseTypes.Token))))
@ -577,7 +577,7 @@ public class InteractiveService : BackgroundService
if (types.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) && if (types.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.Token)) && type.Contains(ResponseTypes.Token)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes (registration.ResponseTypes.Count is 0 || registration.ResponseTypes
.Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))) .Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) && .Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.Token)))) type.Contains(ResponseTypes.Token))))
{ {
@ -589,7 +589,7 @@ public class InteractiveService : BackgroundService
if (types.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.None)) && if (types.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.None)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes (registration.ResponseTypes.Count is 0 || registration.ResponseTypes
.Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries))) .Select(static type => new HashSet<string>(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.None)))) .Any(static type => type.Count is 1 && type.Contains(ResponseTypes.None))))
{ {
choices.Add((( choices.Add(((
@ -873,7 +873,9 @@ public class InteractiveService : BackgroundService
// //
// In a real world application, the certificate wouldn't be embedded in the source code // In a real world application, the certificate wouldn't be embedded in the source code
// and would be installed in the certificate store, making this workaround unnecessary. // and would be installed in the certificate store, making this workaround unnecessary.
#pragma warning disable MA0144
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
#pragma warning restore MA0144
{ {
certificate = X509CertificateLoader.LoadPkcs12( certificate = X509CertificateLoader.LoadPkcs12(
data: certificate.Export(X509ContentType.Pfx, string.Empty), data: certificate.Export(X509ContentType.Pfx, string.Empty),

2
sandbox/OpenIddict.Sandbox.Maui.Client/MainPage.xaml.cs

@ -22,7 +22,7 @@ public partial class MainPage : ContentPage
=> await LogInAsync("Local"); => await LogInAsync("Local");
private async void OnLocalLoginWithGitHubButtonClicked(object sender, EventArgs e) private async void OnLocalLoginWithGitHubButtonClicked(object sender, EventArgs e)
=> await LogInAsync("Local", new() => await LogInAsync("Local", new(StringComparer.Ordinal)
{ {
[Parameters.IdentityProvider] = Providers.GitHub [Parameters.IdentityProvider] = Providers.GitHub
}); });

2
sandbox/OpenIddict.Sandbox.Maui.Client/MauiProgram.cs

@ -57,8 +57,10 @@ public static class MauiProgram
#if IOS #if IOS
// Warning: server certificate validation is disabled to simplify testing the MAUI // Warning: server certificate validation is disabled to simplify testing the MAUI
// application with the iOS simulator: in production, it SHOULD NEVER be disabled. // application with the iOS simulator: in production, it SHOULD NEVER be disabled.
#pragma warning disable MA0039
.ConfigureHttpClientHandler("Local", handler => handler.ServerCertificateCustomValidationCallback = .ConfigureHttpClientHandler("Local", handler => handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator) HttpClientHandler.DangerousAcceptAnyServerCertificateValidator)
#pragma warning restore MA0039
#endif #endif
; ;

2
sandbox/OpenIddict.Sandbox.WinForms.Client/MainForm.cs

@ -22,7 +22,7 @@ public partial class MainForm : Form, IWinFormsShell
=> await LogInAsync("Local"); => await LogInAsync("Local");
private async void LocalLoginWithGitHubButton_Click(object sender, EventArgs e) private async void LocalLoginWithGitHubButton_Click(object sender, EventArgs e)
=> await LogInAsync("Local", new() => await LogInAsync("Local", new(StringComparer.Ordinal)
{ {
[Parameters.IdentityProvider] = Providers.GitHub [Parameters.IdentityProvider] = Providers.GitHub
}); });

2
sandbox/OpenIddict.Sandbox.Wpf.Client/MainWindow.xaml.cs

@ -23,7 +23,7 @@ public partial class MainWindow : Window, IWpfShell
=> await LogInAsync("Local"); => await LogInAsync("Local");
private async void LocalLoginWithGitHubButton_Click(object sender, RoutedEventArgs e) private async void LocalLoginWithGitHubButton_Click(object sender, RoutedEventArgs e)
=> await LogInAsync("Local", new() => await LogInAsync("Local", new(StringComparer.Ordinal)
{ {
[Parameters.IdentityProvider] = Providers.GitHub [Parameters.IdentityProvider] = Providers.GitHub
}); });

10
shared/OpenIddict.Extensions/OpenIddictHelpers.cs

@ -276,8 +276,8 @@ internal static class OpenIddictHelpers
Key: parts[0] is string key ? Uri.UnescapeDataString(key) : null, Key: parts[0] is string key ? Uri.UnescapeDataString(key) : null,
Value: parts.Length is > 1 && parts[1] is string value ? Uri.UnescapeDataString(value) : null)) Value: parts.Length is > 1 && parts[1] is string value ? Uri.UnescapeDataString(value) : null))
.Where(static pair => !string.IsNullOrEmpty(pair.Key)) .Where(static pair => !string.IsNullOrEmpty(pair.Key))
.GroupBy(static pair => pair.Key) .GroupBy(static pair => pair.Key, StringComparer.Ordinal)
.ToDictionary(static pair => pair.Key!, static pair => new StringValues([.. pair.Select(parts => parts.Value)])); .ToDictionary(static pair => pair.Key!, static pair => new StringValues([.. pair.Select(parts => parts.Value)]), StringComparer.Ordinal);
} }
/// <summary> /// <summary>
@ -297,8 +297,8 @@ internal static class OpenIddictHelpers
Key: parts[0] is string key ? Uri.UnescapeDataString(key) : null, Key: parts[0] is string key ? Uri.UnescapeDataString(key) : null,
Value: parts.Length is > 1 && parts[1] is string value ? Uri.UnescapeDataString(value) : null)) Value: parts.Length is > 1 && parts[1] is string value ? Uri.UnescapeDataString(value) : null))
.Where(static pair => !string.IsNullOrEmpty(pair.Key)) .Where(static pair => !string.IsNullOrEmpty(pair.Key))
.GroupBy(static pair => pair.Key) .GroupBy(static pair => pair.Key, StringComparer.Ordinal)
.ToDictionary(static pair => pair.Key!, static pair => new StringValues([.. pair.Select(parts => parts.Value)])); .ToDictionary(static pair => pair.Key!, static pair => new StringValues([.. pair.Select(parts => parts.Value)]), StringComparer.Ordinal);
} }
/// <summary> /// <summary>
@ -345,7 +345,7 @@ internal static class OpenIddictHelpers
while (enumerator.MoveNext()) while (enumerator.MoveNext())
{ {
var element = enumerator.GetTextElement(); var element = enumerator.GetTextElement();
if (charset.Contains(element)) if (charset.Contains(element, StringComparer.Ordinal))
{ {
builder.Append(element); builder.Append(element);
} }

1
src/OpenIddict.Abstractions/OpenIddictConstants.cs

@ -560,6 +560,7 @@ public static class OpenIddictConstants
public static readonly char[] DoubleQuote = ['"']; public static readonly char[] DoubleQuote = ['"'];
public static readonly char[] EqualsSign = ['=']; public static readonly char[] EqualsSign = ['='];
public static readonly char[] Hash = ['#']; public static readonly char[] Hash = ['#'];
public static readonly char[] Plus = ['+'];
public static readonly char[] QuestionMark = ['?']; public static readonly char[] QuestionMark = ['?'];
public static readonly char[] Semicolon = [';']; public static readonly char[] Semicolon = [';'];
public static readonly char[] Space = [' ']; public static readonly char[] Space = [' '];

18
src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs

@ -308,9 +308,7 @@ public static class OpenIddictExtensions
continue; continue;
} }
// Note: though the OIDC core specs does not include the OAuth 2.0-inherited response_type=token, if (segment.Equals(ResponseTypes.Token, StringComparison.Ordinal))
// it is considered as a valid response_type for the implicit flow for backward compatibility.
else if (segment.Equals(ResponseTypes.Token, StringComparison.Ordinal))
{ {
flags |= /* token */ 0x02; flags |= /* token */ 0x02;
@ -359,14 +357,14 @@ public static class OpenIddictExtensions
continue; continue;
} }
else if (segment.Equals(ResponseTypes.IdToken, StringComparison.Ordinal)) if (segment.Equals(ResponseTypes.IdToken, StringComparison.Ordinal))
{ {
flags |= /* id_token: */ 0x02; flags |= /* id_token: */ 0x02;
continue; continue;
} }
else if (segment.Equals(ResponseTypes.Token, StringComparison.Ordinal)) if (segment.Equals(ResponseTypes.Token, StringComparison.Ordinal))
{ {
flags |= /* token: */ 0x04; flags |= /* token: */ 0x04;
@ -678,7 +676,7 @@ public static class OpenIddictExtensions
var builder = ImmutableDictionary.CreateBuilder<string, ImmutableArray<string>>(StringComparer.Ordinal); var builder = ImmutableDictionary.CreateBuilder<string, ImmutableArray<string>>(StringComparer.Ordinal);
foreach (var group in identity.Claims.GroupBy(claim => claim.Type)) foreach (var group in identity.Claims.GroupBy(claim => claim.Type, StringComparer.Ordinal))
{ {
var claims = group.ToList(); var claims = group.ToList();
@ -712,7 +710,7 @@ public static class OpenIddictExtensions
var builder = ImmutableDictionary.CreateBuilder<string, ImmutableArray<string>>(StringComparer.Ordinal); var builder = ImmutableDictionary.CreateBuilder<string, ImmutableArray<string>>(StringComparer.Ordinal);
foreach (var group in principal.Claims.GroupBy(claim => claim.Type)) foreach (var group in principal.Claims.GroupBy(claim => claim.Type, StringComparer.Ordinal))
{ {
var claims = group.ToList(); var claims = group.ToList();
@ -749,7 +747,8 @@ public static class OpenIddictExtensions
foreach (var destination in destinations) foreach (var destination in destinations)
{ {
foreach (var claim in identity.Claims.Where(claim => claim.Type == destination.Key)) foreach (var claim in identity.Claims.Where(claim =>
string.Equals(claim.Type, destination.Key, StringComparison.Ordinal)))
{ {
claim.SetDestinations(destination.Value); claim.SetDestinations(destination.Value);
} }
@ -772,7 +771,8 @@ public static class OpenIddictExtensions
foreach (var destination in destinations) foreach (var destination in destinations)
{ {
foreach (var claim in principal.Claims.Where(claim => claim.Type == destination.Key)) foreach (var claim in principal.Claims.Where(claim =>
string.Equals(claim.Type, destination.Key, StringComparison.Ordinal)))
{ {
claim.SetDestinations(destination.Value); claim.SetDestinations(destination.Value);
} }

2
src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs

@ -121,7 +121,7 @@ public class OpenIddictMessage
{ {
ArgumentNullException.ThrowIfNull(parameters); ArgumentNullException.ThrowIfNull(parameters);
foreach (var parameter in parameters.GroupBy(parameter => parameter.Key)) foreach (var parameter in parameters.GroupBy(parameter => parameter.Key, StringComparer.Ordinal))
{ {
// Ignore parameters whose name is null or empty. // Ignore parameters whose name is null or empty.
if (string.IsNullOrEmpty(parameter.Key)) if (string.IsNullOrEmpty(parameter.Key))

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

@ -205,7 +205,7 @@ public readonly struct OpenIddictParameter : IEquatable<OpenIddictParameter>
(string left, string right) => string.Equals(left, right, StringComparison.Ordinal), (string left, string right) => string.Equals(left, right, StringComparison.Ordinal),
// If the two parameters are string arrays, use SequenceEqual(). // If the two parameters are string arrays, use SequenceEqual().
(string?[] left, string?[] right) => Enumerable.SequenceEqual(left, right), (string?[] left, string?[] right) => Enumerable.SequenceEqual(left, right, StringComparer.Ordinal),
// If one of the two parameters is an undefined JsonElement, treat it // If one of the two parameters is an undefined JsonElement, treat it
// as a null value and return true if the other parameter is null too. // as a null value and return true if the other parameter is null too.
@ -323,7 +323,7 @@ public readonly struct OpenIddictParameter : IEquatable<OpenIddictParameter>
JsonValue value when value.TryGetValue(out int result) => result.GetHashCode(), JsonValue value when value.TryGetValue(out int result) => result.GetHashCode(),
JsonValue value when value.TryGetValue(out long result) => result.GetHashCode(), JsonValue value when value.TryGetValue(out long result) => result.GetHashCode(),
JsonValue value when value.TryGetValue(out string? result) => result.GetHashCode(), JsonValue value when value.TryGetValue(out string? result) => result.GetHashCode(StringComparison.Ordinal),
// When the parameter is a JsonNode (e.g a JsonValue wrapping a non-primitive type), // When the parameter is a JsonNode (e.g a JsonValue wrapping a non-primitive type),
// serialize it to a JsonElement first to determine its actual JSON representation // serialize it to a JsonElement first to determine its actual JSON representation
@ -342,7 +342,7 @@ public readonly struct OpenIddictParameter : IEquatable<OpenIddictParameter>
for (var index = 0; index < array.Length; index++) for (var index = 0; index < array.Length; index++)
{ {
hash.Add(array[index]); hash.Add(array[index], StringComparer.Ordinal);
} }
return hash.ToHashCode(); return hash.ToHashCode();
@ -368,10 +368,10 @@ public readonly struct OpenIddictParameter : IEquatable<OpenIddictParameter>
return result.GetHashCode(); return result.GetHashCode();
case JsonValueKind.Number: case JsonValueKind.Number:
return element.GetRawText().GetHashCode(); return element.GetRawText().GetHashCode(StringComparison.Ordinal);
case JsonValueKind.String: case JsonValueKind.String:
return element.GetString()!.GetHashCode(); return element.GetString()!.GetHashCode(StringComparison.Ordinal);
case JsonValueKind.Array: case JsonValueKind.Array:
{ {
@ -391,7 +391,7 @@ public readonly struct OpenIddictParameter : IEquatable<OpenIddictParameter>
foreach (var property in element.EnumerateObject()) foreach (var property in element.EnumerateObject())
{ {
hash.Add(property.Name); hash.Add(property.Name, StringComparer.Ordinal);
hash.Add(GetHashCodeFromJsonElement(property.Value)); hash.Add(GetHashCodeFromJsonElement(property.Value));
} }
@ -441,7 +441,7 @@ public readonly struct OpenIddictParameter : IEquatable<OpenIddictParameter>
is JsonElement { ValueKind: JsonValueKind.Object } element is JsonElement { ValueKind: JsonValueKind.Object } element
=> GetParametersFromJsonElement(element), => GetParametersFromJsonElement(element),
_ => ImmutableDictionary.Create<string, OpenIddictParameter>(StringComparer.Ordinal) _ => ImmutableDictionary<string, OpenIddictParameter>.Empty
}; };
static IReadOnlyDictionary<string, OpenIddictParameter> GetParametersFromJsonElement(JsonElement element) static IReadOnlyDictionary<string, OpenIddictParameter> GetParametersFromJsonElement(JsonElement element)

4
src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs

@ -323,7 +323,7 @@ public interface IOpenIddictTokenStore<TToken> where TToken : class
/// <param name="identifier">The application identifier associated with the tokens.</param> /// <param name="identifier">The application identifier associated with the tokens.</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 number of tokens associated with the specified application that were marked as revoked.</returns> /// <returns>The number of tokens associated with the specified application that were marked as revoked.</returns>
ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken = default); ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Revokes all the tokens associated with the specified authorization identifier. /// Revokes all the tokens associated with the specified authorization identifier.
@ -339,7 +339,7 @@ public interface IOpenIddictTokenStore<TToken> where TToken : class
/// <param name="subject">The subject associated with the tokens.</param> /// <param name="subject">The subject associated with the tokens.</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 number of tokens associated with the specified subject that were marked as revoked.</returns> /// <returns>The number of tokens associated with the specified subject that were marked as revoked.</returns>
ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken = default); ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the application identifier associated with a token. /// Sets the application identifier associated with a token.

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

@ -66,7 +66,7 @@ public sealed class OpenIddictClientAspNetCoreConfiguration : IConfigureOptions<
foreach (var (provider, registrations) in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientOptions>>() foreach (var (provider, registrations) in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientOptions>>()
.CurrentValue.Registrations .CurrentValue.Registrations
.Where(static registration => !string.IsNullOrEmpty(registration.ProviderName)) .Where(static registration => !string.IsNullOrEmpty(registration.ProviderName))
.GroupBy(static registration => registration.ProviderName) .GroupBy(static registration => registration.ProviderName, StringComparer.Ordinal)
.Select(static group => (ProviderName: group.Key, Registrations: group.ToList()))) .Select(static group => (ProviderName: group.Key, Registrations: group.ToList())))
{ {
// If an explicit mapping was already added, don't overwrite it. // If an explicit mapping was already added, don't overwrite it.
@ -148,7 +148,7 @@ public sealed class OpenIddictClientAspNetCoreConfiguration : IConfigureOptions<
// Ensure the forwarded authentication schemes are mapped to the OpenIddict client forwarder. // Ensure the forwarded authentication schemes are mapped to the OpenIddict client forwarder.
foreach (var group in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientAspNetCoreOptions>>() foreach (var group in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientAspNetCoreOptions>>()
.CurrentValue.ForwardedAuthenticationSchemes .CurrentValue.ForwardedAuthenticationSchemes
.GroupBy(static scheme => scheme.Name) .GroupBy(static scheme => scheme.Name, StringComparer.Ordinal)
.Where(group => !ValidateHandlerType<OpenIddictClientAspNetCoreForwarder>(options.SchemeMap, group.Key))) .Where(group => !ValidateHandlerType<OpenIddictClientAspNetCoreForwarder>(options.SchemeMap, group.Key)))
{ {
builder.AddError(SR.FormatID0414(group.Key)); builder.AddError(SR.FormatID0414(group.Key));
@ -195,7 +195,7 @@ public sealed class OpenIddictClientAspNetCoreConfiguration : IConfigureOptions<
foreach (var (provider, registrations) in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientOptions>>() foreach (var (provider, registrations) in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientOptions>>()
.CurrentValue.Registrations .CurrentValue.Registrations
.Where(static registration => !string.IsNullOrEmpty(registration.ProviderName)) .Where(static registration => !string.IsNullOrEmpty(registration.ProviderName))
.GroupBy(static registration => registration.ProviderName) .GroupBy(static registration => registration.ProviderName, StringComparer.Ordinal)
.Select(static group => (ProviderName: group.Key, Registrations: group.ToList())) .Select(static group => (ProviderName: group.Key, Registrations: group.ToList()))
.Where(static group => group.Registrations.Count is > 1)) .Where(static group => group.Registrations.Count is > 1))
{ {

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

@ -54,7 +54,7 @@ public sealed class OpenIddictClientAspNetCoreForwarder : IAuthenticationHandler
await _context.ChallengeAsync( await _context.ChallengeAsync(
scheme: OpenIddictClientAspNetCoreDefaults.AuthenticationScheme, scheme: OpenIddictClientAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties( properties: new AuthenticationProperties(
items: new Dictionary<string, string?>(properties?.Items ?? ImmutableDictionary.Create<string, string?>()) items: new Dictionary<string, string?>(properties?.Items ?? ImmutableDictionary<string, string?>.Empty, StringComparer.Ordinal)
{ {
[Properties.ProviderName] = _scheme.Name [Properties.ProviderName] = _scheme.Name
}, },
@ -76,7 +76,7 @@ public sealed class OpenIddictClientAspNetCoreForwarder : IAuthenticationHandler
await _context.ForbidAsync( await _context.ForbidAsync(
scheme: OpenIddictClientAspNetCoreDefaults.AuthenticationScheme, scheme: OpenIddictClientAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties( properties: new AuthenticationProperties(
items: new Dictionary<string, string?>(properties?.Items ?? ImmutableDictionary.Create<string, string?>()) items: new Dictionary<string, string?>(properties?.Items ?? ImmutableDictionary<string, string?>.Empty, StringComparer.Ordinal)
{ {
[Properties.ProviderName] = _scheme.Name [Properties.ProviderName] = _scheme.Name
}, },
@ -98,7 +98,7 @@ public sealed class OpenIddictClientAspNetCoreForwarder : IAuthenticationHandler
await _context.SignOutAsync( await _context.SignOutAsync(
scheme: OpenIddictClientAspNetCoreDefaults.AuthenticationScheme, scheme: OpenIddictClientAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties( properties: new AuthenticationProperties(
items: new Dictionary<string, string?>(properties?.Items ?? ImmutableDictionary.Create<string, string?>()) items: new Dictionary<string, string?>(properties?.Items ?? ImmutableDictionary<string, string?>.Empty, StringComparer.Ordinal)
{ {
[Properties.ProviderName] = _scheme.Name [Properties.ProviderName] = _scheme.Name
}, },

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

@ -76,12 +76,12 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
return true; return true;
} }
else if (context.IsRequestSkipped) if (context.IsRequestSkipped)
{ {
return false; return false;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -98,7 +98,7 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
return true; return true;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
return false; return false;
} }
@ -133,7 +133,7 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
return AuthenticateResult.NoResult(); return AuthenticateResult.NoResult();
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
// Note: the missing_token error is special-cased to indicate to ASP.NET Core // Note: the missing_token error is special-cased to indicate to ASP.NET Core
// that no authentication result could be produced due to the lack of token. // that no authentication result could be produced due to the lack of token.
@ -390,7 +390,7 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -436,7 +436,7 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {

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

@ -572,8 +572,7 @@ public static partial class OpenIddictClientAspNetCoreHandlers
context.Issuer = uri; context.Issuer = uri;
} }
if (properties.Items.TryGetValue(Properties.Scope, out string? scope) && if (properties.Items.TryGetValue(Properties.Scope, out string? scope) && !string.IsNullOrEmpty(scope))
!string.IsNullOrEmpty(scope))
{ {
context.Scopes.UnionWith(scope.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)); context.Scopes.UnionWith(scope.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries));
} }

2
src/OpenIddict.Client.DataProtection/OpenIddictClientDataProtectionFormatter.cs

@ -182,7 +182,7 @@ public sealed class OpenIddictClientDataProtectionFormatter : IOpenIddictClientD
ArgumentNullException.ThrowIfNull(writer); ArgumentNullException.ThrowIfNull(writer);
ArgumentNullException.ThrowIfNull(principal); ArgumentNullException.ThrowIfNull(principal);
var properties = new Dictionary<string, string>(); var properties = new Dictionary<string, string>(StringComparer.Ordinal);
// Unlike ASP.NET Core Data Protection-based tokens, tokens serialized using the new format // Unlike ASP.NET Core Data Protection-based tokens, tokens serialized using the new format
// can't include authentication properties. To ensure tokens can be used with previous versions // can't include authentication properties. To ensure tokens can be used with previous versions

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

@ -61,7 +61,7 @@ public sealed class OpenIddictClientOwinConfiguration : IConfigureOptions<OpenId
foreach (var (provider, registrations) in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientOptions>>() foreach (var (provider, registrations) in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientOptions>>()
.CurrentValue.Registrations .CurrentValue.Registrations
.Where(static registration => !string.IsNullOrEmpty(registration.ProviderName)) .Where(static registration => !string.IsNullOrEmpty(registration.ProviderName))
.GroupBy(static registration => registration.ProviderName) .GroupBy(static registration => registration.ProviderName, StringComparer.Ordinal)
.Select(static group => (ProviderName: group.Key, Registrations: group.ToList()))) .Select(static group => (ProviderName: group.Key, Registrations: group.ToList())))
{ {
// If an explicit mapping was already added, don't overwrite it. // If an explicit mapping was already added, don't overwrite it.
@ -109,7 +109,7 @@ public sealed class OpenIddictClientOwinConfiguration : IConfigureOptions<OpenId
foreach (var (provider, registrations) in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientOptions>>() foreach (var (provider, registrations) in _provider.GetRequiredService<IOptionsMonitor<OpenIddictClientOptions>>()
.CurrentValue.Registrations .CurrentValue.Registrations
.Where(static registration => !string.IsNullOrEmpty(registration.ProviderName)) .Where(static registration => !string.IsNullOrEmpty(registration.ProviderName))
.GroupBy(static registration => registration.ProviderName) .GroupBy(static registration => registration.ProviderName, StringComparer.Ordinal)
.Select(static group => (ProviderName: group.Key, Registrations: group.ToList())) .Select(static group => (ProviderName: group.Key, Registrations: group.ToList()))
.Where(static group => group.Registrations.Count is > 1)) .Where(static group => group.Registrations.Count is > 1))
{ {

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

@ -95,12 +95,12 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
return true; return true;
} }
else if (context.IsRequestSkipped) if (context.IsRequestSkipped)
{ {
return false; return false;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -117,7 +117,7 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
return true; return true;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
return false; return false;
} }
@ -152,7 +152,7 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
return null; return null;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
// Note: the missing_token error is special-cased to indicate to Katana // Note: the missing_token error is special-cased to indicate to Katana
// that no authentication result could be produced due to the lack of token. // that no authentication result could be produced due to the lack of token.
@ -315,7 +315,7 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -359,7 +359,7 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -408,7 +408,7 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
authenticationTypes: [OpenIddictClientOwinDefaults.AuthenticationType], authenticationTypes: [OpenIddictClientOwinDefaults.AuthenticationType],
properties : new AuthenticationProperties(dictionary: new Dictionary<string, string>( properties : new AuthenticationProperties(dictionary: new Dictionary<string, string>(
manager.AuthenticationResponseChallenge.Properties.Dictionary manager.AuthenticationResponseChallenge.Properties.Dictionary
?? ImmutableDictionary.Create<string, string>()) ?? ImmutableDictionary<string, string>.Empty, StringComparer.Ordinal)
{ {
[Properties.ProviderName] = type [Properties.ProviderName] = type
})); }));
@ -447,7 +447,7 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
authenticationTypes: [OpenIddictClientOwinDefaults.AuthenticationType], authenticationTypes: [OpenIddictClientOwinDefaults.AuthenticationType],
properties : new AuthenticationProperties(dictionary: new Dictionary<string, string>( properties : new AuthenticationProperties(dictionary: new Dictionary<string, string>(
manager.AuthenticationResponseRevoke.Properties.Dictionary manager.AuthenticationResponseRevoke.Properties.Dictionary
?? ImmutableDictionary.Create<string, string>()) ?? ImmutableDictionary<string, string>.Empty, StringComparer.Ordinal)
{ {
[Properties.ProviderName] = type [Properties.ProviderName] = type
})); }));

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

@ -578,8 +578,7 @@ public static partial class OpenIddictClientOwinHandlers
context.Issuer = uri; context.Issuer = uri;
} }
if (properties.Dictionary.TryGetValue(Properties.Scope, out string? scope) && if (properties.Dictionary.TryGetValue(Properties.Scope, out string? scope) && !string.IsNullOrEmpty(scope))
!string.IsNullOrEmpty(scope))
{ {
context.Scopes.UnionWith(scope.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)); context.Scopes.UnionWith(scope.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries));
} }

12
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs

@ -228,7 +228,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute), uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary( parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value))!; static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal))!;
void HandleCallback(NSUrl? url, NSError? error) void HandleCallback(NSUrl? url, NSError? error)
{ {
@ -346,7 +347,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute), uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary( parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)).AbsoluteUri)!); static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal)).AbsoluteUri)!);
context.HandleRequest(); context.HandleRequest();
#else #else
@ -424,7 +426,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute), uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary( parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)), static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal)),
callbackUri: new Uri(context.RedirectUri, UriKind.Absolute))) callbackUri: new Uri(context.RedirectUri, UriKind.Absolute)))
{ {
case { ResponseStatus: WebAuthenticationStatus.Success } result case { ResponseStatus: WebAuthenticationStatus.Success } result
@ -530,7 +533,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute), uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary( parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)); static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal));
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {

12
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs

@ -228,7 +228,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute), uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary( parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value))!; static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal))!;
void HandleCallback(NSUrl? url, NSError? error) void HandleCallback(NSUrl? url, NSError? error)
{ {
@ -346,7 +347,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute), uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary( parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)).AbsoluteUri)!); static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal)).AbsoluteUri)!);
context.HandleRequest(); context.HandleRequest();
#else #else
@ -424,7 +426,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute), uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary( parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)), static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal)),
callbackUri: new Uri(context.PostLogoutRedirectUri, UriKind.Absolute))) callbackUri: new Uri(context.PostLogoutRedirectUri, UriKind.Absolute)))
{ {
case { ResponseStatus: WebAuthenticationStatus.Success } result case { ResponseStatus: WebAuthenticationStatus.Success } result
@ -530,7 +533,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute), uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary( parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)); static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal));
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {

4
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs

@ -655,13 +655,13 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,

2
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationMarshal.cs

@ -19,7 +19,7 @@ public sealed class OpenIddictClientSystemIntegrationMarshal
private readonly ConcurrentDictionary<string, Lazy<( private readonly ConcurrentDictionary<string, Lazy<(
string RequestForgeryProtection, string RequestForgeryProtection,
SemaphoreSlim Semaphore, SemaphoreSlim Semaphore,
TaskCompletionSource<ProcessAuthenticationContext> TaskCompletionSource)>> _tracker = new(); TaskCompletionSource<ProcessAuthenticationContext> TaskCompletionSource)>> _tracker = new(StringComparer.Ordinal);
/// <summary> /// <summary>
/// Determines whether the authentication demand corresponding to the specified nonce is tracked. /// Determines whether the authentication demand corresponding to the specified nonce is tracked.

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

@ -374,7 +374,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
static string? EscapeDataString(string? value) static string? EscapeDataString(string? value)
=> value is not null ? Uri.EscapeDataString(value).Replace("%20", "+") : null; => value is not null ? Uri.EscapeDataString(value).Replace("%20", "+", StringComparison.Ordinal) : null;
} }
} }
@ -417,7 +417,8 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(request.RequestUri, request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(request.RequestUri,
context.Transaction.Request.GetParameters().ToDictionary( context.Transaction.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)); static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal));
} }
// For POST requests, attach the request parameters to the request form by default. // For POST requests, attach the request parameters to the request form by default.
@ -609,7 +610,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
continue; continue;
} }
else if (string.Equals(encoding, ContentEncodings.Gzip, StringComparison.OrdinalIgnoreCase)) if (string.Equals(encoding, ContentEncodings.Gzip, StringComparison.OrdinalIgnoreCase))
{ {
stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken); stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken);
stream = new GZipStream(stream, CompressionMode.Decompress); stream = new GZipStream(stream, CompressionMode.Decompress);

2
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationExtensions.cs

@ -14,7 +14,7 @@ namespace Microsoft.Extensions.DependencyInjection;
/// <summary> /// <summary>
/// Exposes extensions allowing to register the OpenIddict client Web integration services. /// Exposes extensions allowing to register the OpenIddict client Web integration services.
/// </summary> /// </summary>
public static partial class OpenIddictClientWebIntegrationExtensions public static class OpenIddictClientWebIntegrationExtensions
{ {
/// <summary> /// <summary>
/// Registers the OpenIddict client Web integration services in the DI container. /// Registers the OpenIddict client Web integration services in the DI container.

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

@ -270,7 +270,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
{ {
request.RequestUri = OpenIddictHelpers.AddQueryStringParameters( request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(
uri: request.RequestUri, uri: request.RequestUri,
parameters: new Dictionary<string, StringValues> parameters: new Dictionary<string, StringValues>(StringComparer.Ordinal)
{ {
["chat_os_type"] = "bot", ["chat_os_type"] = "bot",
["chat_version"] = "1.30.0" ["chat_version"] = "1.30.0"

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

@ -66,7 +66,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
} }
} }
context.Response.Scope = string.Join(" ", scopes); context.Response.Scope = string.Join(Separators.Space[0], scopes);
} }
return ValueTask.CompletedTask; return ValueTask.CompletedTask;

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

@ -161,13 +161,11 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// //
// See https://shopify.dev/docs/apps/auth/oauth/getting-started#remove-the-hmac-parameter-from-the-query-string // See https://shopify.dev/docs/apps/auth/oauth/getting-started#remove-the-hmac-parameter-from-the-query-string
// for more information. // for more information.
foreach (var (name, value) in foreach (var (name, value) in OpenIddictHelpers.ParseQuery(context.RequestUri!.Query)
from parameter in OpenIddictHelpers.ParseQuery(context.RequestUri!.Query) .Where(static parameter => !string.IsNullOrEmpty(parameter.Key))
where !string.IsNullOrEmpty(parameter.Key) .Where(static parameter => !string.Equals(parameter.Key, "hmac", StringComparison.Ordinal))
where !string.Equals(parameter.Key, "hmac", StringComparison.Ordinal) .OrderBy(static parameter => parameter.Key, StringComparer.Ordinal)
orderby parameter.Key ascending .SelectMany(static parameter => parameter.Value, static (parameter, value) => (Name: parameter.Key, Value: value)))
from value in parameter.Value
select (Name: parameter.Key, Value: value))
{ {
if (builder.Length is > 0) if (builder.Length is > 0)
{ {
@ -1187,7 +1185,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
{ {
var settings = context.Registration.GetDailymotionSettings(); var settings = context.Registration.GetDailymotionSettings();
context.UserInfoRequest["fields"] = string.Join(",", settings.UserFields); context.UserInfoRequest["fields"] = string.Join(Separators.Comma[0], settings.UserFields);
} }
// Disqus requires sending the client identifier (called "public // Disqus requires sending the client identifier (called "public
@ -1204,7 +1202,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
{ {
var settings = context.Registration.GetFacebookSettings(); var settings = context.Registration.GetFacebookSettings();
context.UserInfoRequest["fields"] = string.Join(",", settings.Fields); context.UserInfoRequest["fields"] = string.Join(Separators.Comma[0], settings.Fields);
} }
// Linear's userinfo endpoint is a GraphQL implementation that requires // Linear's userinfo endpoint is a GraphQL implementation that requires
@ -1213,7 +1211,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
{ {
var settings = context.Registration.GetLinearSettings(); var settings = context.Registration.GetLinearSettings();
context.UserInfoRequest["query"] = $"query {{ viewer {{ {string.Join(" ", settings.UserFields)} }} }}"; context.UserInfoRequest["query"] = $"query {{ viewer {{ {string.Join(Separators.Space[0], settings.UserFields)} }} }}";
} }
// Meetup's userinfo endpoint is a GraphQL implementation that requires // Meetup's userinfo endpoint is a GraphQL implementation that requires
@ -1222,7 +1220,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
{ {
var settings = context.Registration.GetMeetupSettings(); var settings = context.Registration.GetMeetupSettings();
context.UserInfoRequest["query"] = $"query {{ self {{ {string.Join(" ", settings.UserFields)} }} }}"; context.UserInfoRequest["query"] = $"query {{ self {{ {string.Join(Separators.Space[0], settings.UserFields)} }} }}";
} }
// Patreon limits the number of fields returned by the userinfo endpoint // Patreon limits the number of fields returned by the userinfo endpoint
@ -1232,7 +1230,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
{ {
var settings = context.Registration.GetPatreonSettings(); var settings = context.Registration.GetPatreonSettings();
context.UserInfoRequest["fields[user]"] = string.Join(",", settings.UserFields); context.UserInfoRequest["fields[user]"] = string.Join(Separators.Comma[0], settings.UserFields);
} }
// StackOverflow requires sending an application key and a site parameter // StackOverflow requires sending an application key and a site parameter
@ -1274,9 +1272,9 @@ public static partial class OpenIddictClientWebIntegrationHandlers
{ {
var settings = context.Registration.GetTwitterSettings(); var settings = context.Registration.GetTwitterSettings();
context.UserInfoRequest["expansions"] = string.Join(",", settings.Expansions); context.UserInfoRequest["expansions"] = string.Join(Separators.Comma[0], settings.Expansions);
context.UserInfoRequest["tweet.fields"] = string.Join(",", settings.TweetFields); context.UserInfoRequest["tweet.fields"] = string.Join(Separators.Comma[0], settings.TweetFields);
context.UserInfoRequest["user.fields"] = string.Join(",", settings.UserFields); context.UserInfoRequest["user.fields"] = string.Join(Separators.Comma[0], settings.UserFields);
} }
// Weibo requires sending the user identifier as part of the userinfo request. // Weibo requires sending the user identifier as part of the userinfo request.
@ -1880,11 +1878,11 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// the standard format (that requires using a space as the scope separator): // the standard format (that requires using a space as the scope separator):
ProviderTypes.Deezer or ProviderTypes.Disqus or ProviderTypes.Shopify or ProviderTypes.Deezer or ProviderTypes.Disqus or ProviderTypes.Shopify or
ProviderTypes.Strava or ProviderTypes.Todoist or ProviderTypes.Weibo ProviderTypes.Strava or ProviderTypes.Todoist or ProviderTypes.Weibo
=> string.Join(",", context.Scopes), => string.Join(Separators.Comma[0], context.Scopes),
// The following providers are known to use plus-separated scopes instead of // The following providers are known to use plus-separated scopes instead of
// the standard format (that requires using a space as the scope separator): // the standard format (that requires using a space as the scope separator):
ProviderTypes.Trovo => string.Join("+", context.Scopes), ProviderTypes.Trovo => string.Join(Separators.Plus[0], context.Scopes),
_ => context.Request.Scope _ => context.Request.Scope
}; };

2
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationOptions.cs

@ -9,6 +9,6 @@ namespace OpenIddict.Client.WebIntegration;
/// <summary> /// <summary>
/// Provides various settings needed to configure the OpenIddict client Web integration. /// Provides various settings needed to configure the OpenIddict client Web integration.
/// </summary> /// </summary>
public sealed partial class OpenIddictClientWebIntegrationOptions public sealed class OpenIddictClientWebIntegrationOptions
{ {
} }

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

@ -89,7 +89,7 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -138,13 +138,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -419,13 +419,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -478,13 +478,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -531,13 +531,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -585,7 +585,7 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -676,13 +676,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,

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

@ -410,7 +410,7 @@ public static partial class OpenIddictClientHandlers
foreach (var claim in result.ClaimsIdentity.Claims) foreach (var claim in result.ClaimsIdentity.Claims)
{ {
// Exclude claims starting with "oi_" from tokens that are not fully trusted. // Exclude claims starting with "oi_" from tokens that are not fully trusted.
if (claim.Type.StartsWith(Claims.Prefixes.Private)) if (claim.Type.StartsWith(Claims.Prefixes.Private, StringComparison.Ordinal))
{ {
continue; continue;
} }
@ -424,7 +424,7 @@ public static partial class OpenIddictClientHandlers
identity = result.ClaimsIdentity.Clone(claim => claim switch identity = result.ClaimsIdentity.Clone(claim => claim switch
{ {
// Exclude claims starting with "oi_", unless the token is a state token. // Exclude claims starting with "oi_", unless the token is a state token.
{ Type: string type } when type.StartsWith(Claims.Prefixes.Private) && { Type: string type } when type.StartsWith(Claims.Prefixes.Private, StringComparison.Ordinal) &&
result.TokenType is not JsonWebTokenTypes.Private.StateToken => false, result.TokenType is not JsonWebTokenTypes.Private.StateToken => false,
_ => true // Allow any other claim. _ => true // Allow any other claim.

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

@ -74,7 +74,7 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -121,13 +121,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -210,13 +210,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -269,13 +269,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -322,13 +322,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -376,7 +376,7 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -425,13 +425,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,

92
src/OpenIddict.Client/OpenIddictClientHandlers.cs

@ -713,13 +713,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectStateToken) if (context.RejectStateToken)
{ {
@ -1626,13 +1626,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectFrontchannelIdentityToken) if (context.RejectFrontchannelIdentityToken)
{ {
@ -1674,8 +1674,8 @@ public static partial class OpenIddictClientHandlers
Debug.Assert(context.FrontchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(context.FrontchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
foreach (var group in context.FrontchannelIdentityTokenPrincipal.Claims foreach (var group in context.FrontchannelIdentityTokenPrincipal.Claims
.GroupBy(static claim => claim.Type) .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
.ToDictionary(static group => group.Key, group => group.ToList()) .ToDictionary(static group => group.Key, group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value))) .Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{ {
context.Reject( context.Reject(
@ -1806,7 +1806,8 @@ public static partial class OpenIddictClientHandlers
// In any case, the client identifier of the application MUST be included in the audiences. // In any case, the client identifier of the application MUST be included in the audiences.
// See https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation for more information. // See https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation for more information.
var audiences = context.FrontchannelIdentityTokenPrincipal.GetClaims(Claims.Audience); var audiences = context.FrontchannelIdentityTokenPrincipal.GetClaims(Claims.Audience);
if (!string.IsNullOrEmpty(context.Registration.ClientId) && !audiences.Contains(context.Registration.ClientId)) if (!string.IsNullOrEmpty(context.Registration.ClientId) &&
!audiences.Contains(context.Registration.ClientId, StringComparer.Ordinal))
{ {
context.Reject( context.Reject(
error: Errors.InvalidRequest, error: Errors.InvalidRequest,
@ -2150,13 +2151,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectFrontchannelAccessToken) if (context.RejectFrontchannelAccessToken)
{ {
@ -2221,13 +2222,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectAuthorizationCode) if (context.RejectAuthorizationCode)
{ {
@ -2697,7 +2698,7 @@ public static partial class OpenIddictClientHandlers
// Note: the final OAuth 2.0 specification requires using a space as the scope separator. // Note: the final OAuth 2.0 specification requires using a space as the scope separator.
// Clients that need to deal with older or non-compliant implementations can register // Clients that need to deal with older or non-compliant implementations can register
// a custom handler to use a different separator (typically, a comma). // a custom handler to use a different separator (typically, a comma).
context.TokenRequest.Scope = string.Join(" ", context.Scopes); context.TokenRequest.Scope = string.Join(Separators.Space[0], context.Scopes);
} }
} }
@ -2908,13 +2909,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -3363,13 +3364,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectBackchannelIdentityToken) if (context.RejectBackchannelIdentityToken)
{ {
@ -3411,8 +3412,8 @@ public static partial class OpenIddictClientHandlers
Debug.Assert(context.BackchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(context.BackchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
foreach (var group in context.BackchannelIdentityTokenPrincipal.Claims foreach (var group in context.BackchannelIdentityTokenPrincipal.Claims
.GroupBy(static claim => claim.Type) .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
.ToDictionary(static group => group.Key, group => group.ToList()) .ToDictionary(static group => group.Key, group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value))) .Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{ {
context.Reject( context.Reject(
@ -3543,7 +3544,8 @@ public static partial class OpenIddictClientHandlers
// In any case, the client identifier of the application MUST be included in the audiences. // In any case, the client identifier of the application MUST be included in the audiences.
// See https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation for more information. // See https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation for more information.
var audiences = context.BackchannelIdentityTokenPrincipal.GetClaims(Claims.Audience); var audiences = context.BackchannelIdentityTokenPrincipal.GetClaims(Claims.Audience);
if (!string.IsNullOrEmpty(context.Registration.ClientId) && !audiences.Contains(context.Registration.ClientId)) if (!string.IsNullOrEmpty(context.Registration.ClientId) &&
!audiences.Contains(context.Registration.ClientId, StringComparer.Ordinal))
{ {
context.Reject( context.Reject(
error: Errors.InvalidRequest, error: Errors.InvalidRequest,
@ -3851,13 +3853,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectBackchannelAccessToken) if (context.RejectBackchannelAccessToken)
{ {
@ -3920,13 +3922,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectIssuedToken) if (context.RejectIssuedToken)
{ {
@ -3991,13 +3993,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectRefreshToken) if (context.RejectRefreshToken)
{ {
@ -4493,13 +4495,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectUserInfoToken) if (context.RejectUserInfoToken)
{ {
@ -4542,8 +4544,8 @@ public static partial class OpenIddictClientHandlers
Debug.Assert(context.UserInfoTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(context.UserInfoTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
foreach (var group in context.UserInfoTokenPrincipal.Claims foreach (var group in context.UserInfoTokenPrincipal.Claims
.GroupBy(static claim => claim.Type) .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
.ToDictionary(static group => group.Key, group => group.ToList()) .ToDictionary(static group => group.Key, group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value))) .Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{ {
context.Reject( context.Reject(
@ -4907,8 +4909,8 @@ public static partial class OpenIddictClientHandlers
} }
foreach (var group in context.Principal.Claims foreach (var group in context.Principal.Claims
.GroupBy(static claim => claim.Type) .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
.ToDictionary(static group => group.Key, static group => group.ToList()) .ToDictionary(static group => group.Key, static group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value))) .Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{ {
throw new InvalidOperationException(SR.FormatID0424(group.Key)); throw new InvalidOperationException(SR.FormatID0424(group.Key));
@ -5848,13 +5850,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -5912,7 +5914,7 @@ public static partial class OpenIddictClientHandlers
// Note: the final OAuth 2.0 specification requires using a space as the scope separator. // Note: the final OAuth 2.0 specification requires using a space as the scope separator.
// Clients that need to deal with older or non-compliant implementations can register // Clients that need to deal with older or non-compliant implementations can register
// a custom handler to use a different separator (typically, a comma). // a custom handler to use a different separator (typically, a comma).
context.Request.Scope = string.Join(" ", context.Scopes); context.Request.Scope = string.Join(Separators.Space[0], context.Scopes);
} }
// If a nonce was generated and the request is an OpenID Connect request where an authorization // If a nonce was generated and the request is an OpenID Connect request where an authorization
@ -6275,7 +6277,7 @@ public static partial class OpenIddictClientHandlers
// Note: the final OAuth 2.0 specification requires using a space as the scope separator. // Note: the final OAuth 2.0 specification requires using a space as the scope separator.
// Clients that need to deal with older or non-compliant implementations can register // Clients that need to deal with older or non-compliant implementations can register
// a custom handler to use a different separator (typically, a comma). // a custom handler to use a different separator (typically, a comma).
context.DeviceAuthorizationRequest.Scope = string.Join(" ", context.Scopes); context.DeviceAuthorizationRequest.Scope = string.Join(Separators.Space[0], context.Scopes);
} }
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
@ -6737,13 +6739,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -7900,13 +7902,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -8705,13 +8707,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -8908,8 +8910,8 @@ public static partial class OpenIddictClientHandlers
} }
foreach (var group in context.Principal.Claims foreach (var group in context.Principal.Claims
.GroupBy(static claim => claim.Type) .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
.ToDictionary(static group => group.Key, static group => group.ToList()) .ToDictionary(static group => group.Key, static group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value))) .Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{ {
throw new InvalidOperationException(SR.FormatID0424(group.Key)); throw new InvalidOperationException(SR.FormatID0424(group.Key));
@ -9358,13 +9360,13 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,

76
src/OpenIddict.Client/OpenIddictClientService.cs

@ -294,30 +294,27 @@ public class OpenIddictClientService
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
else Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013));
{
Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); return new()
{
return new() AuthorizationCode = context.AuthorizationCode,
{ AuthorizationResponse = context.Request is not null ? new(context.Request.GetParameters()) : new(),
AuthorizationCode = context.AuthorizationCode, BackchannelAccessToken = context.BackchannelAccessToken,
AuthorizationResponse = context.Request is not null ? new(context.Request.GetParameters()) : new(), BackchannelAccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate,
BackchannelAccessToken = context.BackchannelAccessToken, BackchannelIdentityToken = context.BackchannelIdentityToken,
BackchannelAccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, BackchannelIdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal,
BackchannelIdentityToken = context.BackchannelIdentityToken, FrontchannelAccessToken = context.FrontchannelAccessToken,
BackchannelIdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, FrontchannelAccessTokenExpirationDate = context.FrontchannelAccessTokenExpirationDate,
FrontchannelAccessToken = context.FrontchannelAccessToken, FrontchannelIdentityToken = context.FrontchannelIdentityToken,
FrontchannelAccessTokenExpirationDate = context.FrontchannelAccessTokenExpirationDate, FrontchannelIdentityTokenPrincipal = context.FrontchannelIdentityTokenPrincipal,
FrontchannelIdentityToken = context.FrontchannelIdentityToken, Principal = context.MergedPrincipal,
FrontchannelIdentityTokenPrincipal = context.FrontchannelIdentityTokenPrincipal, Properties = context.Properties,
Principal = context.MergedPrincipal, RefreshToken = context.RefreshToken,
Properties = context.Properties, StateTokenPrincipal = context.StateTokenPrincipal,
RefreshToken = context.RefreshToken, TokenResponse = context.TokenResponse ?? new(),
StateTokenPrincipal = context.StateTokenPrincipal, UserInfoTokenPrincipal = context.UserInfoTokenPrincipal
TokenResponse = context.TokenResponse ?? new(), };
UserInfoTokenPrincipal = context.UserInfoTokenPrincipal
};
}
} }
/// <summary> /// <summary>
@ -652,24 +649,21 @@ public class OpenIddictClientService
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
else Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013));
{
Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013));
return new() return new()
{ {
AccessToken = context.BackchannelAccessToken!, AccessToken = context.BackchannelAccessToken!,
AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate,
IdentityToken = context.BackchannelIdentityToken, IdentityToken = context.BackchannelIdentityToken,
IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal,
Principal = context.MergedPrincipal, Principal = context.MergedPrincipal,
Properties = context.Properties, Properties = context.Properties,
RefreshToken = context.RefreshToken, RefreshToken = context.RefreshToken,
TokenResponse = context.TokenResponse ?? new(), TokenResponse = context.TokenResponse ?? new(),
UserInfoToken = context.UserInfoToken, UserInfoToken = context.UserInfoToken,
UserInfoTokenPrincipal = context.UserInfoTokenPrincipal UserInfoTokenPrincipal = context.UserInfoTokenPrincipal
}; };
}
} }
catch (ProtocolException exception) when (exception.Error is Errors.AuthorizationPending) catch (ProtocolException exception) when (exception.Error is Errors.AuthorizationPending)

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

@ -582,13 +582,7 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
{ {
ArgumentNullException.ThrowIfNull(application); ArgumentNullException.ThrowIfNull(application);
var names = await Store.GetDisplayNamesAsync(application, cancellationToken); return await Store.GetDisplayNamesAsync(application, cancellationToken) is { IsEmpty: false } names ? names : [];
if (names is not { Count: > 0 })
{
return ImmutableDictionary.Create<CultureInfo, string>();
}
return names;
} }
/// <summary> /// <summary>
@ -2007,7 +2001,9 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictApplicationManager.GetLocalizedDisplayNameAsync(object application, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictApplicationManager.GetLocalizedDisplayNameAsync(object application, CancellationToken cancellationToken)
#pragma warning disable MA0011
=> GetLocalizedDisplayNameAsync((TApplication) application, cancellationToken); => GetLocalizedDisplayNameAsync((TApplication) application, cancellationToken);
#pragma warning restore MA0011
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictApplicationManager.GetLocalizedDisplayNameAsync(object application, CultureInfo culture, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictApplicationManager.GetLocalizedDisplayNameAsync(object application, CultureInfo culture, CancellationToken cancellationToken)

2
src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs

@ -896,7 +896,7 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
break; break;
} }
if (scope.Contains(Separators.Space[0])) if (scope.Contains(Separators.Space[0], StringComparison.Ordinal))
{ {
yield return new ValidationResult(SR.GetResourceString(SR.ID2042)); yield return new ValidationResult(SR.GetResourceString(SR.ID2042));

21
src/OpenIddict.Core/Managers/OpenIddictResourceManager.cs

@ -12,6 +12,7 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using static System.Net.Mime.MediaTypeNames;
using ValidationException = OpenIddict.Abstractions.OpenIddictExceptions.ValidationException; using ValidationException = OpenIddict.Abstractions.OpenIddictExceptions.ValidationException;
namespace OpenIddict.Core; namespace OpenIddict.Core;
@ -385,13 +386,7 @@ public class OpenIddictResourceManager<TResource> : IOpenIddictResourceManager w
{ {
ArgumentNullException.ThrowIfNull(resource); ArgumentNullException.ThrowIfNull(resource);
var descriptions = await Store.GetDescriptionsAsync(resource, cancellationToken); return await Store.GetDescriptionsAsync(resource, cancellationToken) is { IsEmpty: false } descriptions ? descriptions : [];
if (descriptions is not { Count: > 0 })
{
return ImmutableDictionary.Create<CultureInfo, string>();
}
return descriptions;
} }
/// <summary> /// <summary>
@ -424,13 +419,7 @@ public class OpenIddictResourceManager<TResource> : IOpenIddictResourceManager w
{ {
ArgumentNullException.ThrowIfNull(resource); ArgumentNullException.ThrowIfNull(resource);
var names = await Store.GetDisplayNamesAsync(resource, cancellationToken); return await Store.GetDisplayNamesAsync(resource, cancellationToken) is { IsEmpty: false } names ? names : [];
if (names is not { Count: > 0 })
{
return ImmutableDictionary.Create<CultureInfo, string>();
}
return names;
} }
/// <summary> /// <summary>
@ -880,7 +869,9 @@ public class OpenIddictResourceManager<TResource> : IOpenIddictResourceManager w
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictResourceManager.GetLocalizedDescriptionAsync(object resource, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictResourceManager.GetLocalizedDescriptionAsync(object resource, CancellationToken cancellationToken)
#pragma warning disable MA0011
=> GetLocalizedDescriptionAsync((TResource) resource, cancellationToken); => GetLocalizedDescriptionAsync((TResource) resource, cancellationToken);
#pragma warning restore MA0011
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictResourceManager.GetLocalizedDescriptionAsync(object resource, CultureInfo culture, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictResourceManager.GetLocalizedDescriptionAsync(object resource, CultureInfo culture, CancellationToken cancellationToken)
@ -888,7 +879,9 @@ public class OpenIddictResourceManager<TResource> : IOpenIddictResourceManager w
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictResourceManager.GetLocalizedDisplayNameAsync(object resource, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictResourceManager.GetLocalizedDisplayNameAsync(object resource, CancellationToken cancellationToken)
#pragma warning disable MA0011
=> GetLocalizedDisplayNameAsync((TResource) resource, cancellationToken); => GetLocalizedDisplayNameAsync((TResource) resource, cancellationToken);
#pragma warning restore MA0011
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictResourceManager.GetLocalizedDisplayNameAsync(object resource, CultureInfo culture, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictResourceManager.GetLocalizedDisplayNameAsync(object resource, CultureInfo culture, CancellationToken cancellationToken)

22
src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs

@ -424,13 +424,7 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
{ {
ArgumentNullException.ThrowIfNull(scope); ArgumentNullException.ThrowIfNull(scope);
var descriptions = await Store.GetDescriptionsAsync(scope, cancellationToken); return await Store.GetDescriptionsAsync(scope, cancellationToken) is { IsEmpty: false } descriptions ? descriptions : [];
if (descriptions is not { Count: > 0 })
{
return ImmutableDictionary.Create<CultureInfo, string>();
}
return descriptions;
} }
/// <summary> /// <summary>
@ -463,13 +457,7 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
{ {
ArgumentNullException.ThrowIfNull(scope); ArgumentNullException.ThrowIfNull(scope);
var names = await Store.GetDisplayNamesAsync(scope, cancellationToken); return await Store.GetDisplayNamesAsync(scope, cancellationToken) is { IsEmpty: false } names ? names : [];
if (names is not { Count: > 0 })
{
return ImmutableDictionary.Create<CultureInfo, string>();
}
return names;
} }
/// <summary> /// <summary>
@ -870,7 +858,7 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
yield return new ValidationResult(SR.GetResourceString(SR.ID2044)); yield return new ValidationResult(SR.GetResourceString(SR.ID2044));
} }
else if (name.Contains(Separators.Space[0])) else if (name.Contains(Separators.Space[0], StringComparison.Ordinal))
{ {
yield return new ValidationResult(SR.GetResourceString(SR.ID2045)); yield return new ValidationResult(SR.GetResourceString(SR.ID2045));
} }
@ -962,7 +950,9 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictScopeManager.GetLocalizedDescriptionAsync(object scope, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictScopeManager.GetLocalizedDescriptionAsync(object scope, CancellationToken cancellationToken)
#pragma warning disable MA0011
=> GetLocalizedDescriptionAsync((TScope) scope, cancellationToken); => GetLocalizedDescriptionAsync((TScope) scope, cancellationToken);
#pragma warning restore MA0011
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictScopeManager.GetLocalizedDescriptionAsync(object scope, CultureInfo culture, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictScopeManager.GetLocalizedDescriptionAsync(object scope, CultureInfo culture, CancellationToken cancellationToken)
@ -970,7 +960,9 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictScopeManager.GetLocalizedDisplayNameAsync(object scope, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictScopeManager.GetLocalizedDisplayNameAsync(object scope, CancellationToken cancellationToken)
#pragma warning disable MA0011
=> GetLocalizedDisplayNameAsync((TScope) scope, cancellationToken); => GetLocalizedDisplayNameAsync((TScope) scope, cancellationToken);
#pragma warning restore MA0011
/// <inheritdoc/> /// <inheritdoc/>
ValueTask<string?> IOpenIddictScopeManager.GetLocalizedDisplayNameAsync(object scope, CultureInfo culture, CancellationToken cancellationToken) ValueTask<string?> IOpenIddictScopeManager.GetLocalizedDisplayNameAsync(object scope, CultureInfo culture, CancellationToken cancellationToken)

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

@ -352,7 +352,7 @@ public class OpenIddictEntityFrameworkApplicationStore<
if (string.IsNullOrEmpty(application.DisplayNames)) if (string.IsNullOrEmpty(application.DisplayNames))
{ {
return new(ImmutableDictionary.Create<CultureInfo, string>()); return new([]);
} }
// Note: parsing the stringified display names is an expensive operation. // Note: parsing the stringified display names is an expensive operation.
@ -498,7 +498,7 @@ public class OpenIddictEntityFrameworkApplicationStore<
if (string.IsNullOrEmpty(application.Properties)) if (string.IsNullOrEmpty(application.Properties))
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
// Note: parsing the stringified properties is an expensive operation. // Note: parsing the stringified properties is an expensive operation.
@ -510,7 +510,7 @@ public class OpenIddictEntityFrameworkApplicationStore<
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(application.Properties); using var document = JsonDocument.Parse(application.Properties);
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -606,7 +606,7 @@ public class OpenIddictEntityFrameworkApplicationStore<
if (string.IsNullOrEmpty(application.Settings)) if (string.IsNullOrEmpty(application.Settings))
{ {
return new(ImmutableDictionary.Create<string, string>()); return new([]);
} }
// Note: parsing the stringified settings is an expensive operation. // Note: parsing the stringified settings is an expensive operation.
@ -618,7 +618,7 @@ public class OpenIddictEntityFrameworkApplicationStore<
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(application.Settings); using var document = JsonDocument.Parse(application.Settings);
var builder = ImmutableDictionary.CreateBuilder<string, string>(); var builder = ImmutableDictionary.CreateBuilder<string, string>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -1060,17 +1060,14 @@ public class OpenIddictEntityFrameworkApplicationStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -1091,16 +1088,13 @@ public class OpenIddictEntityFrameworkApplicationStore<
return value; return value;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
} }

28
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs

@ -302,7 +302,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
{ {
ArgumentNullException.ThrowIfNull(authorization); ArgumentNullException.ThrowIfNull(authorization);
return new(authorization.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(authorization.CreationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -320,7 +320,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
if (string.IsNullOrEmpty(authorization.Properties)) if (string.IsNullOrEmpty(authorization.Properties))
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
// Note: parsing the stringified properties is an expensive operation. // Note: parsing the stringified properties is an expensive operation.
@ -332,7 +332,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(authorization.Properties); using var document = JsonDocument.Parse(authorization.Properties);
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -894,17 +894,14 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -925,16 +922,13 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
return value; return value;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
} }

30
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkResourceStore.cs

@ -210,7 +210,7 @@ public class OpenIddictEntityFrameworkResourceStore<
if (string.IsNullOrEmpty(resource.Descriptions)) if (string.IsNullOrEmpty(resource.Descriptions))
{ {
return new(ImmutableDictionary.Create<CultureInfo, string>()); return new([]);
} }
// Note: parsing the stringified descriptions is an expensive operation. // Note: parsing the stringified descriptions is an expensive operation.
@ -256,7 +256,7 @@ public class OpenIddictEntityFrameworkResourceStore<
if (string.IsNullOrEmpty(resource.DisplayNames)) if (string.IsNullOrEmpty(resource.DisplayNames))
{ {
return new(ImmutableDictionary.Create<CultureInfo, string>()); return new([]);
} }
// Note: parsing the stringified display names is an expensive operation. // Note: parsing the stringified display names is an expensive operation.
@ -310,7 +310,7 @@ public class OpenIddictEntityFrameworkResourceStore<
if (string.IsNullOrEmpty(resource.Properties)) if (string.IsNullOrEmpty(resource.Properties))
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
// Note: parsing the stringified properties is an expensive operation. // Note: parsing the stringified properties is an expensive operation.
@ -322,7 +322,7 @@ public class OpenIddictEntityFrameworkResourceStore<
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(resource.Properties); using var document = JsonDocument.Parse(resource.Properties);
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -579,17 +579,14 @@ public class OpenIddictEntityFrameworkResourceStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -610,16 +607,13 @@ public class OpenIddictEntityFrameworkResourceStore<
return value; return value;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
} }

30
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs

@ -242,7 +242,7 @@ public class OpenIddictEntityFrameworkScopeStore<
if (string.IsNullOrEmpty(scope.Descriptions)) if (string.IsNullOrEmpty(scope.Descriptions))
{ {
return new(ImmutableDictionary.Create<CultureInfo, string>()); return new([]);
} }
// Note: parsing the stringified descriptions is an expensive operation. // Note: parsing the stringified descriptions is an expensive operation.
@ -288,7 +288,7 @@ public class OpenIddictEntityFrameworkScopeStore<
if (string.IsNullOrEmpty(scope.DisplayNames)) if (string.IsNullOrEmpty(scope.DisplayNames))
{ {
return new(ImmutableDictionary.Create<CultureInfo, string>()); return new([]);
} }
// Note: parsing the stringified display names is an expensive operation. // Note: parsing the stringified display names is an expensive operation.
@ -342,7 +342,7 @@ public class OpenIddictEntityFrameworkScopeStore<
if (string.IsNullOrEmpty(scope.Properties)) if (string.IsNullOrEmpty(scope.Properties))
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
// Note: parsing the stringified properties is an expensive operation. // Note: parsing the stringified properties is an expensive operation.
@ -354,7 +354,7 @@ public class OpenIddictEntityFrameworkScopeStore<
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(scope.Properties); using var document = JsonDocument.Parse(scope.Properties);
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -683,17 +683,14 @@ public class OpenIddictEntityFrameworkScopeStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -714,16 +711,13 @@ public class OpenIddictEntityFrameworkScopeStore<
return value; return value;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
} }

28
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkSessionStore.cs

@ -343,7 +343,7 @@ public class OpenIddictEntityFrameworkSessionStore<
{ {
ArgumentNullException.ThrowIfNull(session); ArgumentNullException.ThrowIfNull(session);
return new(session.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(session.CreationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -369,7 +369,7 @@ public class OpenIddictEntityFrameworkSessionStore<
if (string.IsNullOrEmpty(session.Properties)) if (string.IsNullOrEmpty(session.Properties))
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
// Note: parsing the stringified properties is an expensive operation. // Note: parsing the stringified properties is an expensive operation.
@ -381,7 +381,7 @@ public class OpenIddictEntityFrameworkSessionStore<
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(session.Properties); using var document = JsonDocument.Parse(session.Properties);
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -660,17 +660,14 @@ public class OpenIddictEntityFrameworkSessionStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -691,16 +688,13 @@ public class OpenIddictEntityFrameworkSessionStore<
return value; return value;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
} }

32
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs

@ -342,7 +342,7 @@ public class OpenIddictEntityFrameworkTokenStore<
{ {
ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(token);
return new(token.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(token.CreationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -350,7 +350,7 @@ public class OpenIddictEntityFrameworkTokenStore<
{ {
ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(token);
return new(token.ExpirationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(token.ExpirationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -376,7 +376,7 @@ public class OpenIddictEntityFrameworkTokenStore<
if (string.IsNullOrEmpty(token.Properties)) if (string.IsNullOrEmpty(token.Properties))
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
// Note: parsing the stringified properties is an expensive operation. // Note: parsing the stringified properties is an expensive operation.
@ -388,7 +388,7 @@ public class OpenIddictEntityFrameworkTokenStore<
.SetSlidingExpiration(TimeSpan.FromMinutes(1)); .SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(token.Properties); using var document = JsonDocument.Parse(token.Properties);
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -406,7 +406,7 @@ public class OpenIddictEntityFrameworkTokenStore<
{ {
ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(token);
return new(token.RedemptionDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(token.RedemptionDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -1016,17 +1016,14 @@ public class OpenIddictEntityFrameworkTokenStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -1047,16 +1044,13 @@ public class OpenIddictEntityFrameworkTokenStore<
return value; return value;
} }
else var converter =
{
var converter =
#if NET #if NET
TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey)); TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else #else
TypeDescriptor.GetConverter(typeof(TKey)); TypeDescriptor.GetConverter(typeof(TKey));
#endif #endif
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
} }

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

@ -587,7 +587,7 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<
ArgumentNullException.ThrowIfNull(application); ArgumentNullException.ThrowIfNull(application);
application.DisplayNames = names is { IsEmpty: false } application.DisplayNames = names is { IsEmpty: false }
? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
@ -714,12 +714,9 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -740,12 +737,9 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<
return value; return value;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
/// <summary> /// <summary>

16
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs

@ -361,7 +361,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
{ {
ArgumentNullException.ThrowIfNull(authorization); ArgumentNullException.ThrowIfNull(authorization);
return new(authorization.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(authorization.CreationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -931,12 +931,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -957,12 +954,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
return value; return value;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
/// <summary> /// <summary>

18
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreResourceStore.cs

@ -334,7 +334,7 @@ public class OpenIddictEntityFrameworkCoreResourceStore<
ArgumentNullException.ThrowIfNull(resource); ArgumentNullException.ThrowIfNull(resource);
resource.Descriptions = descriptions is { IsEmpty: false } resource.Descriptions = descriptions is { IsEmpty: false }
? descriptions.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? descriptions.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
@ -357,7 +357,7 @@ public class OpenIddictEntityFrameworkCoreResourceStore<
ArgumentNullException.ThrowIfNull(resource); ArgumentNullException.ThrowIfNull(resource);
resource.DisplayNames = names is { IsEmpty: false } resource.DisplayNames = names is { IsEmpty: false }
? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
@ -431,12 +431,9 @@ public class OpenIddictEntityFrameworkCoreResourceStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -457,11 +454,8 @@ public class OpenIddictEntityFrameworkCoreResourceStore<
return value; return value;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
} }

20
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs

@ -233,7 +233,7 @@ public class OpenIddictEntityFrameworkCoreScopeStore<
return new(scope.Descriptions is { Count: > 0 } descriptions return new(scope.Descriptions is { Count: > 0 } descriptions
? descriptions.ToImmutableDictionary(static pair => CultureInfo.GetCultureInfo(pair.Key), static pair => pair.Value) ? descriptions.ToImmutableDictionary(static pair => CultureInfo.GetCultureInfo(pair.Key), static pair => pair.Value)
: ImmutableDictionary.Create<CultureInfo, string>()); : []);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -362,7 +362,7 @@ public class OpenIddictEntityFrameworkCoreScopeStore<
ArgumentNullException.ThrowIfNull(scope); ArgumentNullException.ThrowIfNull(scope);
scope.Descriptions = descriptions is { IsEmpty: false } scope.Descriptions = descriptions is { IsEmpty: false }
? descriptions.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? descriptions.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
@ -385,7 +385,7 @@ public class OpenIddictEntityFrameworkCoreScopeStore<
ArgumentNullException.ThrowIfNull(scope); ArgumentNullException.ThrowIfNull(scope);
scope.DisplayNames = names is { IsEmpty: false } scope.DisplayNames = names is { IsEmpty: false }
? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
@ -469,12 +469,9 @@ public class OpenIddictEntityFrameworkCoreScopeStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -495,11 +492,8 @@ public class OpenIddictEntityFrameworkCoreScopeStore<
return value; return value;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
} }

16
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreSessionStore.cs

@ -364,7 +364,7 @@ public class OpenIddictEntityFrameworkCoreSessionStore<
{ {
ArgumentNullException.ThrowIfNull(session); ArgumentNullException.ThrowIfNull(session);
return new(session.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(session.CreationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -632,12 +632,9 @@ public class OpenIddictEntityFrameworkCoreSessionStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -658,11 +655,8 @@ public class OpenIddictEntityFrameworkCoreSessionStore<
return value; return value;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
} }

20
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs

@ -358,7 +358,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
{ {
ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(token);
return new(token.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(token.CreationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -366,7 +366,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
{ {
ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(token);
return new(token.ExpirationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(token.ExpirationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -398,7 +398,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
{ {
ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(token);
return new(token.RedemptionDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(token.RedemptionDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -1080,12 +1080,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
return (TKey?) (object?) identifier; return (TKey?) (object?) identifier;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return (TKey?) converter.ConvertFromInvariantString(identifier); return (TKey?) converter.ConvertFromInvariantString(identifier);
}
} }
/// <summary> /// <summary>
@ -1106,12 +1103,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
return value; return value;
} }
else var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
{
var converter = TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
return converter.ConvertToInvariantString(identifier); return converter.ConvertToInvariantString(identifier);
}
} }
/// <summary> /// <summary>

2
src/OpenIddict.MongoDb.Models/OpenIddictMongoDbSession.cs

@ -11,7 +11,7 @@ namespace OpenIddict.MongoDb.Models;
/// <summary> /// <summary>
/// Represents an OpenIddict session. /// Represents an OpenIddict session.
/// </summary> /// </summary>
[DebuggerDisplay("Id = {Id.ToString(),nq} ; Name = {Name,nq}")] [DebuggerDisplay("Id = {Id.ToString(),nq} ; Subject = {Subject,nq} ; LoginId = {LoginId,nq} ; Status = {Status,nq}")]
public class OpenIddictMongoDbSession public class OpenIddictMongoDbSession
{ {
/// <summary> /// <summary>

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

@ -291,11 +291,11 @@ public class OpenIddictMongoDbApplicationStore<
if (application.Properties is null) if (application.Properties is null)
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
using var document = JsonDocument.Parse(application.Properties.ToJson()); using var document = JsonDocument.Parse(application.Properties.ToJson());
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -464,7 +464,7 @@ public class OpenIddictMongoDbApplicationStore<
ArgumentNullException.ThrowIfNull(application); ArgumentNullException.ThrowIfNull(application);
application.DisplayNames = names is { Count: > 0 } application.DisplayNames = names is { Count: > 0 }
? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;

6
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs

@ -229,7 +229,7 @@ public class OpenIddictMongoDbAuthorizationStore<
{ {
ArgumentNullException.ThrowIfNull(authorization); ArgumentNullException.ThrowIfNull(authorization);
return new(authorization.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(authorization.CreationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -247,11 +247,11 @@ public class OpenIddictMongoDbAuthorizationStore<
if (authorization.Properties is null) if (authorization.Properties is null)
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
using var document = JsonDocument.Parse(authorization.Properties.ToJson()); using var document = JsonDocument.Parse(authorization.Properties.ToJson());
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {

8
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbResourceStore.cs

@ -221,11 +221,11 @@ public class OpenIddictMongoDbResourceStore<
if (resource.Properties is null) if (resource.Properties is null)
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
using var document = JsonDocument.Parse(resource.Properties.ToJson()); using var document = JsonDocument.Parse(resource.Properties.ToJson());
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -313,7 +313,7 @@ public class OpenIddictMongoDbResourceStore<
ArgumentNullException.ThrowIfNull(resource); ArgumentNullException.ThrowIfNull(resource);
resource.Descriptions = descriptions is { Count: > 0 } resource.Descriptions = descriptions is { Count: > 0 }
? descriptions.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? descriptions.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
@ -326,7 +326,7 @@ public class OpenIddictMongoDbResourceStore<
ArgumentNullException.ThrowIfNull(resource); ArgumentNullException.ThrowIfNull(resource);
resource.DisplayNames = names is { Count: > 0 } resource.DisplayNames = names is { Count: > 0 }
? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;

8
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs

@ -240,11 +240,11 @@ public class OpenIddictMongoDbScopeStore<
if (scope.Properties is null) if (scope.Properties is null)
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
using var document = JsonDocument.Parse(scope.Properties.ToJson()); using var document = JsonDocument.Parse(scope.Properties.ToJson());
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -340,7 +340,7 @@ public class OpenIddictMongoDbScopeStore<
ArgumentNullException.ThrowIfNull(scope); ArgumentNullException.ThrowIfNull(scope);
scope.Descriptions = descriptions is { Count: > 0 } scope.Descriptions = descriptions is { Count: > 0 }
? descriptions.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? descriptions.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
@ -353,7 +353,7 @@ public class OpenIddictMongoDbScopeStore<
ArgumentNullException.ThrowIfNull(scope); ArgumentNullException.ThrowIfNull(scope);
scope.DisplayNames = names is { Count: > 0 } scope.DisplayNames = names is { Count: > 0 }
? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value) ? names.ToImmutableDictionary(static pair => pair.Key.Name, static pair => pair.Value, StringComparer.Ordinal)
: null; : null;
return ValueTask.CompletedTask; return ValueTask.CompletedTask;

6
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbSessionStore.cs

@ -263,7 +263,7 @@ public class OpenIddictMongoDbSessionStore<
{ {
ArgumentNullException.ThrowIfNull(session); ArgumentNullException.ThrowIfNull(session);
return new(session.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(session.CreationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -289,11 +289,11 @@ public class OpenIddictMongoDbSessionStore<
if (session.Properties is null) if (session.Properties is null)
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
using var document = JsonDocument.Parse(session.Properties.ToJson()); using var document = JsonDocument.Parse(session.Properties.ToJson());
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {

10
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs

@ -255,7 +255,7 @@ public class OpenIddictMongoDbTokenStore<
{ {
ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(token);
return new(token.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(token.CreationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -263,7 +263,7 @@ public class OpenIddictMongoDbTokenStore<
{ {
ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(token);
return new(token.ExpirationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(token.ExpirationDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -289,11 +289,11 @@ public class OpenIddictMongoDbTokenStore<
if (token.Properties is null) if (token.Properties is null)
{ {
return new(ImmutableDictionary.Create<string, JsonElement>()); return new([]);
} }
using var document = JsonDocument.Parse(token.Properties.ToJson()); using var document = JsonDocument.Parse(token.Properties.ToJson());
var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(); var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject()) foreach (var property in document.RootElement.EnumerateObject())
{ {
@ -308,7 +308,7 @@ public class OpenIddictMongoDbTokenStore<
{ {
ArgumentNullException.ThrowIfNull(token); ArgumentNullException.ThrowIfNull(token);
return new(token.RedemptionDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null); return new(token.RedemptionDate is DateTime date ? new DateTimeOffset(DateTime.SpecifyKind(date, DateTimeKind.Utc)) : null);
} }
/// <inheritdoc/> /// <inheritdoc/>

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

@ -76,12 +76,12 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
return true; return true;
} }
else if (context.IsRequestSkipped) if (context.IsRequestSkipped)
{ {
return false; return false;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -98,7 +98,7 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
return true; return true;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
return false; return false;
} }
@ -133,7 +133,7 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
return AuthenticateResult.NoResult(); return AuthenticateResult.NoResult();
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
// Note: the missing_token error is special-cased to indicate to ASP.NET Core // Note: the missing_token error is special-cased to indicate to ASP.NET Core
// that no authentication result could be produced due to the lack of token. // that no authentication result could be produced due to the lack of token.
@ -405,7 +405,7 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -453,7 +453,7 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -494,7 +494,7 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {

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

@ -768,7 +768,7 @@ public static partial class OpenIddictServerAspNetCoreHandlers
var value = header["Basic ".Length..].Trim(); var value = header["Basic ".Length..].Trim();
var data = Encoding.ASCII.GetString(Convert.FromBase64String(value)); var data = Encoding.ASCII.GetString(Convert.FromBase64String(value));
var index = data.IndexOf(':'); var index = data.IndexOf(':', StringComparison.Ordinal);
if (index is < 0) if (index is < 0)
{ {
context.Reject( context.Reject(
@ -803,7 +803,7 @@ public static partial class OpenIddictServerAspNetCoreHandlers
return null; return null;
} }
return Uri.UnescapeDataString(data.Replace("+", "%20")); return Uri.UnescapeDataString(data.Replace("+", "%20", StringComparison.Ordinal));
} }
} }
} }
@ -1102,7 +1102,7 @@ public static partial class OpenIddictServerAspNetCoreHandlers
builder.Append(parameter.Key); builder.Append(parameter.Key);
builder.Append('='); builder.Append('=');
builder.Append('"'); builder.Append('"');
builder.Append(parameter.Value.Replace("\"", "\\\"")); builder.Append(parameter.Value.Replace("\"", "\\\"", StringComparison.Ordinal));
builder.Append('"'); builder.Append('"');
builder.Append(','); builder.Append(',');
} }

2
src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs

@ -192,7 +192,7 @@ public sealed class OpenIddictServerDataProtectionFormatter : IOpenIddictServerD
ArgumentNullException.ThrowIfNull(writer); ArgumentNullException.ThrowIfNull(writer);
ArgumentNullException.ThrowIfNull(principal); ArgumentNullException.ThrowIfNull(principal);
var properties = new Dictionary<string, string>(); var properties = new Dictionary<string, string>(StringComparer.Ordinal);
// Unlike ASP.NET Core Data Protection-based tokens, tokens serialized using the new format // Unlike ASP.NET Core Data Protection-based tokens, tokens serialized using the new format
// can't include authentication properties. To ensure tokens can be used with previous versions // can't include authentication properties. To ensure tokens can be used with previous versions

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

@ -86,12 +86,12 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
return true; return true;
} }
else if (context.IsRequestSkipped) if (context.IsRequestSkipped)
{ {
return false; return false;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -108,7 +108,7 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
return true; return true;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
return false; return false;
} }
@ -143,7 +143,7 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
return null; return null;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
// Note: the missing_token error is special-cased to indicate to Katana // Note: the missing_token error is special-cased to indicate to Katana
// that no authentication result could be produced due to the lack of token. // that no authentication result could be produced due to the lack of token.
@ -302,7 +302,7 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -344,7 +344,7 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -385,7 +385,7 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {

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

@ -845,7 +845,7 @@ public static partial class OpenIddictServerOwinHandlers
var value = header["Basic ".Length..].Trim(); var value = header["Basic ".Length..].Trim();
var data = Encoding.ASCII.GetString(Convert.FromBase64String(value)); var data = Encoding.ASCII.GetString(Convert.FromBase64String(value));
var index = data.IndexOf(':'); var index = data.IndexOf(':', StringComparison.Ordinal);
if (index is < 0) if (index is < 0)
{ {
context.Reject( context.Reject(
@ -880,7 +880,7 @@ public static partial class OpenIddictServerOwinHandlers
return null; return null;
} }
return Uri.UnescapeDataString(data.Replace("+", "%20")); return Uri.UnescapeDataString(data.Replace("+", "%20", StringComparison.Ordinal));
} }
} }
} }
@ -1293,7 +1293,7 @@ public static partial class OpenIddictServerOwinHandlers
builder.Append(parameter.Key); builder.Append(parameter.Key);
builder.Append('='); builder.Append('=');
builder.Append('"'); builder.Append('"');
builder.Append(parameter.Value.Replace("\"", "\\\"")); builder.Append(parameter.Value.Replace("\"", "\\\"", StringComparison.Ordinal));
builder.Append('"'); builder.Append('"');
builder.Append(','); builder.Append(',');
} }

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

@ -154,13 +154,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -217,13 +217,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -276,13 +276,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -315,13 +315,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (@event.IsRequestSkipped) if (@event.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (@event.IsRejected) if (@event.IsRejected)
{ {
context.Reject( context.Reject(
error: @event.Error ?? Errors.InvalidRequest, error: @event.Error ?? Errors.InvalidRequest,
@ -356,13 +356,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (@event.IsRequestSkipped) if (@event.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (@event.IsRejected) if (@event.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -411,7 +411,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -605,13 +605,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -2369,13 +2369,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -2433,13 +2433,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -2493,13 +2493,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -2539,13 +2539,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (@event.IsRequestSkipped) if (@event.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (@event.IsRejected) if (@event.IsRejected)
{ {
context.Reject( context.Reject(
error: @event.Error ?? Errors.InvalidGrant, error: @event.Error ?? Errors.InvalidGrant,
@ -2592,7 +2592,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -3392,13 +3392,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,

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

@ -98,13 +98,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -157,13 +157,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -211,13 +211,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -257,13 +257,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (@event.IsRequestSkipped) if (@event.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (@event.IsRejected) if (@event.IsRejected)
{ {
context.Reject( context.Reject(
error: @event.Error ?? Errors.InvalidGrant, error: @event.Error ?? Errors.InvalidGrant,
@ -309,7 +309,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -544,13 +544,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -778,13 +778,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -841,13 +841,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -895,13 +895,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -934,13 +934,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (@event.IsRequestSkipped) if (@event.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (@event.IsRejected) if (@event.IsRejected)
{ {
context.Reject( context.Reject(
error: @event.Error ?? Errors.InvalidGrant, error: @event.Error ?? Errors.InvalidGrant,
@ -989,7 +989,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -1037,13 +1037,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,

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

@ -99,13 +99,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -158,13 +158,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -212,13 +212,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -339,7 +339,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -902,13 +902,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -961,13 +961,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -1015,13 +1015,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -1166,7 +1166,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -1257,7 +1257,7 @@ public static partial class OpenIddictServerHandlers
if (credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha256) || if (credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha256) ||
credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha384) || credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha384) ||
credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha512)) credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha512))
{; {
if (!TryGetECParameters(credentials.Key, out var parameters)) if (!TryGetECParameters(credentials.Key, out var parameters))
{ {
context.Logger.LogWarning(6074, SR.GetResourceString(SR.ID6074), credentials.Key.GetType().Name); context.Logger.LogWarning(6074, SR.GetResourceString(SR.ID6074), credentials.Key.GetType().Name);

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

@ -110,13 +110,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -173,13 +173,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -227,13 +227,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidGrant, error: notification.Error ?? Errors.InvalidGrant,
@ -266,13 +266,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (@event.IsRequestSkipped) if (@event.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (@event.IsRejected) if (@event.IsRejected)
{ {
context.Reject( context.Reject(
error: @event.Error ?? Errors.InvalidRequest, error: @event.Error ?? Errors.InvalidRequest,
@ -321,7 +321,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -1226,13 +1226,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -2099,11 +2099,7 @@ public static partial class OpenIddictServerHandlers
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
} }
// When an explicit scope parameter has been included in the token request, if (!scopes.IsSupersetOf(context.Request.GetScopes()))
// the authorization server MUST ensure that it doesn't contain scopes
// that were not granted during the initial authorization/token request.
// See https://tools.ietf.org/html/rfc6749#section-6 for more information.
else if (!scopes.IsSupersetOf(context.Request.GetScopes()))
{ {
context.Logger.LogInformation(6095, SR.GetResourceString(SR.ID6095), Parameters.Scope); context.Logger.LogInformation(6095, SR.GetResourceString(SR.ID6095), Parameters.Scope);
@ -2172,7 +2168,7 @@ public static partial class OpenIddictServerHandlers
// reused as-is and that a new ad-hoc authorization, separate from the one attached // reused as-is and that a new ad-hoc authorization, separate from the one attached
// to the subject token will be created and attached to the issued token by OpenIddict. // to the subject token will be created and attached to the issued token by OpenIddict.
GrantTypes.TokenExchange => notification.SubjectTokenPrincipal GrantTypes.TokenExchange => notification.SubjectTokenPrincipal
?.Clone(claim => !claim.Type.StartsWith(Claims.Prefixes.Private)), ?.Clone(claim => !claim.Type.StartsWith(Claims.Prefixes.Private, StringComparison.Ordinal)),
_ => null _ => null
}; };

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

@ -91,13 +91,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -154,13 +154,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -208,13 +208,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -229,7 +229,7 @@ public static partial class OpenIddictServerHandlers
[Claims.Issuer] = notification.Issuer?.AbsoluteUri, [Claims.Issuer] = notification.Issuer?.AbsoluteUri,
[Claims.Username] = notification.Username, [Claims.Username] = notification.Username,
[Claims.Subject] = notification.Subject, [Claims.Subject] = notification.Subject,
[Claims.Scope] = string.Join(" ", notification.Scopes), [Claims.Scope] = string.Join(Separators.Space[0], notification.Scopes),
[Claims.JwtId] = notification.TokenId, [Claims.JwtId] = notification.TokenId,
[Claims.TokenType] = notification.TokenType, [Claims.TokenType] = notification.TokenType,
[Claims.TokenUsage] = notification.TokenUsage, [Claims.TokenUsage] = notification.TokenUsage,
@ -313,7 +313,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -474,13 +474,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -830,7 +830,7 @@ public static partial class OpenIddictServerHandlers
context.Username = context.GenericTokenPrincipal.Identity.Name; context.Username = context.GenericTokenPrincipal.Identity.Name;
context.Scopes.UnionWith(context.GenericTokenPrincipal.GetScopes()); context.Scopes.UnionWith(context.GenericTokenPrincipal.GetScopes());
foreach (var group in context.GenericTokenPrincipal.Claims.GroupBy(claim => claim.Type)) foreach (var group in context.GenericTokenPrincipal.Claims.GroupBy(claim => claim.Type, StringComparer.Ordinal))
{ {
// Exclude standard claims, that are already handled via strongly-typed properties. // Exclude standard claims, that are already handled via strongly-typed properties.
// Make sure to always update this list when adding new built-in claim properties. // Make sure to always update this list when adding new built-in claim properties.

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

@ -587,7 +587,7 @@ public static partial class OpenIddictServerHandlers
// retrieved as a Dictionary<string, string[]> and converted to ImmutableDictionary<string, ImmutableArray<string>. // retrieved as a Dictionary<string, string[]> and converted to ImmutableDictionary<string, ImmutableArray<string>.
if (token.TryGetPayloadValue(Claims.Private.ClaimDestinationsMap, out Dictionary<string, string[]> destinations)) if (token.TryGetPayloadValue(Claims.Private.ClaimDestinationsMap, out Dictionary<string, string[]> destinations))
{ {
var builder = ImmutableDictionary.CreateBuilder<string, ImmutableArray<string>>(); var builder = ImmutableDictionary.CreateBuilder<string, ImmutableArray<string>>(StringComparer.Ordinal);
foreach (var destination in destinations) foreach (var destination in destinations)
{ {
@ -640,7 +640,7 @@ public static partial class OpenIddictServerHandlers
var scopes = context.Principal.GetClaims(Claims.Scope); var scopes = context.Principal.GetClaims(Claims.Scope);
if (scopes.Length is > 1) if (scopes.Length is > 1)
{ {
context.Principal.SetClaim(Claims.Scope, string.Join(" ", scopes)); context.Principal.SetClaim(Claims.Scope, string.Join(Separators.Space[0], scopes));
} }
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
@ -1700,7 +1700,7 @@ public static partial class OpenIddictServerHandlers
var scopes = context.Principal.GetScopes(); var scopes = context.Principal.GetScopes();
if (scopes.Any()) if (scopes.Any())
{ {
claims.Add(Claims.Scope, string.Join(" ", scopes)); claims.Add(Claims.Scope, string.Join(Separators.Space[0], scopes));
} }
claims.Add(Claims.JwtId, Guid.NewGuid().ToString()); claims.Add(Claims.JwtId, Guid.NewGuid().ToString());

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

@ -83,13 +83,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -146,13 +146,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -200,13 +200,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -254,7 +254,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -415,13 +415,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,

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

@ -90,13 +90,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -153,13 +153,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -207,13 +207,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -245,13 +245,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (@event.IsRequestSkipped) if (@event.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (@event.IsRejected) if (@event.IsRejected)
{ {
context.Reject( context.Reject(
error: @event.Error ?? Errors.InvalidRequest, error: @event.Error ?? Errors.InvalidRequest,
@ -286,13 +286,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (@event.IsRequestSkipped) if (@event.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (@event.IsRejected) if (@event.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -341,7 +341,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -488,13 +488,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,

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

@ -76,13 +76,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -139,13 +139,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -193,13 +193,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -282,7 +282,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
@ -366,13 +366,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,

94
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -662,13 +662,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectClientAssertion) if (context.RejectClientAssertion)
{ {
@ -710,8 +710,8 @@ public static partial class OpenIddictServerHandlers
Debug.Assert(context.ClientAssertionPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(context.ClientAssertionPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
foreach (var group in context.ClientAssertionPrincipal.Claims foreach (var group in context.ClientAssertionPrincipal.Claims
.GroupBy(static claim => claim.Type) .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
.ToDictionary(static group => group.Key, group => group.ToList()) .ToDictionary(static group => group.Key, group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value))) .Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{ {
context.Reject( context.Reject(
@ -1545,13 +1545,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectRequestToken) if (context.RejectRequestToken)
{ {
@ -1667,13 +1667,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectAccessToken) if (context.RejectAccessToken)
{ {
@ -1746,13 +1746,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectAuthorizationCode) if (context.RejectAuthorizationCode)
{ {
@ -1825,13 +1825,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectDeviceCode) if (context.RejectDeviceCode)
{ {
@ -1921,13 +1921,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectGenericToken) if (context.RejectGenericToken)
{ {
@ -2007,13 +2007,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectIdentityToken) if (context.RejectIdentityToken)
{ {
@ -2086,13 +2086,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectRefreshToken) if (context.RejectRefreshToken)
{ {
@ -2192,13 +2192,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectSubjectToken) if (context.RejectSubjectToken)
{ {
@ -2298,13 +2298,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectActorToken) if (context.RejectActorToken)
{ {
@ -2377,13 +2377,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectUserCode) if (context.RejectUserCode)
{ {
@ -2840,8 +2840,8 @@ public static partial class OpenIddictServerHandlers
} }
foreach (var group in context.Principal.Claims foreach (var group in context.Principal.Claims
.GroupBy(static claim => claim.Type) .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
.ToDictionary(static group => group.Key, static group => group.ToList()) .ToDictionary(static group => group.Key, static group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value))) .Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{ {
throw new InvalidOperationException(SR.FormatID0424(group.Key)); throw new InvalidOperationException(SR.FormatID0424(group.Key));
@ -3089,11 +3089,11 @@ public static partial class OpenIddictServerHandlers
// Restore the internal claims resolved from the token. // Restore the internal claims resolved from the token.
foreach (var claims in principal.Claims foreach (var claims in principal.Claims
.Where(claim => claim.Type.StartsWith(Claims.Prefixes.Private, StringComparison.OrdinalIgnoreCase)) .Where(claim => claim.Type.StartsWith(Claims.Prefixes.Private, StringComparison.Ordinal))
.GroupBy(claim => claim.Type)) .GroupBy(claim => claim.Type, StringComparer.Ordinal))
{ {
// If the specified principal already contains one claim of the iterated type, ignore them. // If the specified principal already contains one claim of the iterated type, ignore them.
if (context.Principal.Claims.Any(claim => claim.Type == claims.Key)) if (context.Principal.Claims.Any(claim => string.Equals(claim.Type, claims.Key, StringComparison.Ordinal)))
{ {
continue; continue;
} }
@ -3652,7 +3652,7 @@ public static partial class OpenIddictServerHandlers
context.Request.IsRefreshTokenGrantType() && !string.IsNullOrEmpty(context.Request.Scope)) context.Request.IsRefreshTokenGrantType() && !string.IsNullOrEmpty(context.Request.Scope))
{ {
var scopes = context.Request.GetScopes(); var scopes = context.Request.GetScopes();
principal.SetScopes(scopes.Intersect(context.Principal.GetScopes())); principal.SetScopes(scopes.Intersect(context.Principal.GetScopes(), StringComparer.Ordinal));
context.Logger.LogDebug(6010, SR.GetResourceString(SR.ID6010), scopes); context.Logger.LogDebug(6010, SR.GetResourceString(SR.ID6010), scopes);
} }
@ -4807,13 +4807,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -4871,13 +4871,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -4949,13 +4949,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -5025,13 +5025,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -5089,13 +5089,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -5155,13 +5155,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -5436,13 +5436,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -5501,13 +5501,13 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -5622,7 +5622,7 @@ public static partial class OpenIddictServerHandlers
context.Request.IsAuthorizationCodeGrantType()) || context.Request.IsAuthorizationCodeGrantType()) ||
!scopes.SetEquals(context.Request.GetScopes())) !scopes.SetEquals(context.Request.GetScopes()))
{ {
context.Response.Scope = string.Join(" ", scopes); context.Response.Scope = string.Join(Separators.Space[0], scopes);
} }
} }
} }

10
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs

@ -74,12 +74,12 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle
return true; return true;
} }
else if (context.IsRequestSkipped) if (context.IsRequestSkipped)
{ {
return false; return false;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -96,7 +96,7 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle
return true; return true;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
return false; return false;
} }
@ -131,7 +131,7 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle
return AuthenticateResult.NoResult(); return AuthenticateResult.NoResult();
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
// Note: the missing_token error is special-cased to indicate to ASP.NET Core // Note: the missing_token error is special-cased to indicate to ASP.NET Core
// that no authentication result could be produced due to the lack of token. // that no authentication result could be produced due to the lack of token.
@ -226,7 +226,7 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {

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

@ -23,7 +23,7 @@ using Properties = OpenIddict.Validation.AspNetCore.OpenIddictValidationAspNetCo
namespace OpenIddict.Validation.AspNetCore; namespace OpenIddict.Validation.AspNetCore;
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public static partial class OpenIddictValidationAspNetCoreHandlers public static class OpenIddictValidationAspNetCoreHandlers
{ {
public static ImmutableArray<OpenIddictValidationHandlerDescriptor> DefaultHandlers { get; } = public static ImmutableArray<OpenIddictValidationHandlerDescriptor> DefaultHandlers { get; } =
[ [
@ -601,7 +601,7 @@ public static partial class OpenIddictValidationAspNetCoreHandlers
builder.Append(parameter.Key); builder.Append(parameter.Key);
builder.Append('='); builder.Append('=');
builder.Append('"'); builder.Append('"');
builder.Append(parameter.Value.Replace("\"", "\\\"")); builder.Append(parameter.Value.Replace("\"", "\\\"", StringComparison.Ordinal));
builder.Append('"'); builder.Append('"');
builder.Append(','); builder.Append(',');
} }

10
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs

@ -86,12 +86,12 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
return true; return true;
} }
else if (context.IsRequestSkipped) if (context.IsRequestSkipped)
{ {
return false; return false;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
@ -108,7 +108,7 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
return true; return true;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
return false; return false;
} }
@ -143,7 +143,7 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
return null; return null;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
// Note: the missing_token error is special-cased to indicate to Katana // Note: the missing_token error is special-cased to indicate to Katana
// that no authentication result could be produced due to the lack of token. // that no authentication result could be produced due to the lack of token.
@ -234,7 +234,7 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
return; return;
} }
else if (context.IsRejected) if (context.IsRejected)
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {

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

@ -20,7 +20,7 @@ using Properties = OpenIddict.Validation.Owin.OpenIddictValidationOwinConstants.
namespace OpenIddict.Validation.Owin; namespace OpenIddict.Validation.Owin;
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public static partial class OpenIddictValidationOwinHandlers public static class OpenIddictValidationOwinHandlers
{ {
public static ImmutableArray<OpenIddictValidationHandlerDescriptor> DefaultHandlers { get; } = public static ImmutableArray<OpenIddictValidationHandlerDescriptor> DefaultHandlers { get; } =
[ [
@ -752,7 +752,7 @@ public static partial class OpenIddictValidationOwinHandlers
builder.Append(parameter.Key); builder.Append(parameter.Key);
builder.Append('='); builder.Append('=');
builder.Append('"'); builder.Append('"');
builder.Append(parameter.Value.Replace("\"", "\\\"")); builder.Append(parameter.Value.Replace("\"", "\\\"", StringComparison.Ordinal));
builder.Append('"'); builder.Append('"');
builder.Append(','); builder.Append(',');
} }

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

@ -370,7 +370,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
return ValueTask.CompletedTask; return ValueTask.CompletedTask;
static string? EscapeDataString(string? value) static string? EscapeDataString(string? value)
=> value is not null ? Uri.EscapeDataString(value).Replace("%20", "+") : null; => value is not null ? Uri.EscapeDataString(value).Replace("%20", "+", StringComparison.Ordinal) : null;
} }
} }
@ -413,7 +413,8 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(request.RequestUri, request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(request.RequestUri,
context.Transaction.Request.GetParameters().ToDictionary( context.Transaction.Request.GetParameters().ToDictionary(
static parameter => parameter.Key, static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)); static parameter => (StringValues) parameter.Value,
StringComparer.Ordinal));
} }
// For POST requests, attach the request parameters to the request form by default. // For POST requests, attach the request parameters to the request form by default.
@ -605,7 +606,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
continue; continue;
} }
else if (string.Equals(encoding, ContentEncodings.Gzip, StringComparison.OrdinalIgnoreCase)) if (string.Equals(encoding, ContentEncodings.Gzip, StringComparison.OrdinalIgnoreCase))
{ {
stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken); stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken);
stream = new GZipStream(stream, CompressionMode.Decompress); stream = new GZipStream(stream, CompressionMode.Decompress);

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

@ -410,7 +410,7 @@ public static partial class OpenIddictValidationHandlers
var scopes = context.Principal.GetClaims(Claims.Scope); var scopes = context.Principal.GetClaims(Claims.Scope);
if (scopes.Length is > 1) if (scopes.Length is > 1)
{ {
context.Principal.SetClaim(Claims.Scope, string.Join(" ", scopes)); context.Principal.SetClaim(Claims.Scope, string.Join(Separators.Space[0], scopes));
} }
return ValueTask.CompletedTask; return ValueTask.CompletedTask;

8
src/OpenIddict.Validation/OpenIddictValidationHandlers.cs

@ -602,13 +602,13 @@ public static partial class OpenIddictValidationHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
context.Reject( context.Reject(
error: notification.Error ?? Errors.InvalidRequest, error: notification.Error ?? Errors.InvalidRequest,
@ -993,13 +993,13 @@ public static partial class OpenIddictValidationHandlers
return; return;
} }
else if (notification.IsRequestSkipped) if (notification.IsRequestSkipped)
{ {
context.SkipRequest(); context.SkipRequest();
return; return;
} }
else if (notification.IsRejected) if (notification.IsRejected)
{ {
if (context.RejectAccessToken) if (context.RejectAccessToken)
{ {

2
test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs

@ -85,7 +85,7 @@ public class OpenIddictConverterTests
return converter.Read(ref reader, type, options: null!); return converter.Read(ref reader, type, options: null!);
}); });
Assert.StartsWith(SR.GetResourceString(SR.ID0176), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0176), exception.Message, StringComparison.Ordinal);
Assert.Equal("typeToConvert", exception.ParamName); Assert.Equal("typeToConvert", exception.ParamName);
} }

164
test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs

@ -46,7 +46,7 @@ public class OpenIddictExtensionsTests
}; };
// Act and assert // Act and assert
Assert.Equal(values, request.GetAcrValues()); Assert.Equal(values, request.GetAcrValues(), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -107,7 +107,7 @@ public class OpenIddictExtensionsTests
}; };
// Act and assert // Act and assert
Assert.Equal(values, request.GetPromptValues()); Assert.Equal(values, request.GetPromptValues(), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -168,7 +168,7 @@ public class OpenIddictExtensionsTests
}; };
// Act and assert // Act and assert
Assert.Equal(values, request.GetResponseTypes()); Assert.Equal(values, request.GetResponseTypes(), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -203,7 +203,7 @@ public class OpenIddictExtensionsTests
}; };
// Act and assert // Act and assert
Assert.Equal(scopes, request.GetScopes()); Assert.Equal(scopes, request.GetScopes(), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -1091,7 +1091,7 @@ public class OpenIddictExtensionsTests
claim.Properties[Properties.Destinations] = destination!; claim.Properties[Properties.Destinations] = destination!;
// Act and assert // Act and assert
Assert.Equal(destinations, claim.GetDestinations()); Assert.Equal(destinations, claim.GetDestinations(), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -1185,7 +1185,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => claim.SetDestinations(destination!)); var exception = Assert.Throws<ArgumentException>(() => claim.SetDestinations(destination!));
Assert.Equal("destinations", exception.ParamName); Assert.Equal("destinations", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0182), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0182), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -1606,7 +1606,7 @@ public class OpenIddictExtensionsTests
identity.AddClaim(new Claim(Claims.ClientId, "B56BF6CE-8D8C-4290-A0E7-A4F8EE0A9FC4")); identity.AddClaim(new Claim(Claims.ClientId, "B56BF6CE-8D8C-4290-A0E7-A4F8EE0A9FC4"));
// Act // Act
var clone = identity.Clone(claim => claim.Type == Claims.Name); var clone = identity.Clone(claim => claim.Type is Claims.Name);
clone.AddClaim(new Claim("clone_claim", "value")); clone.AddClaim(new Claim("clone_claim", "value"));
// Assert // Assert
@ -1626,7 +1626,7 @@ public class OpenIddictExtensionsTests
var principal = new ClaimsPrincipal(identity); var principal = new ClaimsPrincipal(identity);
// Act // Act
var clone = principal.Clone(claim => claim.Type == Claims.Name); var clone = principal.Clone(claim => claim.Type is Claims.Name);
((ClaimsIdentity) clone.Identity!).AddClaim(new Claim("clone_claim", "value")); ((ClaimsIdentity) clone.Identity!).AddClaim(new Claim("clone_claim", "value"));
// Assert // Assert
@ -1645,7 +1645,7 @@ public class OpenIddictExtensionsTests
identity.AddClaim(new Claim(Claims.Subject, "D8F1A010-BD46-4F8F-AD4E-05582307F8F4")); identity.AddClaim(new Claim(Claims.Subject, "D8F1A010-BD46-4F8F-AD4E-05582307F8F4"));
// Act // Act
var clone = identity.Clone(claim => claim.Type == Claims.Name); var clone = identity.Clone(claim => claim.Type is Claims.Name);
// Assert // Assert
Assert.Single(clone.Claims); Assert.Single(clone.Claims);
@ -1663,7 +1663,7 @@ public class OpenIddictExtensionsTests
var principal = new ClaimsPrincipal(identity); var principal = new ClaimsPrincipal(identity);
// Act // Act
var clone = principal.Clone(claim => claim.Type == Claims.Name); var clone = principal.Clone(claim => claim.Type is Claims.Name);
// Assert // Assert
Assert.Single(clone.Claims); Assert.Single(clone.Claims);
@ -1683,7 +1683,7 @@ public class OpenIddictExtensionsTests
identity.Actor.AddClaim(new Claim(Claims.Subject, "D8F1A010-BD46-4F8F-AD4E-05582307F8F4")); identity.Actor.AddClaim(new Claim(Claims.Subject, "D8F1A010-BD46-4F8F-AD4E-05582307F8F4"));
// Act // Act
var clone = identity.Clone(claim => claim.Type == Claims.Name); var clone = identity.Clone(claim => claim.Type is Claims.Name);
// Assert // Assert
Assert.Single(clone.Actor!.Claims); Assert.Single(clone.Actor!.Claims);
@ -1704,7 +1704,7 @@ public class OpenIddictExtensionsTests
var principal = new ClaimsPrincipal(identity); var principal = new ClaimsPrincipal(identity);
// Act // Act
var clone = principal.Clone(claim => claim.Type == Claims.Name); var clone = principal.Clone(claim => claim.Type is Claims.Name);
// Assert // Assert
Assert.Single(((ClaimsIdentity) clone.Identity!).Actor!.Claims); Assert.Single(((ClaimsIdentity) clone.Identity!).Actor!.Claims);
@ -1746,7 +1746,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, "Bob le Bricoleur")); var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, "Bob le Bricoleur"));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -1837,7 +1837,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, true)); var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, true));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -1928,7 +1928,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, 42L)); var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, 42L));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -1992,7 +1992,7 @@ public class OpenIddictExtensionsTests
var identity = (ClaimsIdentity) null!; var identity = (ClaimsIdentity) null!;
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => identity.AddClaim(Claims.Name, new Dictionary<string, string?>())); var exception = Assert.Throws<ArgumentNullException>(() => identity.AddClaim(Claims.Name, new Dictionary<string, string?>(StringComparer.Ordinal)));
Assert.Equal("identity", exception.ParamName); Assert.Equal("identity", exception.ParamName);
} }
@ -2004,7 +2004,7 @@ public class OpenIddictExtensionsTests
var principal = (ClaimsPrincipal) null!; var principal = (ClaimsPrincipal) null!;
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.AddClaim(Claims.Name, new Dictionary<string, string?>())); var exception = Assert.Throws<ArgumentNullException>(() => principal.AddClaim(Claims.Name, new Dictionary<string, string?>(StringComparer.Ordinal)));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
} }
@ -2016,10 +2016,10 @@ public class OpenIddictExtensionsTests
var principal = new ClaimsPrincipal(); var principal = new ClaimsPrincipal();
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, new Dictionary<string, string?>())); var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, new Dictionary<string, string?>(StringComparer.Ordinal)));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -2031,7 +2031,7 @@ public class OpenIddictExtensionsTests
var identity = new ClaimsIdentity(); var identity = new ClaimsIdentity();
// Act and assert // Act and assert
var exception = Assert.ThrowsAny<ArgumentException>(() => identity.AddClaim(type!, new Dictionary<string, string?>())); var exception = Assert.ThrowsAny<ArgumentException>(() => identity.AddClaim(type!, new Dictionary<string, string?>(StringComparer.Ordinal)));
Assert.Equal("type", exception.ParamName); Assert.Equal("type", exception.ParamName);
} }
@ -2045,7 +2045,7 @@ public class OpenIddictExtensionsTests
var principal = new ClaimsPrincipal(new ClaimsIdentity()); var principal = new ClaimsPrincipal(new ClaimsIdentity());
// Act and assert // Act and assert
var exception = Assert.ThrowsAny<ArgumentException>(() => principal.AddClaim(type!, new Dictionary<string, string?>())); var exception = Assert.ThrowsAny<ArgumentException>(() => principal.AddClaim(type!, new Dictionary<string, string?>(StringComparer.Ordinal)));
Assert.Equal("type", exception.ParamName); Assert.Equal("type", exception.ParamName);
} }
@ -2057,7 +2057,7 @@ public class OpenIddictExtensionsTests
var identity = new ClaimsIdentity(); var identity = new ClaimsIdentity();
// Act // Act
identity.AddClaim("type", new Dictionary<string, string?> identity.AddClaim("type", new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
["parameter"] = "value" ["parameter"] = "value"
}); });
@ -2073,7 +2073,7 @@ public class OpenIddictExtensionsTests
var principal = new ClaimsPrincipal(new ClaimsIdentity()); var principal = new ClaimsPrincipal(new ClaimsIdentity());
// Act // Act
principal.AddClaim("type", new Dictionary<string, string?> principal.AddClaim("type", new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
["parameter"] = "value" ["parameter"] = "value"
}); });
@ -2116,7 +2116,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, default(JsonElement))); var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, default(JsonElement)));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -2158,7 +2158,7 @@ public class OpenIddictExtensionsTests
JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]"))); JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]")));
Assert.Equal("value", exception.ParamName); Assert.Equal("value", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]
@ -2172,7 +2172,7 @@ public class OpenIddictExtensionsTests
JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]"))); JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]")));
Assert.Equal("value", exception.ParamName); Assert.Equal("value", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]
@ -2235,7 +2235,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, (JsonNode) null!)); var exception = Assert.Throws<ArgumentException>(() => principal.AddClaim(Claims.Name, (JsonNode) null!));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -2301,7 +2301,7 @@ public class OpenIddictExtensionsTests
new JsonArray(["Fabrikam", "Contoso"]))); new JsonArray(["Fabrikam", "Contoso"])));
Assert.Equal("value", exception.ParamName); Assert.Equal("value", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]
@ -2315,7 +2315,7 @@ public class OpenIddictExtensionsTests
new JsonArray(["Fabrikam", "Contoso"]))); new JsonArray(["Fabrikam", "Contoso"])));
Assert.Equal("value", exception.ParamName); Assert.Equal("value", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]
@ -2378,7 +2378,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.AddClaims("type", ["value1", "value2"])); var exception = Assert.Throws<ArgumentException>(() => principal.AddClaims("type", ["value1", "value2"]));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -2459,7 +2459,7 @@ public class OpenIddictExtensionsTests
identity.AddClaims("TYPE", ["value1", "value2"]); identity.AddClaims("TYPE", ["value1", "value2"]);
// Assert // Assert
Assert.Equal<string>(["value1", "value2"], identity.GetClaims("type")); Assert.Equal<string>(["value1", "value2"], identity.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -2472,7 +2472,7 @@ public class OpenIddictExtensionsTests
principal.AddClaims("TYPE", ["value1", "value2"]); principal.AddClaims("TYPE", ["value1", "value2"]);
// Assert // Assert
Assert.Equal<string>(["value1", "value2"], principal.GetClaims("type")); Assert.Equal<string>(["value1", "value2"], principal.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -2509,7 +2509,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.AddClaims("type", default(JsonElement))); var exception = Assert.Throws<ArgumentException>(() => principal.AddClaims("type", default(JsonElement)));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -2551,7 +2551,7 @@ public class OpenIddictExtensionsTests
JsonSerializer.Deserialize<JsonElement>(@"{""parameter"":""value""}"))); JsonSerializer.Deserialize<JsonElement>(@"{""parameter"":""value""}")));
Assert.Equal("value", exception.ParamName); Assert.Equal("value", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]
@ -2565,7 +2565,7 @@ public class OpenIddictExtensionsTests
JsonSerializer.Deserialize<JsonElement>(@"{""parameter"":""value""}"))); JsonSerializer.Deserialize<JsonElement>(@"{""parameter"":""value""}")));
Assert.Equal("value", exception.ParamName); Assert.Equal("value", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0185), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]
@ -2629,7 +2629,7 @@ public class OpenIddictExtensionsTests
identity.AddClaims("TYPE", JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]")); identity.AddClaims("TYPE", JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]"));
// Assert // Assert
Assert.Equal<string>(["Fabrikam", "Contoso"], identity.GetClaims("type")); Assert.Equal<string>(["Fabrikam", "Contoso"], identity.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -2642,7 +2642,7 @@ public class OpenIddictExtensionsTests
principal.AddClaims("TYPE", JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]")); principal.AddClaims("TYPE", JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]"));
// Assert // Assert
Assert.Equal<string>(["Fabrikam", "Contoso"], principal.GetClaims("type")); Assert.Equal<string>(["Fabrikam", "Contoso"], principal.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -2679,7 +2679,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.AddClaims("type", (JsonArray) null!)); var exception = Assert.Throws<ArgumentException>(() => principal.AddClaims("type", (JsonArray) null!));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -2795,7 +2795,7 @@ public class OpenIddictExtensionsTests
identity.AddClaims("TYPE", new JsonArray(["Fabrikam", "Contoso"])); identity.AddClaims("TYPE", new JsonArray(["Fabrikam", "Contoso"]));
// Assert // Assert
Assert.Equal<string>(["Fabrikam", "Contoso"], identity.GetClaims("type")); Assert.Equal<string>(["Fabrikam", "Contoso"], identity.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -2808,7 +2808,7 @@ public class OpenIddictExtensionsTests
principal.AddClaims("TYPE", new JsonArray(["Fabrikam", "Contoso"])); principal.AddClaims("TYPE", new JsonArray(["Fabrikam", "Contoso"]));
// Assert // Assert
Assert.Equal<string>(["Fabrikam", "Contoso"], principal.GetClaims("type")); Assert.Equal<string>(["Fabrikam", "Contoso"], principal.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -3255,7 +3255,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim("type", "value")); var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim("type", "value"));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -3408,7 +3408,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim("type", true)); var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim("type", true));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -3561,7 +3561,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim("type", 42L)); var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim("type", 42L));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -3687,7 +3687,7 @@ public class OpenIddictExtensionsTests
var identity = (ClaimsIdentity) null!; var identity = (ClaimsIdentity) null!;
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => identity.SetClaim("type", new Dictionary<string, string?>())); var exception = Assert.Throws<ArgumentNullException>(() => identity.SetClaim("type", new Dictionary<string, string?>(StringComparer.Ordinal)));
Assert.Equal("identity", exception.ParamName); Assert.Equal("identity", exception.ParamName);
} }
@ -3699,7 +3699,7 @@ public class OpenIddictExtensionsTests
var principal = (ClaimsPrincipal) null!; var principal = (ClaimsPrincipal) null!;
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.SetClaim("type", new Dictionary<string, string?>())); var exception = Assert.Throws<ArgumentNullException>(() => principal.SetClaim("type", new Dictionary<string, string?>(StringComparer.Ordinal)));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
} }
@ -3711,13 +3711,13 @@ public class OpenIddictExtensionsTests
var principal = new ClaimsPrincipal(); var principal = new ClaimsPrincipal();
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim("type", new Dictionary<string, string?> var exception = Assert.Throws<ArgumentException>(() => principal.SetClaim("type", new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
["parameter"] = "value" ["parameter"] = "value"
})); }));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -3729,7 +3729,7 @@ public class OpenIddictExtensionsTests
var identity = new ClaimsIdentity(); var identity = new ClaimsIdentity();
// Act and assert // Act and assert
var exception = Assert.ThrowsAny<ArgumentException>(() => identity.SetClaim(type!, new Dictionary<string, string?>())); var exception = Assert.ThrowsAny<ArgumentException>(() => identity.SetClaim(type!, new Dictionary<string, string?>(StringComparer.Ordinal)));
Assert.Equal("type", exception.ParamName); Assert.Equal("type", exception.ParamName);
} }
@ -3743,7 +3743,7 @@ public class OpenIddictExtensionsTests
var principal = new ClaimsPrincipal(new ClaimsIdentity()); var principal = new ClaimsPrincipal(new ClaimsIdentity());
// Act and assert // Act and assert
var exception = Assert.ThrowsAny<ArgumentException>(() => principal.SetClaim(type!, new Dictionary<string, string?>())); var exception = Assert.ThrowsAny<ArgumentException>(() => principal.SetClaim(type!, new Dictionary<string, string?>(StringComparer.Ordinal)));
Assert.Equal("type", exception.ParamName); Assert.Equal("type", exception.ParamName);
} }
@ -3756,7 +3756,7 @@ public class OpenIddictExtensionsTests
identity.AddClaim("type", "value1"); identity.AddClaim("type", "value1");
// Act // Act
identity.SetClaim("type", new Dictionary<string, string?> identity.SetClaim("type", new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
["parameter"] = "value" ["parameter"] = "value"
}, "issuer"); }, "issuer");
@ -3776,7 +3776,7 @@ public class OpenIddictExtensionsTests
principal.AddClaim("type", "value1"); principal.AddClaim("type", "value1");
// Act // Act
principal.SetClaim("type", new Dictionary<string, string?> principal.SetClaim("type", new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
["parameter"] = "value" ["parameter"] = "value"
}, "issuer"); }, "issuer");
@ -3795,7 +3795,7 @@ public class OpenIddictExtensionsTests
var identity = new ClaimsIdentity(); var identity = new ClaimsIdentity();
// Act // Act
identity.SetClaim("TYPE", new Dictionary<string, string?> identity.SetClaim("TYPE", new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
["parameter"] = "value" ["parameter"] = "value"
}); });
@ -3811,7 +3811,7 @@ public class OpenIddictExtensionsTests
var principal = new ClaimsPrincipal(new ClaimsIdentity()); var principal = new ClaimsPrincipal(new ClaimsIdentity());
// Act // Act
principal.SetClaim("TYPE", new Dictionary<string, string?> principal.SetClaim("TYPE", new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
["parameter"] = "value" ["parameter"] = "value"
}); });
@ -3828,7 +3828,7 @@ public class OpenIddictExtensionsTests
identity.AddClaim("type", "value"); identity.AddClaim("type", "value");
// Act // Act
identity.SetClaim("type", new Dictionary<string, string?>()); identity.SetClaim("type", new Dictionary<string, string?>(StringComparer.Ordinal));
// Assert // Assert
Assert.Null(identity.GetClaim("type")); Assert.Null(identity.GetClaim("type"));
@ -3842,7 +3842,7 @@ public class OpenIddictExtensionsTests
principal.AddClaim("type", "value"); principal.AddClaim("type", "value");
// Act // Act
principal.SetClaim("type", new Dictionary<string, string?>()); principal.SetClaim("type", new Dictionary<string, string?>(StringComparer.Ordinal));
// Assert // Assert
Assert.Null(principal.GetClaim("type")); Assert.Null(principal.GetClaim("type"));
@ -3883,7 +3883,7 @@ public class OpenIddictExtensionsTests
JsonSerializer.Deserialize<JsonElement>(@"{""parameter"":""value""}"))); JsonSerializer.Deserialize<JsonElement>(@"{""parameter"":""value""}")));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -4091,7 +4091,7 @@ public class OpenIddictExtensionsTests
new JsonObject { ["parameter"] = "value" })); new JsonObject { ["parameter"] = "value" }));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -4298,7 +4298,7 @@ public class OpenIddictExtensionsTests
var exception = Assert.Throws<ArgumentException>(() => principal.SetClaims("type", ["value1", "value2"])); var exception = Assert.Throws<ArgumentException>(() => principal.SetClaims("type", ["value1", "value2"]));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -4378,7 +4378,7 @@ public class OpenIddictExtensionsTests
identity.SetClaims("TYPE", ["value1", "value2"]); identity.SetClaims("TYPE", ["value1", "value2"]);
// Assert // Assert
Assert.Equal<string>(["value1", "value2"], identity.GetClaims("type")); Assert.Equal<string>(["value1", "value2"], identity.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -4391,7 +4391,7 @@ public class OpenIddictExtensionsTests
principal.SetClaims("TYPE", ["value1", "value2"]); principal.SetClaims("TYPE", ["value1", "value2"]);
// Assert // Assert
Assert.Equal<string>(["value1", "value2"], principal.GetClaims("type")); Assert.Equal<string>(["value1", "value2"], principal.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -4457,7 +4457,7 @@ public class OpenIddictExtensionsTests
JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]"))); JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]")));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -4537,7 +4537,7 @@ public class OpenIddictExtensionsTests
identity.SetClaims("TYPE", JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]")); identity.SetClaims("TYPE", JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]"));
// Assert // Assert
Assert.Equal<string>(["Fabrikam", "Contoso"], identity.GetClaims("type")); Assert.Equal<string>(["Fabrikam", "Contoso"], identity.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -4550,7 +4550,7 @@ public class OpenIddictExtensionsTests
principal.SetClaims("TYPE", JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]")); principal.SetClaims("TYPE", JsonSerializer.Deserialize<JsonElement>(@"[""Fabrikam"",""Contoso""]"));
// Assert // Assert
Assert.Equal<string>(["Fabrikam", "Contoso"], principal.GetClaims("type")); Assert.Equal<string>(["Fabrikam", "Contoso"], principal.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -4670,7 +4670,7 @@ public class OpenIddictExtensionsTests
new JsonArray("Fabrikam", "Contoso"))); new JsonArray("Fabrikam", "Contoso")));
Assert.Equal("principal", exception.ParamName); Assert.Equal("principal", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0286), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -4774,7 +4774,7 @@ public class OpenIddictExtensionsTests
identity.SetClaims("TYPE", new JsonArray("Fabrikam", "Contoso")); identity.SetClaims("TYPE", new JsonArray("Fabrikam", "Contoso"));
// Assert // Assert
Assert.Equal<string>(["Fabrikam", "Contoso"], identity.GetClaims("type")); Assert.Equal<string>(["Fabrikam", "Contoso"], identity.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -4787,7 +4787,7 @@ public class OpenIddictExtensionsTests
principal.SetClaims("TYPE", new JsonArray("Fabrikam", "Contoso")); principal.SetClaims("TYPE", new JsonArray("Fabrikam", "Contoso"));
// Assert // Assert
Assert.Equal<string>(["Fabrikam", "Contoso"], principal.GetClaims("type")); Assert.Equal<string>(["Fabrikam", "Contoso"], principal.GetClaims("type"), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -4999,7 +4999,7 @@ public class OpenIddictExtensionsTests
identity.SetClaims(Claims.Private.Audience, audience.ToImmutableArray()); identity.SetClaims(Claims.Private.Audience, audience.ToImmutableArray());
// Act and assert // Act and assert
Assert.Equal(audiences, identity.GetAudiences()); Assert.Equal(audiences, identity.GetAudiences(), StringComparer.Ordinal);
} }
[Theory] [Theory]
@ -5015,7 +5015,7 @@ public class OpenIddictExtensionsTests
principal.SetClaims(Claims.Private.Audience, audience.ToImmutableArray()); principal.SetClaims(Claims.Private.Audience, audience.ToImmutableArray());
// Act and assert // Act and assert
Assert.Equal(audiences, principal.GetAudiences()); Assert.Equal(audiences, principal.GetAudiences(), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -5055,7 +5055,7 @@ public class OpenIddictExtensionsTests
identity.SetClaims(Claims.Private.Presenter, presenter.ToImmutableArray()); identity.SetClaims(Claims.Private.Presenter, presenter.ToImmutableArray());
// Act and assert // Act and assert
Assert.Equal(presenters, identity.GetPresenters()); Assert.Equal(presenters, identity.GetPresenters(), StringComparer.Ordinal);
} }
[Theory] [Theory]
@ -5071,7 +5071,7 @@ public class OpenIddictExtensionsTests
principal.SetClaims(Claims.Private.Presenter, presenter.ToImmutableArray()); principal.SetClaims(Claims.Private.Presenter, presenter.ToImmutableArray());
// Act and assert // Act and assert
Assert.Equal(presenters, principal.GetPresenters()); Assert.Equal(presenters, principal.GetPresenters(), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -5111,7 +5111,7 @@ public class OpenIddictExtensionsTests
identity.SetClaims(Claims.Private.Resource, resource.ToImmutableArray()); identity.SetClaims(Claims.Private.Resource, resource.ToImmutableArray());
// Act and assert // Act and assert
Assert.Equal(resources, identity.GetResources()); Assert.Equal(resources, identity.GetResources(), StringComparer.Ordinal);
} }
[Theory] [Theory]
@ -5127,7 +5127,7 @@ public class OpenIddictExtensionsTests
principal.SetClaims(Claims.Private.Resource, resource.ToImmutableArray()); principal.SetClaims(Claims.Private.Resource, resource.ToImmutableArray());
// Act and assert // Act and assert
Assert.Equal(resources, principal.GetResources()); Assert.Equal(resources, principal.GetResources(), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -5167,7 +5167,7 @@ public class OpenIddictExtensionsTests
identity.SetClaims(Claims.Private.Scope, scope.ToImmutableArray()); identity.SetClaims(Claims.Private.Scope, scope.ToImmutableArray());
// Act and assert // Act and assert
Assert.Equal(scopes, identity.GetScopes()); Assert.Equal(scopes, identity.GetScopes(), StringComparer.Ordinal);
} }
[Theory] [Theory]
@ -5183,7 +5183,7 @@ public class OpenIddictExtensionsTests
principal.SetClaims(Claims.Private.Scope, scope.ToImmutableArray()); principal.SetClaims(Claims.Private.Scope, scope.ToImmutableArray());
// Act and assert // Act and assert
Assert.Equal(scopes, principal.GetScopes()); Assert.Equal(scopes, principal.GetScopes(), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -6430,7 +6430,7 @@ public class OpenIddictExtensionsTests
identity.SetAudiences(audiences); identity.SetAudiences(audiences);
// Assert // Assert
Assert.Equal(audience, identity.GetClaims(Claims.Private.Audience)); Assert.Equal(audience, identity.GetClaims(Claims.Private.Audience), StringComparer.Ordinal);
} }
[Theory] [Theory]
@ -6449,7 +6449,7 @@ public class OpenIddictExtensionsTests
principal.SetAudiences(audiences); principal.SetAudiences(audiences);
// Assert // Assert
Assert.Equal(audience, principal.GetClaims(Claims.Private.Audience)); Assert.Equal(audience, principal.GetClaims(Claims.Private.Audience), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -6492,7 +6492,7 @@ public class OpenIddictExtensionsTests
identity.SetPresenters(presenters); identity.SetPresenters(presenters);
// Assert // Assert
Assert.Equal(presenter, identity.GetClaims(Claims.Private.Presenter)); Assert.Equal(presenter, identity.GetClaims(Claims.Private.Presenter), StringComparer.Ordinal);
} }
[Theory] [Theory]
@ -6511,7 +6511,7 @@ public class OpenIddictExtensionsTests
principal.SetPresenters(presenters); principal.SetPresenters(presenters);
// Assert // Assert
Assert.Equal(presenter, principal.GetClaims(Claims.Private.Presenter)); Assert.Equal(presenter, principal.GetClaims(Claims.Private.Presenter), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -6554,7 +6554,7 @@ public class OpenIddictExtensionsTests
identity.SetResources(resources); identity.SetResources(resources);
// Assert // Assert
Assert.Equal(resource, identity.GetClaims(Claims.Private.Resource)); Assert.Equal(resource, identity.GetClaims(Claims.Private.Resource), StringComparer.Ordinal);
} }
[Theory] [Theory]
@ -6573,7 +6573,7 @@ public class OpenIddictExtensionsTests
principal.SetResources(resources); principal.SetResources(resources);
// Assert // Assert
Assert.Equal(resource, principal.GetClaims(Claims.Private.Resource)); Assert.Equal(resource, principal.GetClaims(Claims.Private.Resource), StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -6616,7 +6616,7 @@ public class OpenIddictExtensionsTests
identity.SetScopes(scopes); identity.SetScopes(scopes);
// Assert // Assert
Assert.Equal(scope, identity.GetClaims(Claims.Private.Scope)); Assert.Equal(scope, identity.GetClaims(Claims.Private.Scope), StringComparer.Ordinal);
} }
[Theory] [Theory]
@ -6635,7 +6635,7 @@ public class OpenIddictExtensionsTests
principal.SetScopes(scopes); principal.SetScopes(scopes);
// Assert // Assert
Assert.Equal(scope, principal.GetClaims(Claims.Private.Scope)); Assert.Equal(scope, principal.GetClaims(Claims.Private.Scope), StringComparer.Ordinal);
} }
[Fact] [Fact]

8
test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs

@ -25,7 +25,7 @@ public class OpenIddictMessageTests
}); });
Assert.Equal("parameters", exception.ParamName); Assert.Equal("parameters", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0189), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0189), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]
@ -42,7 +42,7 @@ public class OpenIddictMessageTests
}); });
Assert.Equal("parameters", exception.ParamName); Assert.Equal("parameters", exception.ParamName);
Assert.StartsWith(SR.GetResourceString(SR.ID0191), exception.Message); Assert.StartsWith(SR.GetResourceString(SR.ID0191), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]
@ -253,7 +253,7 @@ public class OpenIddictMessageTests
public void GetParameters_EnumeratesParameters() public void GetParameters_EnumeratesParameters()
{ {
// Arrange // Arrange
var parameters = new Dictionary<string, OpenIddictParameter> var parameters = new Dictionary<string, OpenIddictParameter>(StringComparer.Ordinal)
{ {
["int"] = int.MaxValue, ["int"] = int.MaxValue,
["long"] = long.MaxValue, ["long"] = long.MaxValue,
@ -483,7 +483,7 @@ public class OpenIddictMessageTests
// Act and assert // Act and assert
var element = JsonSerializer.Deserialize<JsonElement>(message.ToString()); var element = JsonSerializer.Deserialize<JsonElement>(message.ToString());
Assert.DoesNotContain("secret value", message.ToString()); Assert.DoesNotContain("secret value", message.ToString(), StringComparison.Ordinal);
Assert.Equal("[redacted]", element.GetProperty(parameter).GetString()); Assert.Equal("[redacted]", element.GetProperty(parameter).GetString());
} }

22
test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs

@ -316,12 +316,12 @@ public class OpenIddictParameterTests
["field"] = new JsonArray(0, 1, 2) ["field"] = new JsonArray(0, 1, 2)
}))); })));
Assert.True(parameter.Equals(new OpenIddictParameter(JsonValue.Create(new Dictionary<string, object> Assert.True(parameter.Equals(new OpenIddictParameter(JsonValue.Create(new Dictionary<string, object>(StringComparer.Ordinal)
{ {
["field"] = new JsonArray(0, 1, 2, 3) ["field"] = new JsonArray(0, 1, 2, 3)
})))); }))));
Assert.True(parameter.Equals(new OpenIddictParameter(JsonValue.Create(new Dictionary<string, object> Assert.True(parameter.Equals(new OpenIddictParameter(JsonValue.Create(new Dictionary<string, object>(StringComparer.Ordinal)
{ {
["field"] = new[] { 0, 1, 2, 3 } ["field"] = new[] { 0, 1, 2, 3 }
})))); }))));
@ -445,12 +445,12 @@ public class OpenIddictParameterTests
Assert.Equal(1, new OpenIddictParameter(true).GetHashCode()); Assert.Equal(1, new OpenIddictParameter(true).GetHashCode());
Assert.Equal(0, new OpenIddictParameter(false).GetHashCode()); Assert.Equal(0, new OpenIddictParameter(false).GetHashCode());
Assert.Equal(42.GetHashCode(), new OpenIddictParameter(42).GetHashCode()); Assert.Equal(42.GetHashCode(), new OpenIddictParameter(42).GetHashCode());
Assert.Equal("Fabrikam".GetHashCode(), new OpenIddictParameter("Fabrikam").GetHashCode()); Assert.Equal("Fabrikam".GetHashCode(StringComparison.Ordinal), new OpenIddictParameter("Fabrikam").GetHashCode());
Assert.NotEqual(1, new OpenIddictParameter("true").GetHashCode()); Assert.NotEqual(1, new OpenIddictParameter("true").GetHashCode());
Assert.NotEqual(0, new OpenIddictParameter("false").GetHashCode()); Assert.NotEqual(0, new OpenIddictParameter("false").GetHashCode());
Assert.NotEqual(42.GetHashCode(), new OpenIddictParameter("42").GetHashCode()); Assert.NotEqual(42.GetHashCode(), new OpenIddictParameter("42").GetHashCode());
Assert.NotEqual("Fabrikam".GetHashCode(), new OpenIddictParameter(42).GetHashCode()); Assert.NotEqual("Fabrikam".GetHashCode(StringComparison.Ordinal), new OpenIddictParameter(42).GetHashCode());
} }
[Fact] [Fact]
@ -851,7 +851,7 @@ public class OpenIddictParameterTests
public void GetNamedParameters_ReturnsExpectedParametersForJsonObjectElements() public void GetNamedParameters_ReturnsExpectedParametersForJsonObjectElements()
{ {
// Arrange // Arrange
var parameters = new Dictionary<string, string?> var parameters = new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
["parameter"] = "value" ["parameter"] = "value"
}; };
@ -860,14 +860,14 @@ public class OpenIddictParameterTests
JsonSerializer.Deserialize<JsonElement>(@"{""parameter"":""value""}")); JsonSerializer.Deserialize<JsonElement>(@"{""parameter"":""value""}"));
// Act and assert // Act and assert
Assert.Equal(parameters, parameter.GetNamedParameters().ToDictionary(pair => pair.Key, pair => (string?) pair.Value)); Assert.Equal(parameters, parameter.GetNamedParameters().ToDictionary(pair => pair.Key, pair => (string?) pair.Value, StringComparer.Ordinal));
} }
[Fact] [Fact]
public void GetNamedParameters_ReturnsExpectedParametersForJsonObjectNodes() public void GetNamedParameters_ReturnsExpectedParametersForJsonObjectNodes()
{ {
// Arrange // Arrange
var parameters = new Dictionary<string, string?> var parameters = new Dictionary<string, string?>(StringComparer.Ordinal)
{ {
["parameter"] = "value" ["parameter"] = "value"
}; };
@ -878,7 +878,7 @@ public class OpenIddictParameterTests
}); });
// Act and assert // Act and assert
Assert.Equal(parameters, parameter.GetNamedParameters().ToDictionary(pair => pair.Key, pair => (string?) pair.Value)); Assert.Equal(parameters, parameter.GetNamedParameters().ToDictionary(pair => pair.Key, pair => (string?) pair.Value, StringComparer.Ordinal));
} }
[Fact] [Fact]
@ -926,7 +926,7 @@ public class OpenIddictParameterTests
// Act and assert // Act and assert
Assert.Equal(parameters, from element in parameter.GetUnnamedParameters() Assert.Equal(parameters, from element in parameter.GetUnnamedParameters()
select (string?) element); select (string?) element, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -965,7 +965,7 @@ public class OpenIddictParameterTests
// Act and assert // Act and assert
Assert.Equal(parameters, from element in parameter.GetUnnamedParameters() Assert.Equal(parameters, from element in parameter.GetUnnamedParameters()
select (string?) element); select (string?) element, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -982,7 +982,7 @@ public class OpenIddictParameterTests
// Act and assert // Act and assert
Assert.Equal(parameters, from element in parameter.GetUnnamedParameters() Assert.Equal(parameters, from element in parameter.GetUnnamedParameters()
select (string?) element); select (string?) element, StringComparer.Ordinal);
} }
[Fact] [Fact]

8
test/OpenIddict.Client.Tests/OpenIddictClientBuilderTests.cs

@ -1196,7 +1196,7 @@ public class OpenIddictClientBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetPostLogoutRedirectionEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetPostLogoutRedirectionEndpointUris(new Uri(uri)));
Assert.Equal("uris", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -1210,7 +1210,7 @@ public class OpenIddictClientBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetPostLogoutRedirectionEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetPostLogoutRedirectionEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("uris", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]
@ -1280,7 +1280,7 @@ public class OpenIddictClientBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetRedirectionEndpointUris(new Uri(uri))); var exception = Assert.Throws<ArgumentException>(() => builder.SetRedirectionEndpointUris(new Uri(uri)));
Assert.Equal("uris", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message); Assert.Contains(SR.GetResourceString(SR.ID0072), exception.Message, StringComparison.Ordinal);
} }
[Theory] [Theory]
@ -1294,7 +1294,7 @@ public class OpenIddictClientBuilderTests
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentException>(() => builder.SetRedirectionEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute))); var exception = Assert.Throws<ArgumentException>(() => builder.SetRedirectionEndpointUris(new Uri(uri, UriKind.RelativeOrAbsolute)));
Assert.Equal("uris", exception.ParamName); Assert.Equal("uris", exception.ParamName);
Assert.Contains(SR.FormatID0081("~"), exception.Message); Assert.Contains(SR.FormatID0081("~"), exception.Message, StringComparison.Ordinal);
} }
[Fact] [Fact]

30
test/OpenIddict.Client.Tests/OpenIddictClientConfigurationTests.cs

@ -175,7 +175,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0075), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0075), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -196,7 +196,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0455), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0455), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -216,7 +216,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0521), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0521), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -237,7 +237,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0136), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0136), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -258,7 +258,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0137), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0137), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -280,7 +280,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0395), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0395), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -300,7 +300,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0522), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0522), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -321,7 +321,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0313), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0313), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -335,7 +335,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0076), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0076), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -353,7 +353,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0285), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0285), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -368,7 +368,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0356), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0356), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -384,8 +384,8 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0357), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0357), result.Failures!, StringComparer.Ordinal);
Assert.Contains(SR.GetResourceString(SR.ID0358), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0358), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -400,7 +400,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.FormatID0281(ResponseTypes.Code), result.Failures!); Assert.Contains(SR.FormatID0281(ResponseTypes.Code), result.Failures!, StringComparer.Ordinal);
} }
[Fact] [Fact]
@ -451,7 +451,7 @@ public class OpenIddictClientConfigurationTests
var result = configuration.Validate(name: null, options); var result = configuration.Validate(name: null, options);
// Assert // Assert
Assert.Contains(SR.GetResourceString(SR.ID0347), result.Failures!); Assert.Contains(SR.GetResourceString(SR.ID0347), result.Failures!, StringComparer.Ordinal);
} }
private static OpenIddictClientOptions CreateBaseOptions() private static OpenIddictClientOptions CreateBaseOptions()

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save