diff --git a/.editorconfig b/.editorconfig
index b78ba8ada..e02201537 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -95,10 +95,22 @@ csharp_using_directive_placement = outside_namespace
[*.{cs,vb}]
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.IDE0002.severity = none
+dotnet_diagnostic.IDE0042.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.style = begins_with_i
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
diff --git a/Directory.Packages.props b/Directory.Packages.props
index c0b25826e..02431b72d 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,17 +4,14 @@
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,
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
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).
-->
-
+
diff --git a/gen/OpenIddict.Client.WebIntegration.Generators/OpenIddictClientWebIntegrationGenerator.cs b/gen/OpenIddict.Client.WebIntegration.Generators/OpenIddictClientWebIntegrationGenerator.cs
index 379f1d6d7..757d3fd66 100644
--- a/gen/OpenIddict.Client.WebIntegration.Generators/OpenIddictClientWebIntegrationGenerator.cs
+++ b/gen/OpenIddict.Client.WebIntegration.Generators/OpenIddictClientWebIntegrationGenerator.cs
@@ -897,7 +897,7 @@ public static class ProviderTypes
Name = (string) constant.Attribute("Name"),
Value = (string) constant.Attribute("Value")
})
- .GroupBy(static constant => constant.Class)
+ .GroupBy(static constant => constant.Class, StringComparer.Ordinal)
.ToList(),
})
.ToList()
@@ -1600,7 +1600,7 @@ public sealed class {{ provider.name }}
static TemplateContext CreateTemplateContext(object model)
{
- var context = new TemplateContext
+ var context = new TemplateContext(StringComparer.OrdinalIgnoreCase)
{
LimitToString = 128 * 1024 * 1024,
LoopLimit = 100_000
diff --git a/sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/AuthenticationController.cs b/sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/AuthenticationController.cs
index 01b3f3f6e..ba3ef7db2 100644
--- a/sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/AuthenticationController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/AuthenticationController.cs
@@ -31,7 +31,7 @@ public async Task LogIn(string provider, string returnUrl)
// the user is directly redirected to GitHub (in this case, no login page is shown).
if (string.Equals(provider, "Local+GitHub", StringComparison.Ordinal))
{
- var properties = new AuthenticationProperties(new Dictionary
+ var properties = new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
// Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required.
@@ -61,7 +61,7 @@ public async Task LogIn(string provider, string returnUrl)
return new HttpStatusCodeResult(400);
}
- var properties = new AuthenticationProperties(new Dictionary
+ var properties = new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
// Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required.
@@ -100,7 +100,7 @@ public async Task LogOut(string returnUrl)
if (identity.FindFirst(Claims.Private.RegistrationId)?.Value is string identifier &&
await _service.GetServerConfigurationByRegistrationIdAsync(identifier) is { EndSessionEndpoint: Uri })
{
- var properties = new AuthenticationProperties(new Dictionary
+ var properties = new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictClientOwinConstants.Properties.RegistrationId] = identifier,
@@ -195,7 +195,7 @@ or Claims.Private.RegistrationId or Claims.Private.ProviderName
OpenIddictClientOwinConstants.Tokens.BackchannelAccessToken or
OpenIddictClientOwinConstants.Tokens.BackchannelIdentityToken or
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
// of the resulting authentication cookie from the lifetime of the identity token returned by
diff --git a/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthenticationController.cs b/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthenticationController.cs
index c512e6744..10503cf5b 100644
--- a/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthenticationController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthenticationController.cs
@@ -86,7 +86,7 @@ or Claims.Private.RegistrationId or Claims.Private.ProviderName
// If needed, the tokens returned by the authorization server can be stored in the authentication cookie.
OpenIddictClientOwinConstants.Tokens.BackchannelAccessToken or
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
// of the resulting authentication cookie from the lifetime of the identity token returned by
diff --git a/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthorizationController.cs b/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthorizationController.cs
index 7f31fdcfc..20be17f6e 100644
--- a/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthorizationController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/AuthorizationController.cs
@@ -92,7 +92,7 @@ public async Task Authorize()
{
context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidRequest,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@@ -102,7 +102,7 @@ public async Task Authorize()
return new EmptyResult();
}
- var properties = new AuthenticationProperties(new Dictionary
+ var properties = new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
// Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required.
@@ -154,7 +154,7 @@ public async Task Authorize()
case ConsentTypes.External when authorizations.Count is 0:
context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@@ -231,7 +231,7 @@ public async Task Authorize()
case ConsentTypes.Systematic when request.HasPromptValue(PromptValues.None):
context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@@ -277,7 +277,7 @@ public async Task Accept()
{
context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerOwinConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@@ -307,7 +307,7 @@ public async Task Accept()
{
context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] =
@@ -425,7 +425,7 @@ public async Task Exchange()
{
context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The token is no longer valid."
@@ -439,7 +439,7 @@ public async Task Exchange()
{
context.Authentication.Challenge(
authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."
diff --git a/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ManageController.cs b/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ManageController.cs
index d375429b6..e442c27dc 100644
--- a/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ManageController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ManageController.cs
@@ -289,7 +289,7 @@ public async Task ManageLogins(ManageMessageId? message)
return View("Error");
}
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;
return View(new ManageLoginsViewModel
{
diff --git a/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ResourceController.cs b/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ResourceController.cs
index 98968c5bd..7e551af19 100644
--- a/sandbox/OpenIddict.Sandbox.AspNet.Server/Controllers/ResourceController.cs
+++ b/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.Http;
using System.Security.Claims;
@@ -27,7 +28,7 @@ public async Task GetMessage()
{
context.Authentication.Challenge(
authenticationTypes: OpenIddictValidationOwinDefaults.AuthenticationType,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictValidationOwinConstants.Properties.Scope] = "demo_api",
[OpenIddictValidationOwinConstants.Properties.Error] = Errors.InsufficientScope,
@@ -43,7 +44,7 @@ public async Task GetMessage()
{
context.Authentication.Challenge(
authenticationTypes: OpenIddictValidationOwinDefaults.AuthenticationType,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictValidationOwinConstants.Properties.Error] = Errors.InvalidToken,
[OpenIddictValidationOwinConstants.Properties.ErrorDescription] =
diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/AuthenticationController.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/AuthenticationController.cs
index 91491bb54..e8b965062 100644
--- a/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/AuthenticationController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/AuthenticationController.cs
@@ -24,7 +24,7 @@ public async Task LogIn(string provider, string returnUrl)
// the user is directly redirected to GitHub (in this case, no login page is shown).
if (string.Equals(provider, "Local+GitHub", StringComparison.Ordinal))
{
- var properties = new AuthenticationProperties(new Dictionary
+ var properties = new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
// Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required.
@@ -54,7 +54,7 @@ public async Task LogIn(string provider, string returnUrl)
return BadRequest();
}
- var properties = new AuthenticationProperties(new Dictionary
+ var properties = new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
// Note: when only one client is registered in the client options,
// specifying the issuer URI or the provider name is not required.
@@ -96,7 +96,7 @@ public async Task LogOut(string returnUrl)
if (identity.FindFirst(Claims.Private.RegistrationId)?.Value is string identifier &&
await _service.GetServerConfigurationByRegistrationIdAsync(identifier) is { EndSessionEndpoint: Uri })
{
- var properties = new AuthenticationProperties(new Dictionary
+ var properties = new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictClientAspNetCoreConstants.Properties.RegistrationId] = identifier,
diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AccountController.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AccountController.cs
index 18f10aecf..a4f91562c 100644
--- a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AccountController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AccountController.cs
@@ -71,11 +71,9 @@ public async Task Login(LoginViewModel model, string returnUrl =
{
return View("Lockout");
}
- else
- {
- ModelState.AddModelError(string.Empty, "Invalid login attempt.");
- return View(model);
- }
+
+ ModelState.AddModelError(string.Empty, "Invalid login attempt.");
+ return View(model);
}
// If we got this far, something failed, redisplay form
@@ -173,14 +171,12 @@ public async Task ExternalLoginCallback(string returnUrl = null)
{
return View("Lockout");
}
- else
- {
- // If the user does not have an account, then ask the user to create an account.
- ViewData["ReturnUrl"] = returnUrl;
- ViewData["LoginProvider"] = info.LoginProvider;
- var email = info.Principal.FindFirstValue(ClaimTypes.Email);
- return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
- }
+
+ // If the user does not have an account, then ask the user to create an account.
+ ViewData["ReturnUrl"] = returnUrl;
+ ViewData["LoginProvider"] = info.LoginProvider;
+ var email = info.Principal.FindFirstValue(ClaimTypes.Email);
+ return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
}
//
@@ -367,11 +363,11 @@ public async Task SendCode(SendCodeViewModel model)
}
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);
}
- else if (model.SelectedProvider == "Phone")
+ else if (string.Equals(model.SelectedProvider, "Phone", StringComparison.Ordinal))
{
await _smsSender.SendSmsAsync(await _userManager.GetPhoneNumberAsync(user), message);
}
@@ -418,11 +414,9 @@ public async Task VerifyCode(VerifyCodeViewModel model)
{
return View("Lockout");
}
- else
- {
- ModelState.AddModelError("", "Invalid code.");
- return View(model);
- }
+
+ ModelState.AddModelError("", "Invalid code.");
+ return View(model);
}
#region Helpers
@@ -460,10 +454,8 @@ private IActionResult RedirectToLocal(string returnUrl)
{
return Redirect(returnUrl);
}
- else
- {
- return RedirectToAction(nameof(HomeController.Index), "Home");
- }
+
+ return RedirectToAction(nameof(HomeController.Index), "Home");
}
#endregion
diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AuthorizationController.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AuthorizationController.cs
index ef32ad5e6..c03472615 100644
--- a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AuthorizationController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/AuthorizationController.cs
@@ -4,6 +4,7 @@
* the license and the contributors participating to this project.
*/
+using System.Globalization;
using System.Security.Claims;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore;
@@ -91,7 +92,7 @@ public async Task Authorize()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in."
@@ -117,7 +118,7 @@ public async Task Authorize()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidRequest,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@@ -181,7 +182,7 @@ public async Task Authorize()
case ConsentTypes.External when authorizations.Count is 0:
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@@ -255,7 +256,7 @@ public async Task Authorize()
case ConsentTypes.Systematic when request.HasPromptValue(PromptValues.None):
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@@ -265,7 +266,7 @@ public async Task Authorize()
// In every other case, render the consent form.
default: return View(new AuthorizeViewModel
{
- ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application),
+ ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application, CultureInfo.CurrentCulture),
Scope = request.Scope
});
}
@@ -289,7 +290,7 @@ public async Task Accept()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@@ -317,7 +318,7 @@ public async Task Accept()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@@ -406,15 +407,13 @@ public async Task Verify()
// Render a form asking the user to confirm the authorization demand.
return View(new VerifyViewModel
{
- ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application),
- Scope = string.Join(" ", result.Principal.GetScopes()),
+ ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application, CultureInfo.CurrentCulture),
+ Scope = string.Join(Separators.Space[0], result.Principal.GetScopes()),
UserCode = result.Properties.GetTokenValue(OpenIddictServerAspNetCoreConstants.Tokens.UserCode)
});
}
- // If a user code was specified (e.g as part of the verification_uri_complete)
- // 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)))
+ if (!string.IsNullOrEmpty(result.Properties?.GetTokenValue(OpenIddictServerAspNetCoreConstants.Tokens.UserCode)))
{
return View(new VerifyViewModel
{
@@ -437,7 +436,7 @@ public async Task VerifyAccept()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
@@ -544,7 +543,7 @@ public async Task Exchange()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The username/password couple is invalid."
@@ -557,7 +556,7 @@ public async Task Exchange()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The username/password couple is invalid."
@@ -599,7 +598,7 @@ public async Task Exchange()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid."
@@ -611,7 +610,7 @@ public async Task Exchange()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."
@@ -657,7 +656,7 @@ public async Task Exchange()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid."
@@ -669,7 +668,7 @@ public async Task Exchange()
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."
diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ManageController.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ManageController.cs
index 859db0e29..13771b634 100644
--- a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ManageController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ManageController.cs
@@ -271,7 +271,7 @@ public async Task ManageLogins(ManageMessageId? message = null)
return View("Error");
}
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;
return View(new ManageLoginsViewModel
{
diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ResourceController.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ResourceController.cs
index c044dd99d..f461386fe 100644
--- a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ResourceController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/ResourceController.cs
@@ -28,7 +28,7 @@ public async Task GetMessage()
{
return Forbid(
authenticationSchemes: OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictValidationAspNetCoreConstants.Properties.Scope] = "demo_api",
[OpenIddictValidationAspNetCoreConstants.Properties.Error] = Errors.InsufficientScope,
@@ -42,7 +42,7 @@ public async Task GetMessage()
{
return Challenge(
authenticationSchemes: OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictValidationAspNetCoreConstants.Properties.Error] = Errors.InvalidToken,
[OpenIddictValidationAspNetCoreConstants.Properties.ErrorDescription] =
diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/UserinfoController.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/UserinfoController.cs
index 63447c085..1470adbc4 100644
--- a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/UserinfoController.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Controllers/UserinfoController.cs
@@ -26,7 +26,7 @@ public async Task UserInfo()
{
return Challenge(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
- properties: new AuthenticationProperties(new Dictionary
+ properties: new AuthenticationProperties(new Dictionary(StringComparer.Ordinal)
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidToken,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Program.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Program.cs
index baf9e5a19..80e5f2cfe 100644
--- a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Program.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Program.cs
@@ -370,8 +370,8 @@ static ValueTask GetServerAuthenticationOptionsA
ServerCertificate = store.Certificates
.Find(X509FindType.FindByExtension, "1.3.6.1.4.1.311.84.1.1", validOnly: false)
.Cast()
- .Where(static certificate => certificate.NotBefore < TimeProvider.System.GetLocalNow())
- .Where(static certificate => certificate.NotAfter > TimeProvider.System.GetLocalNow())
+ .Where(static certificate => new DateTimeOffset(certificate.NotBefore) < TimeProvider.System.GetLocalNow())
+ .Where(static certificate => new DateTimeOffset(certificate.NotAfter) > TimeProvider.System.GetLocalNow())
.OrderByDescending(static certificate => certificate.NotAfter)
.FirstOrDefault()
?? throw new InvalidOperationException("The ASP.NET Core HTTPS development certificate was not found.")
diff --git a/sandbox/OpenIddict.Sandbox.Console.Client/InteractiveService.cs b/sandbox/OpenIddict.Sandbox.Console.Client/InteractiveService.cs
index b96d123a8..479ee652f 100644
--- a/sandbox/OpenIddict.Sandbox.Console.Client/InteractiveService.cs
+++ b/sandbox/OpenIddict.Sandbox.Console.Client/InteractiveService.cs
@@ -502,13 +502,13 @@ async Task PromptAsync() => AnsiConsole.Prompt(new SelectionPrompt choices = [];
var types = configuration.ResponseTypesSupported.Select(static type =>
- new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)));
+ new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal));
if (configuration.GrantTypesSupported.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)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes
- .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)))
+ .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.Code))))
{
choices.Add(((
@@ -521,7 +521,7 @@ async Task PromptAsync() => AnsiConsole.Prompt(new SelectionPrompt type.Count is 1 && type.Contains(ResponseTypes.IdToken)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes
- .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)))
+ .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.IdToken))))
{
choices.Add(((
@@ -532,7 +532,7 @@ async Task PromptAsync() => AnsiConsole.Prompt(new SelectionPrompt type.Count is 2 && type.Contains(ResponseTypes.IdToken) &&
type.Contains(ResponseTypes.Token)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes
- .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)))
+ .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.IdToken) &&
type.Contains(ResponseTypes.Token))))
{
@@ -550,7 +550,7 @@ async Task PromptAsync() => AnsiConsole.Prompt(new SelectionPrompt type.Count is 2 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.IdToken)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes
- .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)))
+ .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.IdToken))))
{
@@ -563,7 +563,7 @@ async Task PromptAsync() => AnsiConsole.Prompt(new SelectionPrompt new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)))
+ .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 3 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.IdToken) &&
type.Contains(ResponseTypes.Token))))
@@ -577,7 +577,7 @@ async Task PromptAsync() => AnsiConsole.Prompt(new SelectionPrompt type.Count is 2 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.Token)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes
- .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)))
+ .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 2 && type.Contains(ResponseTypes.Code) &&
type.Contains(ResponseTypes.Token))))
{
@@ -589,7 +589,7 @@ async Task PromptAsync() => AnsiConsole.Prompt(new SelectionPrompt type.Count is 1 && type.Contains(ResponseTypes.None)) &&
(registration.ResponseTypes.Count is 0 || registration.ResponseTypes
- .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries)))
+ .Select(static type => new HashSet(type.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries), StringComparer.Ordinal))
.Any(static type => type.Count is 1 && type.Contains(ResponseTypes.None))))
{
choices.Add(((
@@ -873,7 +873,9 @@ static X509Certificate2 GenerateEphemeralTlsClientCertificate()
//
// 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.
+#pragma warning disable MA0144
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+#pragma warning restore MA0144
{
certificate = X509CertificateLoader.LoadPkcs12(
data: certificate.Export(X509ContentType.Pfx, string.Empty),
diff --git a/sandbox/OpenIddict.Sandbox.Maui.Client/MainPage.xaml.cs b/sandbox/OpenIddict.Sandbox.Maui.Client/MainPage.xaml.cs
index 311145222..5c11bc794 100644
--- a/sandbox/OpenIddict.Sandbox.Maui.Client/MainPage.xaml.cs
+++ b/sandbox/OpenIddict.Sandbox.Maui.Client/MainPage.xaml.cs
@@ -22,7 +22,7 @@ private async void OnLocalLoginButtonClicked(object sender, EventArgs e)
=> await LogInAsync("Local");
private async void OnLocalLoginWithGitHubButtonClicked(object sender, EventArgs e)
- => await LogInAsync("Local", new()
+ => await LogInAsync("Local", new(StringComparer.Ordinal)
{
[Parameters.IdentityProvider] = Providers.GitHub
});
diff --git a/sandbox/OpenIddict.Sandbox.Maui.Client/MauiProgram.cs b/sandbox/OpenIddict.Sandbox.Maui.Client/MauiProgram.cs
index d15264940..b160b43a8 100644
--- a/sandbox/OpenIddict.Sandbox.Maui.Client/MauiProgram.cs
+++ b/sandbox/OpenIddict.Sandbox.Maui.Client/MauiProgram.cs
@@ -57,8 +57,10 @@ public static MauiApp CreateMauiApp()
#if IOS
// Warning: server certificate validation is disabled to simplify testing the MAUI
// application with the iOS simulator: in production, it SHOULD NEVER be disabled.
+#pragma warning disable MA0039
.ConfigureHttpClientHandler("Local", handler => handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator)
+#pragma warning restore MA0039
#endif
;
diff --git a/sandbox/OpenIddict.Sandbox.WinForms.Client/MainForm.cs b/sandbox/OpenIddict.Sandbox.WinForms.Client/MainForm.cs
index 9aaf0f287..2590205b3 100644
--- a/sandbox/OpenIddict.Sandbox.WinForms.Client/MainForm.cs
+++ b/sandbox/OpenIddict.Sandbox.WinForms.Client/MainForm.cs
@@ -22,7 +22,7 @@ private async void LocalLoginButton_Click(object sender, EventArgs e)
=> await LogInAsync("Local");
private async void LocalLoginWithGitHubButton_Click(object sender, EventArgs e)
- => await LogInAsync("Local", new()
+ => await LogInAsync("Local", new(StringComparer.Ordinal)
{
[Parameters.IdentityProvider] = Providers.GitHub
});
diff --git a/sandbox/OpenIddict.Sandbox.Wpf.Client/MainWindow.xaml.cs b/sandbox/OpenIddict.Sandbox.Wpf.Client/MainWindow.xaml.cs
index ff916a8f8..5e28d59e6 100644
--- a/sandbox/OpenIddict.Sandbox.Wpf.Client/MainWindow.xaml.cs
+++ b/sandbox/OpenIddict.Sandbox.Wpf.Client/MainWindow.xaml.cs
@@ -23,7 +23,7 @@ private async void LocalLoginButton_Click(object sender, RoutedEventArgs e)
=> await LogInAsync("Local");
private async void LocalLoginWithGitHubButton_Click(object sender, RoutedEventArgs e)
- => await LogInAsync("Local", new()
+ => await LogInAsync("Local", new(StringComparer.Ordinal)
{
[Parameters.IdentityProvider] = Providers.GitHub
});
diff --git a/shared/OpenIddict.Extensions/OpenIddictHelpers.cs b/shared/OpenIddict.Extensions/OpenIddictHelpers.cs
index f7dd1287a..9bacb8511 100644
--- a/shared/OpenIddict.Extensions/OpenIddictHelpers.cs
+++ b/shared/OpenIddict.Extensions/OpenIddictHelpers.cs
@@ -276,8 +276,8 @@ public static IReadOnlyDictionary ParseQuery(string query)
Key: parts[0] is string key ? Uri.UnescapeDataString(key) : null,
Value: parts.Length is > 1 && parts[1] is string value ? Uri.UnescapeDataString(value) : null))
.Where(static pair => !string.IsNullOrEmpty(pair.Key))
- .GroupBy(static pair => pair.Key)
- .ToDictionary(static pair => pair.Key!, static pair => new StringValues([.. pair.Select(parts => parts.Value)]));
+ .GroupBy(static pair => pair.Key, StringComparer.Ordinal)
+ .ToDictionary(static pair => pair.Key!, static pair => new StringValues([.. pair.Select(parts => parts.Value)]), StringComparer.Ordinal);
}
///
@@ -297,8 +297,8 @@ public static IReadOnlyDictionary ParseFragment(string fra
Key: parts[0] is string key ? Uri.UnescapeDataString(key) : null,
Value: parts.Length is > 1 && parts[1] is string value ? Uri.UnescapeDataString(value) : null))
.Where(static pair => !string.IsNullOrEmpty(pair.Key))
- .GroupBy(static pair => pair.Key)
- .ToDictionary(static pair => pair.Key!, static pair => new StringValues([.. pair.Select(parts => parts.Value)]));
+ .GroupBy(static pair => pair.Key, StringComparer.Ordinal)
+ .ToDictionary(static pair => pair.Key!, static pair => new StringValues([.. pair.Select(parts => parts.Value)]), StringComparer.Ordinal);
}
///
@@ -345,7 +345,7 @@ public static async ValueTask> ParseFo
while (enumerator.MoveNext())
{
var element = enumerator.GetTextElement();
- if (charset.Contains(element))
+ if (charset.Contains(element, StringComparer.Ordinal))
{
builder.Append(element);
}
diff --git a/src/OpenIddict.Abstractions/OpenIddictConstants.cs b/src/OpenIddict.Abstractions/OpenIddictConstants.cs
index cbc3369ef..b297b1373 100644
--- a/src/OpenIddict.Abstractions/OpenIddictConstants.cs
+++ b/src/OpenIddict.Abstractions/OpenIddictConstants.cs
@@ -560,6 +560,7 @@ public static class Separators
public static readonly char[] DoubleQuote = ['"'];
public static readonly char[] EqualsSign = ['='];
public static readonly char[] Hash = ['#'];
+ public static readonly char[] Plus = ['+'];
public static readonly char[] QuestionMark = ['?'];
public static readonly char[] Semicolon = [';'];
public static readonly char[] Space = [' '];
diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
index 556456381..94ee1b264 100644
--- a/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
+++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
@@ -308,9 +308,7 @@ public static bool IsImplicitFlow(this OpenIddictRequest request)
continue;
}
- // Note: though the OIDC core specs does not include the OAuth 2.0-inherited response_type=token,
- // it is considered as a valid response_type for the implicit flow for backward compatibility.
- else if (segment.Equals(ResponseTypes.Token, StringComparison.Ordinal))
+ if (segment.Equals(ResponseTypes.Token, StringComparison.Ordinal))
{
flags |= /* token */ 0x02;
@@ -359,14 +357,14 @@ public static bool IsHybridFlow(this OpenIddictRequest request)
continue;
}
- else if (segment.Equals(ResponseTypes.IdToken, StringComparison.Ordinal))
+ if (segment.Equals(ResponseTypes.IdToken, StringComparison.Ordinal))
{
flags |= /* id_token: */ 0x02;
continue;
}
- else if (segment.Equals(ResponseTypes.Token, StringComparison.Ordinal))
+ if (segment.Equals(ResponseTypes.Token, StringComparison.Ordinal))
{
flags |= /* token: */ 0x04;
@@ -678,7 +676,7 @@ public static ImmutableDictionary> GetDestination
var builder = ImmutableDictionary.CreateBuilder>(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();
@@ -712,7 +710,7 @@ public static ImmutableDictionary> GetDestination
var builder = ImmutableDictionary.CreateBuilder>(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();
@@ -749,7 +747,8 @@ public static ClaimsIdentity SetDestinations(this ClaimsIdentity identity,
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);
}
@@ -772,7 +771,8 @@ public static ClaimsPrincipal SetDestinations(this ClaimsPrincipal principal,
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);
}
diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs
index d0456b708..90ebbf84f 100644
--- a/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs
+++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs
@@ -121,7 +121,7 @@ public OpenIddictMessage(IEnumerable> 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.
if (string.IsNullOrEmpty(parameter.Key))
diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs
index f578d4961..fa5289989 100644
--- a/src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs
+++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs
@@ -205,7 +205,7 @@ public bool Equals(OpenIddictParameter other)
(string left, string right) => string.Equals(left, right, StringComparison.Ordinal),
// 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
// as a null value and return true if the other parameter is null too.
@@ -323,7 +323,7 @@ JsonValue value when value.TryGetValue(out bool 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 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),
// serialize it to a JsonElement first to determine its actual JSON representation
@@ -342,7 +342,7 @@ static int GetHashCodeFromArray(string?[] array)
for (var index = 0; index < array.Length; index++)
{
- hash.Add(array[index]);
+ hash.Add(array[index], StringComparer.Ordinal);
}
return hash.ToHashCode();
@@ -368,10 +368,10 @@ static int GetHashCodeFromJsonElement(JsonElement element)
return result.GetHashCode();
case JsonValueKind.Number:
- return element.GetRawText().GetHashCode();
+ return element.GetRawText().GetHashCode(StringComparison.Ordinal);
case JsonValueKind.String:
- return element.GetString()!.GetHashCode();
+ return element.GetString()!.GetHashCode(StringComparison.Ordinal);
case JsonValueKind.Array:
{
@@ -391,7 +391,7 @@ static int GetHashCodeFromJsonElement(JsonElement element)
foreach (var property in element.EnumerateObject())
{
- hash.Add(property.Name);
+ hash.Add(property.Name, StringComparer.Ordinal);
hash.Add(GetHashCodeFromJsonElement(property.Value));
}
@@ -441,7 +441,7 @@ JsonNode value when JsonSerializer.SerializeToElement(value, OpenIddictSerialize
is JsonElement { ValueKind: JsonValueKind.Object } element
=> GetParametersFromJsonElement(element),
- _ => ImmutableDictionary.Create(StringComparer.Ordinal)
+ _ => ImmutableDictionary.Empty
};
static IReadOnlyDictionary GetParametersFromJsonElement(JsonElement element)
diff --git a/src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs b/src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs
index 784e85da3..bcac5ea1b 100644
--- a/src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs
+++ b/src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs
@@ -323,7 +323,7 @@ IAsyncEnumerable ListAsync(
/// The application identifier associated with the tokens.
/// The that can be used to abort the operation.
/// The number of tokens associated with the specified application that were marked as revoked.
- ValueTask RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken = default);
+ ValueTask RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken);
///
/// Revokes all the tokens associated with the specified authorization identifier.
@@ -339,7 +339,7 @@ IAsyncEnumerable ListAsync(
/// The subject associated with the tokens.
/// The that can be used to abort the operation.
/// The number of tokens associated with the specified subject that were marked as revoked.
- ValueTask RevokeBySubjectAsync(string subject, CancellationToken cancellationToken = default);
+ ValueTask RevokeBySubjectAsync(string subject, CancellationToken cancellationToken);
///
/// Sets the application identifier associated with a token.
diff --git a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs
index 28683114f..e08d00bf8 100644
--- a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs
+++ b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs
@@ -66,7 +66,7 @@ public void PostConfigure(string? name, OpenIddictClientAspNetCoreOptions option
foreach (var (provider, registrations) in _provider.GetRequiredService>()
.CurrentValue.Registrations
.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())))
{
// If an explicit mapping was already added, don't overwrite it.
@@ -148,7 +148,7 @@ public ValidateOptionsResult Validate(string? name, AuthenticationOptions option
// Ensure the forwarded authentication schemes are mapped to the OpenIddict client forwarder.
foreach (var group in _provider.GetRequiredService>()
.CurrentValue.ForwardedAuthenticationSchemes
- .GroupBy(static scheme => scheme.Name)
+ .GroupBy(static scheme => scheme.Name, StringComparer.Ordinal)
.Where(group => !ValidateHandlerType(options.SchemeMap, group.Key)))
{
builder.AddError(SR.FormatID0414(group.Key));
@@ -195,7 +195,7 @@ public ValidateOptionsResult Validate(string? name, OpenIddictClientAspNetCoreOp
foreach (var (provider, registrations) in _provider.GetRequiredService>()
.CurrentValue.Registrations
.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()))
.Where(static group => group.Registrations.Count is > 1))
{
diff --git a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreForwarder.cs b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreForwarder.cs
index 2d746f85e..edc4b44f8 100644
--- a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreForwarder.cs
+++ b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreForwarder.cs
@@ -54,7 +54,7 @@ public async Task ChallengeAsync(AuthenticationProperties? properties)
await _context.ChallengeAsync(
scheme: OpenIddictClientAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(
- items: new Dictionary(properties?.Items ?? ImmutableDictionary.Create())
+ items: new Dictionary(properties?.Items ?? ImmutableDictionary.Empty, StringComparer.Ordinal)
{
[Properties.ProviderName] = _scheme.Name
},
@@ -76,7 +76,7 @@ public async Task ForbidAsync(AuthenticationProperties? properties)
await _context.ForbidAsync(
scheme: OpenIddictClientAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(
- items: new Dictionary(properties?.Items ?? ImmutableDictionary.Create())
+ items: new Dictionary(properties?.Items ?? ImmutableDictionary.Empty, StringComparer.Ordinal)
{
[Properties.ProviderName] = _scheme.Name
},
@@ -98,7 +98,7 @@ public async Task SignOutAsync(AuthenticationProperties? properties)
await _context.SignOutAsync(
scheme: OpenIddictClientAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(
- items: new Dictionary(properties?.Items ?? ImmutableDictionary.Create())
+ items: new Dictionary(properties?.Items ?? ImmutableDictionary.Empty, StringComparer.Ordinal)
{
[Properties.ProviderName] = _scheme.Name
},
diff --git a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs
index f704f287e..87645a200 100644
--- a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs
+++ b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs
@@ -76,12 +76,12 @@ public async Task HandleRequestAsync()
return true;
}
- else if (context.IsRequestSkipped)
+ if (context.IsRequestSkipped)
{
return false;
}
- else if (context.IsRejected)
+ if (context.IsRejected)
{
var notification = new ProcessErrorContext(transaction)
{
@@ -98,7 +98,7 @@ public async Task HandleRequestAsync()
return true;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
return false;
}
@@ -133,7 +133,7 @@ protected override async Task HandleAuthenticateAsync()
return AuthenticateResult.NoResult();
}
- else if (context.IsRejected)
+ if (context.IsRejected)
{
// 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.
@@ -390,7 +390,7 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties? pro
return;
}
- else if (context.IsRejected)
+ if (context.IsRejected)
{
var notification = new ProcessErrorContext(transaction)
{
@@ -436,7 +436,7 @@ public async Task SignOutAsync(AuthenticationProperties? properties)
return;
}
- else if (context.IsRejected)
+ if (context.IsRejected)
{
var notification = new ProcessErrorContext(transaction)
{
diff --git a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs
index f46f25eb9..28729103f 100644
--- a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs
+++ b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs
@@ -572,8 +572,7 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
context.Issuer = uri;
}
- if (properties.Items.TryGetValue(Properties.Scope, out string? scope) &&
- !string.IsNullOrEmpty(scope))
+ if (properties.Items.TryGetValue(Properties.Scope, out string? scope) && !string.IsNullOrEmpty(scope))
{
context.Scopes.UnionWith(scope.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries));
}
diff --git a/src/OpenIddict.Client.DataProtection/OpenIddictClientDataProtectionFormatter.cs b/src/OpenIddict.Client.DataProtection/OpenIddictClientDataProtectionFormatter.cs
index ddf227363..b0abdf994 100644
--- a/src/OpenIddict.Client.DataProtection/OpenIddictClientDataProtectionFormatter.cs
+++ b/src/OpenIddict.Client.DataProtection/OpenIddictClientDataProtectionFormatter.cs
@@ -182,7 +182,7 @@ public void WriteToken(BinaryWriter writer, ClaimsPrincipal principal)
ArgumentNullException.ThrowIfNull(writer);
ArgumentNullException.ThrowIfNull(principal);
- var properties = new Dictionary();
+ var properties = new Dictionary(StringComparer.Ordinal);
// 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
diff --git a/src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs b/src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs
index cd5af07d5..21110aa34 100644
--- a/src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs
+++ b/src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs
@@ -61,7 +61,7 @@ public void PostConfigure(string? name, OpenIddictClientOwinOptions options)
foreach (var (provider, registrations) in _provider.GetRequiredService>()
.CurrentValue.Registrations
.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())))
{
// If an explicit mapping was already added, don't overwrite it.
@@ -109,7 +109,7 @@ public ValidateOptionsResult Validate(string? name, OpenIddictClientOwinOptions
foreach (var (provider, registrations) in _provider.GetRequiredService>()
.CurrentValue.Registrations
.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()))
.Where(static group => group.Registrations.Count is > 1))
{
diff --git a/src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs b/src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs
index 9ec920de1..774da6c38 100644
--- a/src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs
+++ b/src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs
@@ -95,12 +95,12 @@ public override async Task InvokeAsync()
return true;
}
- else if (context.IsRequestSkipped)
+ if (context.IsRequestSkipped)
{
return false;
}
- else if (context.IsRejected)
+ if (context.IsRejected)
{
var notification = new ProcessErrorContext(transaction)
{
@@ -117,7 +117,7 @@ public override async Task InvokeAsync()
return true;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
return false;
}
@@ -152,7 +152,7 @@ public override async Task InvokeAsync()
return null;
}
- else if (context.IsRejected)
+ if (context.IsRejected)
{
// 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.
@@ -315,7 +315,7 @@ protected override async Task TeardownCoreAsync()
return;
}
- else if (context.IsRejected)
+ if (context.IsRejected)
{
var notification = new ProcessErrorContext(transaction)
{
@@ -359,7 +359,7 @@ protected override async Task TeardownCoreAsync()
return;
}
- else if (context.IsRejected)
+ if (context.IsRejected)
{
var notification = new ProcessErrorContext(transaction)
{
@@ -408,7 +408,7 @@ protected override async Task TeardownCoreAsync()
authenticationTypes: [OpenIddictClientOwinDefaults.AuthenticationType],
properties : new AuthenticationProperties(dictionary: new Dictionary(
manager.AuthenticationResponseChallenge.Properties.Dictionary
- ?? ImmutableDictionary.Create())
+ ?? ImmutableDictionary.Empty, StringComparer.Ordinal)
{
[Properties.ProviderName] = type
}));
@@ -447,7 +447,7 @@ protected override async Task TeardownCoreAsync()
authenticationTypes: [OpenIddictClientOwinDefaults.AuthenticationType],
properties : new AuthenticationProperties(dictionary: new Dictionary(
manager.AuthenticationResponseRevoke.Properties.Dictionary
- ?? ImmutableDictionary.Create())
+ ?? ImmutableDictionary.Empty, StringComparer.Ordinal)
{
[Properties.ProviderName] = type
}));
diff --git a/src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs b/src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs
index 95559fce2..c5e628f3e 100644
--- a/src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs
+++ b/src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs
@@ -578,8 +578,7 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
context.Issuer = uri;
}
- if (properties.Dictionary.TryGetValue(Properties.Scope, out string? scope) &&
- !string.IsNullOrEmpty(scope))
+ if (properties.Dictionary.TryGetValue(Properties.Scope, out string? scope) && !string.IsNullOrEmpty(scope))
{
context.Scopes.UnionWith(scope.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries));
}
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
index 5b7d24ba6..ff210830e 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
@@ -228,7 +228,8 @@ NSUrl CreateUrl() => OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
- static parameter => (StringValues) parameter.Value))!;
+ static parameter => (StringValues) parameter.Value,
+ StringComparer.Ordinal))!;
void HandleCallback(NSUrl? url, NSError? error)
{
@@ -346,7 +347,8 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
- static parameter => (StringValues) parameter.Value)).AbsoluteUri)!);
+ static parameter => (StringValues) parameter.Value,
+ StringComparer.Ordinal)).AbsoluteUri)!);
context.HandleRequest();
#else
@@ -424,7 +426,8 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
- static parameter => (StringValues) parameter.Value)),
+ static parameter => (StringValues) parameter.Value,
+ StringComparer.Ordinal)),
callbackUri: new Uri(context.RedirectUri, UriKind.Absolute)))
{
case { ResponseStatus: WebAuthenticationStatus.Success } result
@@ -530,7 +533,8 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
- static parameter => (StringValues) parameter.Value));
+ static parameter => (StringValues) parameter.Value,
+ StringComparer.Ordinal));
if (OperatingSystem.IsWindows())
{
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
index 85950f40d..7f2ecade6 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
@@ -228,7 +228,8 @@ NSUrl CreateUrl() => OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
- static parameter => (StringValues) parameter.Value))!;
+ static parameter => (StringValues) parameter.Value,
+ StringComparer.Ordinal))!;
void HandleCallback(NSUrl? url, NSError? error)
{
@@ -346,7 +347,8 @@ public async ValueTask HandleAsync(ApplyEndSessionRequestContext context)
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
- static parameter => (StringValues) parameter.Value)).AbsoluteUri)!);
+ static parameter => (StringValues) parameter.Value,
+ StringComparer.Ordinal)).AbsoluteUri)!);
context.HandleRequest();
#else
@@ -424,7 +426,8 @@ public async ValueTask HandleAsync(ApplyEndSessionRequestContext context)
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
- static parameter => (StringValues) parameter.Value)),
+ static parameter => (StringValues) parameter.Value,
+ StringComparer.Ordinal)),
callbackUri: new Uri(context.PostLogoutRedirectUri, UriKind.Absolute)))
{
case { ResponseStatus: WebAuthenticationStatus.Success } result
@@ -530,7 +533,8 @@ public async ValueTask HandleAsync(ApplyEndSessionRequestContext context)
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
- static parameter => (StringValues) parameter.Value));
+ static parameter => (StringValues) parameter.Value,
+ StringComparer.Ordinal));
if (OperatingSystem.IsWindows())
{
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs
index 138e4bd6f..ac56bfa77 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs
@@ -655,13 +655,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationMarshal.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationMarshal.cs
index b8dbc3714..e5d1a43da 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationMarshal.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationMarshal.cs
@@ -19,7 +19,7 @@ public sealed class OpenIddictClientSystemIntegrationMarshal
private readonly ConcurrentDictionary TaskCompletionSource)>> _tracker = new();
+ TaskCompletionSource TaskCompletionSource)>> _tracker = new(StringComparer.Ordinal);
///
/// Determines whether the authentication demand corresponding to the specified nonce is tracked.
diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
index 8819d0ece..f47dc1b72 100644
--- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
+++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
@@ -374,7 +374,7 @@ context.ClientAuthenticationMethod is ClientAuthenticationMethods.ClientSecretBa
return ValueTask.CompletedTask;
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 ValueTask HandleAsync(TContext context)
request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(request.RequestUri,
context.Transaction.Request.GetParameters().ToDictionary(
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.
@@ -609,7 +610,7 @@ public async ValueTask HandleAsync(TContext context)
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 = new GZipStream(stream, CompressionMode.Decompress);
diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationExtensions.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationExtensions.cs
index 6c9fa75d3..0ba5652c7 100644
--- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationExtensions.cs
+++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationExtensions.cs
@@ -14,7 +14,7 @@ namespace Microsoft.Extensions.DependencyInjection;
///
/// Exposes extensions allowing to register the OpenIddict client Web integration services.
///
-public static partial class OpenIddictClientWebIntegrationExtensions
+public static class OpenIddictClientWebIntegrationExtensions
{
///
/// Registers the OpenIddict client Web integration services in the DI container.
diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs
index 77802d7f2..f796c2338 100644
--- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs
+++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs
@@ -270,7 +270,7 @@ public ValueTask HandleAsync(PrepareTokenRequestContext context)
{
request.RequestUri = OpenIddictHelpers.AddQueryStringParameters(
uri: request.RequestUri,
- parameters: new Dictionary
+ parameters: new Dictionary(StringComparer.Ordinal)
{
["chat_os_type"] = "bot",
["chat_version"] = "1.30.0"
diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Introspection.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Introspection.cs
index f15f8c66b..422ff6f99 100644
--- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Introspection.cs
+++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Introspection.cs
@@ -66,7 +66,7 @@ public ValueTask HandleAsync(ExtractIntrospectionResponseContext context)
}
}
- context.Response.Scope = string.Join(" ", scopes);
+ context.Response.Scope = string.Join(Separators.Space[0], scopes);
}
return ValueTask.CompletedTask;
diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
index adbf18819..d95e6bf47 100644
--- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
+++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
@@ -161,13 +161,11 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
//
// See https://shopify.dev/docs/apps/auth/oauth/getting-started#remove-the-hmac-parameter-from-the-query-string
// for more information.
- foreach (var (name, value) in
- from parameter in OpenIddictHelpers.ParseQuery(context.RequestUri!.Query)
- where !string.IsNullOrEmpty(parameter.Key)
- where !string.Equals(parameter.Key, "hmac", StringComparison.Ordinal)
- orderby parameter.Key ascending
- from value in parameter.Value
- select (Name: parameter.Key, Value: value))
+ foreach (var (name, value) in OpenIddictHelpers.ParseQuery(context.RequestUri!.Query)
+ .Where(static parameter => !string.IsNullOrEmpty(parameter.Key))
+ .Where(static parameter => !string.Equals(parameter.Key, "hmac", StringComparison.Ordinal))
+ .OrderBy(static parameter => parameter.Key, StringComparer.Ordinal)
+ .SelectMany(static parameter => parameter.Value, static (parameter, value) => (Name: parameter.Key, Value: value)))
{
if (builder.Length is > 0)
{
@@ -1187,7 +1185,7 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
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
@@ -1204,7 +1202,7 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
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
@@ -1213,7 +1211,7 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
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
@@ -1222,7 +1220,7 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
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
@@ -1232,7 +1230,7 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
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
@@ -1274,9 +1272,9 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
var settings = context.Registration.GetTwitterSettings();
- context.UserInfoRequest["expansions"] = string.Join(",", settings.Expansions);
- context.UserInfoRequest["tweet.fields"] = string.Join(",", settings.TweetFields);
- context.UserInfoRequest["user.fields"] = string.Join(",", settings.UserFields);
+ context.UserInfoRequest["expansions"] = string.Join(Separators.Comma[0], settings.Expansions);
+ context.UserInfoRequest["tweet.fields"] = string.Join(Separators.Comma[0], settings.TweetFields);
+ context.UserInfoRequest["user.fields"] = string.Join(Separators.Comma[0], settings.UserFields);
}
// Weibo requires sending the user identifier as part of the userinfo request.
@@ -1880,11 +1878,11 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
// the standard format (that requires using a space as the scope separator):
ProviderTypes.Deezer or ProviderTypes.Disqus or ProviderTypes.Shopify or
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 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
};
diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationOptions.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationOptions.cs
index a87181ab0..8e219e020 100644
--- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationOptions.cs
+++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationOptions.cs
@@ -9,6 +9,6 @@ namespace OpenIddict.Client.WebIntegration;
///
/// Provides various settings needed to configure the OpenIddict client Web integration.
///
-public sealed partial class OpenIddictClientWebIntegrationOptions
+public sealed class OpenIddictClientWebIntegrationOptions
{
}
diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.Authentication.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.Authentication.cs
index 9173eb8b4..c2d571209 100644
--- a/src/OpenIddict.Client/OpenIddictClientHandlers.Authentication.cs
+++ b/src/OpenIddict.Client/OpenIddictClientHandlers.Authentication.cs
@@ -89,7 +89,7 @@ public async ValueTask HandleAsync(ProcessChallengeContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
@@ -138,13 +138,13 @@ public async ValueTask HandleAsync(ProcessChallengeContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -419,13 +419,13 @@ public async ValueTask HandleAsync(ProcessRequestContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -478,13 +478,13 @@ public async ValueTask HandleAsync(ProcessRequestContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -531,13 +531,13 @@ public async ValueTask HandleAsync(ProcessRequestContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -585,7 +585,7 @@ public async ValueTask HandleAsync(TContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
@@ -676,13 +676,13 @@ public async ValueTask HandleAsync(ValidateRedirectionRequestContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs
index aba7b694a..e26f67474 100644
--- a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs
+++ b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs
@@ -410,7 +410,7 @@ public async ValueTask HandleAsync(ValidateTokenContext context)
foreach (var claim in result.ClaimsIdentity.Claims)
{
// 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;
}
@@ -424,7 +424,7 @@ public async ValueTask HandleAsync(ValidateTokenContext context)
identity = result.ClaimsIdentity.Clone(claim => claim switch
{
// 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,
_ => true // Allow any other claim.
diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.Session.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.Session.cs
index 84518daee..aa8bea7f1 100644
--- a/src/OpenIddict.Client/OpenIddictClientHandlers.Session.cs
+++ b/src/OpenIddict.Client/OpenIddictClientHandlers.Session.cs
@@ -74,7 +74,7 @@ public async ValueTask HandleAsync(ProcessSignOutContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
@@ -121,13 +121,13 @@ public async ValueTask HandleAsync(ProcessSignOutContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -210,13 +210,13 @@ public async ValueTask HandleAsync(ProcessRequestContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -269,13 +269,13 @@ public async ValueTask HandleAsync(ProcessRequestContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -322,13 +322,13 @@ public async ValueTask HandleAsync(ProcessRequestContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -376,7 +376,7 @@ public async ValueTask HandleAsync(TContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
@@ -425,13 +425,13 @@ public async ValueTask HandleAsync(ValidatePostLogoutRedirectionRequestContext c
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.cs
index 76dd0a4e3..389bd25ce 100644
--- a/src/OpenIddict.Client/OpenIddictClientHandlers.cs
+++ b/src/OpenIddict.Client/OpenIddictClientHandlers.cs
@@ -713,13 +713,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
if (context.RejectStateToken)
{
@@ -1626,13 +1626,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
if (context.RejectFrontchannelIdentityToken)
{
@@ -1674,8 +1674,8 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
Debug.Assert(context.FrontchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
foreach (var group in context.FrontchannelIdentityTokenPrincipal.Claims
- .GroupBy(static claim => claim.Type)
- .ToDictionary(static group => group.Key, group => group.ToList())
+ .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
+ .ToDictionary(static group => group.Key, group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{
context.Reject(
@@ -1806,7 +1806,8 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
// 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.
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(
error: Errors.InvalidRequest,
@@ -2150,13 +2151,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
if (context.RejectFrontchannelAccessToken)
{
@@ -2221,13 +2222,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
if (context.RejectAuthorizationCode)
{
@@ -2697,7 +2698,7 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
// 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
// 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 async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -3363,13 +3364,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
if (context.RejectBackchannelIdentityToken)
{
@@ -3411,8 +3412,8 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
Debug.Assert(context.BackchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
foreach (var group in context.BackchannelIdentityTokenPrincipal.Claims
- .GroupBy(static claim => claim.Type)
- .ToDictionary(static group => group.Key, group => group.ToList())
+ .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
+ .ToDictionary(static group => group.Key, group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{
context.Reject(
@@ -3543,7 +3544,8 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
// 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.
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(
error: Errors.InvalidRequest,
@@ -3851,13 +3853,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
if (context.RejectBackchannelAccessToken)
{
@@ -3920,13 +3922,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
if (context.RejectIssuedToken)
{
@@ -3991,13 +3993,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
if (context.RejectRefreshToken)
{
@@ -4493,13 +4495,13 @@ public async ValueTask HandleAsync(ProcessAuthenticationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
if (context.RejectUserInfoToken)
{
@@ -4542,8 +4544,8 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
Debug.Assert(context.UserInfoTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
foreach (var group in context.UserInfoTokenPrincipal.Claims
- .GroupBy(static claim => claim.Type)
- .ToDictionary(static group => group.Key, group => group.ToList())
+ .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
+ .ToDictionary(static group => group.Key, group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{
context.Reject(
@@ -4907,8 +4909,8 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
}
foreach (var group in context.Principal.Claims
- .GroupBy(static claim => claim.Type)
- .ToDictionary(static group => group.Key, static group => group.ToList())
+ .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
+ .ToDictionary(static group => group.Key, static group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{
throw new InvalidOperationException(SR.FormatID0424(group.Key));
@@ -5848,13 +5850,13 @@ public async ValueTask HandleAsync(ProcessChallengeContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -5912,7 +5914,7 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
// 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
// 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
@@ -6275,7 +6277,7 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
// 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
// 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;
@@ -6737,13 +6739,13 @@ public async ValueTask HandleAsync(ProcessChallengeContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -7900,13 +7902,13 @@ public async ValueTask HandleAsync(ProcessIntrospectionContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -8705,13 +8707,13 @@ public async ValueTask HandleAsync(ProcessRevocationContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
@@ -8908,8 +8910,8 @@ public ValueTask HandleAsync(ProcessSignOutContext context)
}
foreach (var group in context.Principal.Claims
- .GroupBy(static claim => claim.Type)
- .ToDictionary(static group => group.Key, static group => group.ToList())
+ .GroupBy(static claim => claim.Type, StringComparer.Ordinal)
+ .ToDictionary(static group => group.Key, static group => group.ToList(), StringComparer.Ordinal)
.Where(static group => !ValidateClaimGroup(group.Key, group.Value)))
{
throw new InvalidOperationException(SR.FormatID0424(group.Key));
@@ -9358,13 +9360,13 @@ public async ValueTask HandleAsync(ProcessSignOutContext context)
return;
}
- else if (notification.IsRequestSkipped)
+ if (notification.IsRequestSkipped)
{
context.SkipRequest();
return;
}
- else if (notification.IsRejected)
+ if (notification.IsRejected)
{
context.Reject(
error: notification.Error ?? Errors.InvalidRequest,
diff --git a/src/OpenIddict.Client/OpenIddictClientService.cs b/src/OpenIddict.Client/OpenIddictClientService.cs
index 34bcb79dd..ec2f5ef4c 100644
--- a/src/OpenIddict.Client/OpenIddictClientService.cs
+++ b/src/OpenIddict.Client/OpenIddictClientService.cs
@@ -294,30 +294,27 @@ public async ValueTask AuthenticateInteractivel
context.Error, context.ErrorDescription, context.ErrorUri);
}
- else
- {
- Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013));
-
- return new()
- {
- AuthorizationCode = context.AuthorizationCode,
- AuthorizationResponse = context.Request is not null ? new(context.Request.GetParameters()) : new(),
- BackchannelAccessToken = context.BackchannelAccessToken,
- BackchannelAccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate,
- BackchannelIdentityToken = context.BackchannelIdentityToken,
- BackchannelIdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal,
- FrontchannelAccessToken = context.FrontchannelAccessToken,
- FrontchannelAccessTokenExpirationDate = context.FrontchannelAccessTokenExpirationDate,
- FrontchannelIdentityToken = context.FrontchannelIdentityToken,
- FrontchannelIdentityTokenPrincipal = context.FrontchannelIdentityTokenPrincipal,
- Principal = context.MergedPrincipal,
- Properties = context.Properties,
- RefreshToken = context.RefreshToken,
- StateTokenPrincipal = context.StateTokenPrincipal,
- TokenResponse = context.TokenResponse ?? new(),
- UserInfoTokenPrincipal = context.UserInfoTokenPrincipal
- };
- }
+ Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013));
+
+ return new()
+ {
+ AuthorizationCode = context.AuthorizationCode,
+ AuthorizationResponse = context.Request is not null ? new(context.Request.GetParameters()) : new(),
+ BackchannelAccessToken = context.BackchannelAccessToken,
+ BackchannelAccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate,
+ BackchannelIdentityToken = context.BackchannelIdentityToken,
+ BackchannelIdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal,
+ FrontchannelAccessToken = context.FrontchannelAccessToken,
+ FrontchannelAccessTokenExpirationDate = context.FrontchannelAccessTokenExpirationDate,
+ FrontchannelIdentityToken = context.FrontchannelIdentityToken,
+ FrontchannelIdentityTokenPrincipal = context.FrontchannelIdentityTokenPrincipal,
+ Principal = context.MergedPrincipal,
+ Properties = context.Properties,
+ RefreshToken = context.RefreshToken,
+ StateTokenPrincipal = context.StateTokenPrincipal,
+ TokenResponse = context.TokenResponse ?? new(),
+ UserInfoTokenPrincipal = context.UserInfoTokenPrincipal
+ };
}
///
@@ -652,24 +649,21 @@ public async ValueTask AuthenticateWithDeviceAsync(D
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()
- {
- AccessToken = context.BackchannelAccessToken!,
- AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate,
- IdentityToken = context.BackchannelIdentityToken,
- IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal,
- Principal = context.MergedPrincipal,
- Properties = context.Properties,
- RefreshToken = context.RefreshToken,
- TokenResponse = context.TokenResponse ?? new(),
- UserInfoToken = context.UserInfoToken,
- UserInfoTokenPrincipal = context.UserInfoTokenPrincipal
- };
- }
+ return new()
+ {
+ AccessToken = context.BackchannelAccessToken!,
+ AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate,
+ IdentityToken = context.BackchannelIdentityToken,
+ IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal,
+ Principal = context.MergedPrincipal,
+ Properties = context.Properties,
+ RefreshToken = context.RefreshToken,
+ TokenResponse = context.TokenResponse ?? new(),
+ UserInfoToken = context.UserInfoToken,
+ UserInfoTokenPrincipal = context.UserInfoTokenPrincipal
+ };
}
catch (ProtocolException exception) when (exception.Error is Errors.AuthorizationPending)
diff --git a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
index fe1b58c3e..49f9fbd88 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
@@ -582,13 +582,7 @@ public virtual async ValueTask> GetDisp
{
ArgumentNullException.ThrowIfNull(application);
- var names = await Store.GetDisplayNamesAsync(application, cancellationToken);
- if (names is not { Count: > 0 })
- {
- return ImmutableDictionary.Create();
- }
-
- return names;
+ return await Store.GetDisplayNamesAsync(application, cancellationToken) is { IsEmpty: false } names ? names : [];
}
///
@@ -2007,7 +2001,9 @@ ValueTask> IOpenIddictApplicationManage
///
ValueTask IOpenIddictApplicationManager.GetLocalizedDisplayNameAsync(object application, CancellationToken cancellationToken)
+#pragma warning disable MA0011
=> GetLocalizedDisplayNameAsync((TApplication) application, cancellationToken);
+#pragma warning restore MA0011
///
ValueTask IOpenIddictApplicationManager.GetLocalizedDisplayNameAsync(object application, CultureInfo culture, CancellationToken cancellationToken)
diff --git a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
index 901a18d1f..fd823537f 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
@@ -896,7 +896,7 @@ async IAsyncEnumerable ExecuteAsync([EnumeratorCancellation] C
break;
}
- if (scope.Contains(Separators.Space[0]))
+ if (scope.Contains(Separators.Space[0], StringComparison.Ordinal))
{
yield return new ValidationResult(SR.GetResourceString(SR.ID2042));
diff --git a/src/OpenIddict.Core/Managers/OpenIddictResourceManager.cs b/src/OpenIddict.Core/Managers/OpenIddictResourceManager.cs
index c4cc73a25..a24d0929b 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictResourceManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictResourceManager.cs
@@ -12,6 +12,7 @@
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
+using static System.Net.Mime.MediaTypeNames;
using ValidationException = OpenIddict.Abstractions.OpenIddictExceptions.ValidationException;
namespace OpenIddict.Core;
@@ -385,13 +386,7 @@ public virtual async ValueTask> GetDesc
{
ArgumentNullException.ThrowIfNull(resource);
- var descriptions = await Store.GetDescriptionsAsync(resource, cancellationToken);
- if (descriptions is not { Count: > 0 })
- {
- return ImmutableDictionary.Create();
- }
-
- return descriptions;
+ return await Store.GetDescriptionsAsync(resource, cancellationToken) is { IsEmpty: false } descriptions ? descriptions : [];
}
///
@@ -424,13 +419,7 @@ public virtual async ValueTask> GetDisp
{
ArgumentNullException.ThrowIfNull(resource);
- var names = await Store.GetDisplayNamesAsync(resource, cancellationToken);
- if (names is not { Count: > 0 })
- {
- return ImmutableDictionary.Create();
- }
-
- return names;
+ return await Store.GetDisplayNamesAsync(resource, cancellationToken) is { IsEmpty: false } names ? names : [];
}
///
@@ -880,7 +869,9 @@ ValueTask> IOpenIddictResourceManager.G
///
ValueTask IOpenIddictResourceManager.GetLocalizedDescriptionAsync(object resource, CancellationToken cancellationToken)
+#pragma warning disable MA0011
=> GetLocalizedDescriptionAsync((TResource) resource, cancellationToken);
+#pragma warning restore MA0011
///
ValueTask IOpenIddictResourceManager.GetLocalizedDescriptionAsync(object resource, CultureInfo culture, CancellationToken cancellationToken)
@@ -888,7 +879,9 @@ ValueTask> IOpenIddictResourceManager.G
///
ValueTask IOpenIddictResourceManager.GetLocalizedDisplayNameAsync(object resource, CancellationToken cancellationToken)
+#pragma warning disable MA0011
=> GetLocalizedDisplayNameAsync((TResource) resource, cancellationToken);
+#pragma warning restore MA0011
///
ValueTask IOpenIddictResourceManager.GetLocalizedDisplayNameAsync(object resource, CultureInfo culture, CancellationToken cancellationToken)
diff --git a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
index bf5414862..832fd58ca 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
@@ -424,13 +424,7 @@ public virtual async ValueTask> GetDesc
{
ArgumentNullException.ThrowIfNull(scope);
- var descriptions = await Store.GetDescriptionsAsync(scope, cancellationToken);
- if (descriptions is not { Count: > 0 })
- {
- return ImmutableDictionary.Create();
- }
-
- return descriptions;
+ return await Store.GetDescriptionsAsync(scope, cancellationToken) is { IsEmpty: false } descriptions ? descriptions : [];
}
///
@@ -463,13 +457,7 @@ public virtual async ValueTask> GetDisp
{
ArgumentNullException.ThrowIfNull(scope);
- var names = await Store.GetDisplayNamesAsync(scope, cancellationToken);
- if (names is not { Count: > 0 })
- {
- return ImmutableDictionary.Create();
- }
-
- return names;
+ return await Store.GetDisplayNamesAsync(scope, cancellationToken) is { IsEmpty: false } names ? names : [];
}
///
@@ -870,7 +858,7 @@ async IAsyncEnumerable ExecuteAsync([EnumeratorCancellation] C
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));
}
@@ -962,7 +950,9 @@ ValueTask> IOpenIddictScopeManager.GetD
///
ValueTask IOpenIddictScopeManager.GetLocalizedDescriptionAsync(object scope, CancellationToken cancellationToken)
+#pragma warning disable MA0011
=> GetLocalizedDescriptionAsync((TScope) scope, cancellationToken);
+#pragma warning restore MA0011
///
ValueTask IOpenIddictScopeManager.GetLocalizedDescriptionAsync(object scope, CultureInfo culture, CancellationToken cancellationToken)
@@ -970,7 +960,9 @@ ValueTask> IOpenIddictScopeManager.GetD
///
ValueTask IOpenIddictScopeManager.GetLocalizedDisplayNameAsync(object scope, CancellationToken cancellationToken)
+#pragma warning disable MA0011
=> GetLocalizedDisplayNameAsync((TScope) scope, cancellationToken);
+#pragma warning restore MA0011
///
ValueTask IOpenIddictScopeManager.GetLocalizedDisplayNameAsync(object scope, CultureInfo culture, CancellationToken cancellationToken)
diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
index dc8d91bc3..1a668a7de 100644
--- a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
+++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
@@ -352,7 +352,7 @@ public virtual ValueTask> GetDisplayNam
if (string.IsNullOrEmpty(application.DisplayNames))
{
- return new(ImmutableDictionary.Create());
+ return new([]);
}
// Note: parsing the stringified display names is an expensive operation.
@@ -498,7 +498,7 @@ public virtual ValueTask> GetProperties
if (string.IsNullOrEmpty(application.Properties))
{
- return new(ImmutableDictionary.Create());
+ return new([]);
}
// Note: parsing the stringified properties is an expensive operation.
@@ -510,7 +510,7 @@ public virtual ValueTask> GetProperties
.SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(application.Properties);
- var builder = ImmutableDictionary.CreateBuilder();
+ var builder = ImmutableDictionary.CreateBuilder(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject())
{
@@ -606,7 +606,7 @@ public virtual ValueTask> GetSettingsAsync(T
if (string.IsNullOrEmpty(application.Settings))
{
- return new(ImmutableDictionary.Create());
+ return new([]);
}
// Note: parsing the stringified settings is an expensive operation.
@@ -618,7 +618,7 @@ public virtual ValueTask> GetSettingsAsync(T
.SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(application.Settings);
- var builder = ImmutableDictionary.CreateBuilder();
+ var builder = ImmutableDictionary.CreateBuilder(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject())
{
@@ -1060,17 +1060,14 @@ public virtual async ValueTask UpdateAsync(TApplication application, Cancellatio
return (TKey?) (object?) identifier;
}
- else
- {
- var converter =
+ var converter =
#if NET
- TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
+ TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else
- TypeDescriptor.GetConverter(typeof(TKey));
+ TypeDescriptor.GetConverter(typeof(TKey));
#endif
- return (TKey?) converter.ConvertFromInvariantString(identifier);
- }
+ return (TKey?) converter.ConvertFromInvariantString(identifier);
}
///
@@ -1091,16 +1088,13 @@ public virtual async ValueTask UpdateAsync(TApplication application, Cancellatio
return value;
}
- else
- {
- var converter =
+ var converter =
#if NET
- TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
+ TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else
- TypeDescriptor.GetConverter(typeof(TKey));
+ TypeDescriptor.GetConverter(typeof(TKey));
#endif
- return converter.ConvertToInvariantString(identifier);
- }
+ return converter.ConvertToInvariantString(identifier);
}
}
diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
index b6c60f8c7..6519f5ed1 100644
--- a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
+++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
@@ -302,7 +302,7 @@ async IAsyncEnumerable ExecuteAsync([EnumeratorCancellation] Can
{
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);
}
///
@@ -320,7 +320,7 @@ public virtual ValueTask> GetProperties
if (string.IsNullOrEmpty(authorization.Properties))
{
- return new(ImmutableDictionary.Create());
+ return new([]);
}
// Note: parsing the stringified properties is an expensive operation.
@@ -332,7 +332,7 @@ public virtual ValueTask> GetProperties
.SetSlidingExpiration(TimeSpan.FromMinutes(1));
using var document = JsonDocument.Parse(authorization.Properties);
- var builder = ImmutableDictionary.CreateBuilder();
+ var builder = ImmutableDictionary.CreateBuilder(StringComparer.Ordinal);
foreach (var property in document.RootElement.EnumerateObject())
{
@@ -894,17 +894,14 @@ public virtual async ValueTask UpdateAsync(TAuthorization authorization, Cancell
return (TKey?) (object?) identifier;
}
- else
- {
- var converter =
+ var converter =
#if NET
- TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
+ TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else
- TypeDescriptor.GetConverter(typeof(TKey));
+ TypeDescriptor.GetConverter(typeof(TKey));
#endif
- return (TKey?) converter.ConvertFromInvariantString(identifier);
- }
+ return (TKey?) converter.ConvertFromInvariantString(identifier);
}
///
@@ -925,16 +922,13 @@ public virtual async ValueTask UpdateAsync(TAuthorization authorization, Cancell
return value;
}
- else
- {
- var converter =
+ var converter =
#if NET
- TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
+ TypeDescriptor.GetConverterFromRegisteredType(typeof(TKey));
#else
- TypeDescriptor.GetConverter(typeof(TKey));
+ TypeDescriptor.GetConverter(typeof(TKey));
#endif
- return converter.ConvertToInvariantString(identifier);
- }
+ return converter.ConvertToInvariantString(identifier);
}
}
diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkResourceStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkResourceStore.cs
index 783e52498..afa49a1ff 100644
--- a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkResourceStore.cs
+++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkResourceStore.cs
@@ -210,7 +210,7 @@ public virtual ValueTask> GetDescriptio
if (string.IsNullOrEmpty(resource.Descriptions))
{
- return new(ImmutableDictionary.Create());
+ return new([]);
}
// Note: parsing the stringified descriptions is an expensive operation.
@@ -256,7 +256,7 @@ public virtual ValueTask