From 8feeb8698d31760cafb68ffb8d72262144c5c79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Thu, 25 Jun 2020 02:27:41 +0200 Subject: [PATCH] Update the entire codebase to use IStringLocalizer/ResourceManager --- Directory.Build.props | 1 + Directory.Build.targets | 16 + Directory.Packages.props | 2 + .../Authorization/VerifyViewModel.cs | 2 +- .../Helpers/OpenIddictHelpers.cs | 3 +- .../OpenIddict.Extensions.csproj | 4 + .../Caches/IOpenIddictApplicationCache.cs | 1 - .../Caches/IOpenIddictTokenCache.cs | 1 - .../OpenIddict.Abstractions.csproj | 5 + .../Primitives/OpenIddictConverter.cs | 3 +- .../Primitives/OpenIddictExtensions.cs | 57 +- .../Primitives/OpenIddictMessage.cs | 17 +- .../Primitives/OpenIddictParameter.cs | 11 +- .../Resources/OpenIddictResources.resx | 1432 +++++++++++++++++ .../Stores/IOpenIddictApplicationStore.cs | 4 +- .../Stores/IOpenIddictAuthorizationStore.cs | 2 +- .../Stores/IOpenIddictScopeStore.cs | 4 +- .../Stores/IOpenIddictTokenStore.cs | 2 +- .../Caches/OpenIddictApplicationCache.cs | 17 +- .../Caches/OpenIddictAuthorizationCache.cs | 41 +- .../Caches/OpenIddictScopeCache.cs | 17 +- .../Caches/OpenIddictTokenCache.cs | 37 +- .../Managers/OpenIddictApplicationManager.cs | 83 +- .../OpenIddictAuthorizationManager.cs | 74 +- .../Managers/OpenIddictScopeManager.cs | 36 +- .../Managers/OpenIddictTokenManager.cs | 69 +- src/OpenIddict.Core/OpenIddict.Core.csproj | 1 + src/OpenIddict.Core/OpenIddictCoreBuilder.cs | 51 +- .../OpenIddictCoreExtensions.cs | 19 +- .../OpenIddictApplicationStoreResolver.cs | 19 +- .../OpenIddictAuthorizationStoreResolver.cs | 19 +- .../Resolvers/OpenIddictScopeStoreResolver.cs | 19 +- .../Resolvers/OpenIddictTokenStoreResolver.cs | 19 +- .../OpenIddictEntityFrameworkBuilder.cs | 3 +- ...EntityFrameworkApplicationStoreResolver.cs | 15 +- ...tityFrameworkAuthorizationStoreResolver.cs | 15 +- ...IddictEntityFrameworkScopeStoreResolver.cs | 15 +- ...IddictEntityFrameworkTokenStoreResolver.cs | 15 +- ...enIddictEntityFrameworkApplicationStore.cs | 25 +- ...IddictEntityFrameworkAuthorizationStore.cs | 54 +- .../OpenIddictEntityFrameworkScopeStore.cs | 25 +- .../OpenIddictEntityFrameworkTokenStore.cs | 52 +- .../OpenIddictEntityFrameworkCoreBuilder.cs | 3 +- ...tyFrameworkCoreApplicationStoreResolver.cs | 15 +- ...FrameworkCoreAuthorizationStoreResolver.cs | 15 +- ...ctEntityFrameworkCoreScopeStoreResolver.cs | 15 +- ...ctEntityFrameworkCoreTokenStoreResolver.cs | 15 +- ...dictEntityFrameworkCoreApplicationStore.cs | 25 +- ...ctEntityFrameworkCoreAuthorizationStore.cs | 54 +- ...OpenIddictEntityFrameworkCoreScopeStore.cs | 25 +- ...OpenIddictEntityFrameworkCoreTokenStore.cs | 52 +- .../OpenIddictMongoDbBuilder.cs | 9 +- .../OpenIddictMongoDbContext.cs | 9 +- .../OpenIddictMongoDbOptions.cs | 1 - ...enIddictMongoDbApplicationStoreResolver.cs | 9 +- ...IddictMongoDbAuthorizationStoreResolver.cs | 9 +- .../OpenIddictMongoDbScopeStoreResolver.cs | 9 +- .../OpenIddictMongoDbTokenStoreResolver.cs | 9 +- .../OpenIddictMongoDbApplicationStore.cs | 26 +- .../OpenIddictMongoDbAuthorizationStore.cs | 50 +- .../Stores/OpenIddictMongoDbScopeStore.cs | 26 +- .../Stores/OpenIddictMongoDbTokenStore.cs | 46 +- .../OpenIddictServerAspNetCoreBuilder.cs | 3 +- ...OpenIddictServerAspNetCoreConfiguration.cs | 18 +- .../OpenIddictServerAspNetCoreHandler.cs | 36 +- ...ServerAspNetCoreHandlers.Authentication.cs | 36 +- ...nIddictServerAspNetCoreHandlers.Session.cs | 33 +- .../OpenIddictServerAspNetCoreHandlers.cs | 66 +- .../OpenIddictServerDataProtectionHandlers.cs | 7 +- .../OpenIddictServerOwinBuilder.cs | 3 +- .../OpenIddictServerOwinConfiguration.cs | 7 +- .../OpenIddictServerOwinHandler.cs | 38 +- ...IddictServerOwinHandlers.Authentication.cs | 36 +- .../OpenIddictServerOwinHandlers.Device.cs | 2 +- .../OpenIddictServerOwinHandlers.Session.cs | 33 +- .../OpenIddictServerOwinHandlers.cs | 61 +- .../OpenIddictServerOwinMiddlewareFactory.cs | 17 +- .../OpenIddict.Server.csproj | 1 + .../OpenIddictServerBuilder.cs | 102 +- .../OpenIddictServerConfiguration.cs | 109 +- .../OpenIddictServerDispatcher.cs | 13 +- .../OpenIddictServerEvents.Authentication.cs | 7 +- .../OpenIddictServerEvents.Session.cs | 7 +- .../OpenIddictServerEvents.Userinfo.cs | 2 +- .../OpenIddictServerEvents.cs | 7 +- .../OpenIddictServerExtensions.cs | 19 +- .../OpenIddictServerFactory.cs | 8 +- .../OpenIddictServerHandlerDescriptor.cs | 7 +- ...OpenIddictServerHandlers.Authentication.cs | 169 +- .../OpenIddictServerHandlers.Device.cs | 109 +- .../OpenIddictServerHandlers.Discovery.cs | 23 +- .../OpenIddictServerHandlers.Exchange.cs | 182 +-- .../OpenIddictServerHandlers.Introspection.cs | 90 +- .../OpenIddictServerHandlers.Revocation.cs | 94 +- .../OpenIddictServerHandlers.Session.cs | 37 +- .../OpenIddictServerHandlers.Userinfo.cs | 18 +- .../OpenIddictServerHandlers.cs | 466 ++---- .../OpenIddictServerHelpers.cs | 5 +- .../OpenIddictServerOptions.cs | 7 +- .../OpenIddictServerTransaction.cs | 6 + .../OpenIddictValidationAspNetCoreBuilder.cs | 3 +- ...IddictValidationAspNetCoreConfiguration.cs | 13 +- .../OpenIddictValidationAspNetCoreHandler.cs | 20 +- .../OpenIddictValidationAspNetCoreHandlers.cs | 23 +- ...ctValidationDataProtectionConfiguration.cs | 1 - ...nIddictValidationDataProtectionHandlers.cs | 7 +- .../OpenIddictValidationOwinBuilder.cs | 3 +- .../OpenIddictValidationOwinHandler.cs | 22 +- .../OpenIddictValidationOwinHandlers.cs | 23 +- ...enIddictValidationOwinMiddlewareFactory.cs | 17 +- ...alidationServerIntegrationConfiguration.cs | 14 +- ...tionSystemNetHttpHandlers.Introspection.cs | 5 +- ...enIddictValidationSystemNetHttpHandlers.cs | 13 +- .../OpenIddict.Validation.csproj | 1 + .../OpenIddictValidationBuilder.cs | 41 +- .../OpenIddictValidationConfiguration.cs | 48 +- .../OpenIddictValidationDispatcher.cs | 13 +- .../OpenIddictValidationEvents.cs | 6 + .../OpenIddictValidationExtensions.cs | 18 +- .../OpenIddictValidationFactory.cs | 6 + .../OpenIddictValidationHandlerDescriptor.cs | 7 +- .../OpenIddictValidationHandlers.Discovery.cs | 19 +- ...nIddictValidationHandlers.Introspection.cs | 13 +- .../OpenIddictValidationHandlers.cs | 94 +- .../OpenIddictValidationHelpers.cs | 5 +- .../OpenIddictValidationOptions.cs | 7 +- .../OpenIddictValidationRetriever.cs | 11 +- .../OpenIddictValidationService.cs | 174 +- .../OpenIddictValidationTransaction.cs | 6 + .../Primitives/OpenIddictConverterTests.cs | 3 +- .../Primitives/OpenIddictExtensionsTests.cs | 39 +- .../Primitives/OpenIddictMessageTests.cs | 19 +- .../Primitives/OpenIddictParameterTests.cs | 7 +- .../OpenIddictCoreBuilderTests.cs | 83 +- ...OpenIddictApplicationStoreResolverTests.cs | 10 +- ...enIddictAuthorizationStoreResolverTests.cs | 10 +- .../OpenIddictScopeStoreResolverTests.cs | 10 +- .../OpenIddictTokenStoreResolverTests.cs | 10 +- .../OpenIddictEntityFrameworkBuilderTests.cs | 3 +- ...yFrameworkApplicationStoreResolverTests.cs | 17 +- ...rameworkAuthorizationStoreResolverTests.cs | 15 +- ...tEntityFrameworkScopeStoreResolverTests.cs | 15 +- ...tEntityFrameworkTokenStoreResolverTests.cs | 15 +- ...enIddictEntityFrameworkCoreBuilderTests.cs | 3 +- ...meworkCoreApplicationStoreResolverTests.cs | 17 +- ...workCoreAuthorizationStoreResolverTests.cs | 15 +- ...ityFrameworkCoreScopeStoreResolverTests.cs | 15 +- ...ityFrameworkCoreTokenStoreResolverTests.cs | 15 +- .../OpenIddictMongoDbBuilderTests.cs | 9 +- .../OpenIddictMongoDbContextTests.cs | 9 +- ...ictMongoDbApplicationStoreResolverTests.cs | 11 +- ...tMongoDbAuthorizationStoreResolverTests.cs | 9 +- ...penIddictMongoDbScopeStoreResolverTests.cs | 9 +- ...penIddictMongoDbTokenStoreResolverTests.cs | 9 +- ...pNetCoreIntegrationTests.Authentication.cs | 5 +- ...rverAspNetCoreIntegrationTests.Exchange.cs | 3 +- ...spNetCoreIntegrationTests.Introspection.cs | 3 +- ...erAspNetCoreIntegrationTests.Revocation.cs | 3 +- ...erverAspNetCoreIntegrationTests.Session.cs | 5 +- ...nIddictServerAspNetCoreIntegrationTests.cs | 3 +- .../OpenIddictServerIntegrationTestClient.cs | 2 +- ...ctServerIntegrationTests.Authentication.cs | 104 +- ...nIddictServerIntegrationTests.Discovery.cs | 3 +- ...enIddictServerIntegrationTests.Exchange.cs | 112 +- ...ictServerIntegrationTests.Introspection.cs | 37 +- ...IddictServerIntegrationTests.Revocation.cs | 29 +- ...penIddictServerIntegrationTests.Session.cs | 19 +- ...enIddictServerIntegrationTests.Userinfo.cs | 7 +- .../OpenIddictServerIntegrationTests.cs | 92 +- ...rverOwinIntegrationTests.Authentication.cs | 5 +- ...dictServerOwinIntegrationTests.Exchange.cs | 3 +- ...erverOwinIntegrationTests.Introspection.cs | 3 +- ...ctServerOwinIntegrationTests.Revocation.cs | 3 +- ...ddictServerOwinIntegrationTests.Session.cs | 5 +- .../OpenIddictServerOwinIntegrationTests.cs | 3 +- .../OpenIddictServerBuilderTests.cs | 8 +- 176 files changed, 3216 insertions(+), 2864 deletions(-) create mode 100644 src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx diff --git a/Directory.Build.props b/Directory.Build.props index 678ea10d..31704373 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,6 +9,7 @@ true $(MSBuildThisFileDirectory)eng\CodeAnalysis.ruleset true + false diff --git a/Directory.Build.targets b/Directory.Build.targets index ed7b2568..5b4bcf0d 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -73,5 +73,21 @@ + + + + + + diff --git a/Directory.Packages.props b/Directory.Packages.props index a15cf074..b5579558 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -42,6 +42,7 @@ + @@ -63,6 +64,7 @@ + diff --git a/samples/Mvc.Server/ViewModels/Authorization/VerifyViewModel.cs b/samples/Mvc.Server/ViewModels/Authorization/VerifyViewModel.cs index baedb0d0..0a48a0e6 100644 --- a/samples/Mvc.Server/ViewModels/Authorization/VerifyViewModel.cs +++ b/samples/Mvc.Server/ViewModels/Authorization/VerifyViewModel.cs @@ -12,7 +12,7 @@ namespace Mvc.Server.ViewModels.Authorization [BindNever, Display(Name = "Error")] public string Error { get; set; } - + [BindNever, Display(Name = "Error description")] public string ErrorDescription { get; set; } diff --git a/shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs b/shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs index 4383668d..d653d38d 100644 --- a/shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs +++ b/shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Extensions { @@ -38,7 +39,7 @@ namespace OpenIddict.Extensions if (!definition.IsGenericTypeDefinition) { - throw new ArgumentException("The second parameter must be a generic type definition.", nameof(definition)); + throw new ArgumentException(SR.GetResourceString(SR.ID1262), nameof(definition)); } if (definition.IsInterface) diff --git a/shared/OpenIddict.Extensions/OpenIddict.Extensions.csproj b/shared/OpenIddict.Extensions/OpenIddict.Extensions.csproj index e57111d9..da0a368f 100644 --- a/shared/OpenIddict.Extensions/OpenIddict.Extensions.csproj +++ b/shared/OpenIddict.Extensions/OpenIddict.Extensions.csproj @@ -5,4 +5,8 @@ false + + + + diff --git a/src/OpenIddict.Abstractions/Caches/IOpenIddictApplicationCache.cs b/src/OpenIddict.Abstractions/Caches/IOpenIddictApplicationCache.cs index 9d354295..3e7961cf 100644 --- a/src/OpenIddict.Abstractions/Caches/IOpenIddictApplicationCache.cs +++ b/src/OpenIddict.Abstractions/Caches/IOpenIddictApplicationCache.cs @@ -5,7 +5,6 @@ */ using System.Collections.Generic; -using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; diff --git a/src/OpenIddict.Abstractions/Caches/IOpenIddictTokenCache.cs b/src/OpenIddict.Abstractions/Caches/IOpenIddictTokenCache.cs index 0c87e302..78a6a81d 100644 --- a/src/OpenIddict.Abstractions/Caches/IOpenIddictTokenCache.cs +++ b/src/OpenIddict.Abstractions/Caches/IOpenIddictTokenCache.cs @@ -5,7 +5,6 @@ */ using System.Collections.Generic; -using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; diff --git a/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj b/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj index 329c7248..e2caceb8 100644 --- a/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj +++ b/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj @@ -2,6 +2,7 @@ net461;netstandard2.0;netstandard2.1 + true @@ -29,4 +30,8 @@ + + + + diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictConverter.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictConverter.cs index 132b63e0..435337b7 100644 --- a/src/OpenIddict.Abstractions/Primitives/OpenIddictConverter.cs +++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictConverter.cs @@ -8,6 +8,7 @@ using System; using System.Text.Json; using System.Text.Json.Serialization; using JetBrains.Annotations; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Abstractions { @@ -52,7 +53,7 @@ namespace OpenIddict.Abstractions return typeToConvert == typeof(OpenIddictMessage) ? new OpenIddictMessage(document.RootElement.Clone()) : typeToConvert == typeof(OpenIddictRequest) ? new OpenIddictRequest(document.RootElement.Clone()) : typeToConvert == typeof(OpenIddictResponse) ? (OpenIddictMessage) new OpenIddictResponse(document.RootElement.Clone()) : - throw new ArgumentException("The specified type is not supported.", nameof(typeToConvert)); + throw new ArgumentException(SR.GetResourceString(SR.ID1175), nameof(typeToConvert)); } /// diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs index a72e24a0..6abc9c88 100644 --- a/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs +++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs @@ -16,6 +16,7 @@ using System.Text.Json; using JetBrains.Annotations; using Microsoft.Extensions.Primitives; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Abstractions { @@ -115,7 +116,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(value)) { - throw new ArgumentException("The value cannot be null or empty.", nameof(value)); + throw new ArgumentException(SR.GetResourceString(SR.ID1176), nameof(value)); } return HasValue(request.AcrValues, value, Separators.Space); @@ -135,7 +136,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(prompt)) { - throw new ArgumentException("The prompt cannot be null or empty.", nameof(prompt)); + throw new ArgumentException(SR.GetResourceString(SR.ID1177), nameof(prompt)); } return HasValue(request.Prompt, prompt, Separators.Space); @@ -155,7 +156,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The response type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1178), nameof(type)); } return HasValue(request.ResponseType, type, Separators.Space); @@ -175,7 +176,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(scope)) { - throw new ArgumentException("The scope cannot be null or empty.", nameof(scope)); + throw new ArgumentException(SR.GetResourceString(SR.ID1179), nameof(scope)); } return HasValue(request.Scope, scope, Separators.Space); @@ -556,7 +557,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(destination)) { - throw new ArgumentException("The destination cannot be null or empty.", nameof(destination)); + throw new ArgumentException(SR.GetResourceString(SR.ID1180), nameof(destination)); } claim.Properties.TryGetValue(Properties.Destinations, out string destinations); @@ -591,7 +592,7 @@ namespace OpenIddict.Abstractions if (destinations.Any(destination => string.IsNullOrEmpty(destination))) { - throw new ArgumentException("Destinations cannot be null or empty.", nameof(destinations)); + throw new ArgumentException(SR.GetResourceString(SR.ID1181), nameof(destinations)); } claim.Properties[Properties.Destinations] = @@ -646,7 +647,7 @@ namespace OpenIddict.Abstractions { if (!destinations.SetEquals(claims[index].GetDestinations())) { - throw new InvalidOperationException($"Conflicting destinations for the claim '{group.Key}' were specified."); + throw new InvalidOperationException(SR.FormatID1182(group.Key)); } } @@ -779,12 +780,12 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } if (string.IsNullOrEmpty(value)) { - throw new ArgumentException("The claim value cannot be null or empty.", nameof(value)); + throw new ArgumentException(SR.GetResourceString(SR.ID1184), nameof(value)); } identity.AddClaim(new Claim(type, value)); @@ -810,12 +811,12 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } if (string.IsNullOrEmpty(value)) { - throw new ArgumentException("The claim value cannot be null or empty.", nameof(value)); + throw new ArgumentException(SR.GetResourceString(SR.ID1184), nameof(value)); } if (destinations == null) @@ -855,7 +856,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } return identity.FindFirst(type)?.Value; @@ -876,7 +877,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } return principal.FindFirst(type)?.Value; @@ -897,7 +898,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } return identity.FindAll(type).Select(claim => claim.Value).Distinct(StringComparer.Ordinal).ToImmutableArray(); @@ -918,7 +919,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } return identity.FindAll(type).Any(); @@ -939,7 +940,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } return principal.FindAll(type).Select(claim => claim.Value).Distinct(StringComparer.Ordinal).ToImmutableArray(); @@ -960,7 +961,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } return principal.FindAll(type).Any(); @@ -981,7 +982,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } foreach (var claim in identity.FindAll(type).ToList()) @@ -1007,7 +1008,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } foreach (var identity in principal.Identities) @@ -1039,7 +1040,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } identity.RemoveClaims(type); @@ -1070,7 +1071,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } principal.RemoveClaims(type); @@ -1100,7 +1101,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } identity.RemoveClaims(type); @@ -1130,7 +1131,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The claim type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1183), nameof(type)); } principal.RemoveClaims(type); @@ -1322,7 +1323,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(audience)) { - throw new ArgumentException("The audience cannot be null or empty.", nameof(audience)); + throw new ArgumentException(SR.GetResourceString(SR.ID1185), nameof(audience)); } return principal.HasClaim(Claims.Private.Audience, audience); @@ -1351,7 +1352,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(presenter)) { - throw new ArgumentException("The presenter cannot be null or empty.", nameof(presenter)); + throw new ArgumentException(SR.GetResourceString(SR.ID1186), nameof(presenter)); } return principal.HasClaim(Claims.Private.Presenter, presenter); @@ -1380,7 +1381,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(resource)) { - throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); + throw new ArgumentException(SR.GetResourceString(SR.ID1061), nameof(resource)); } return principal.HasClaim(Claims.Private.Resource, resource); @@ -1409,7 +1410,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(scope)) { - throw new ArgumentException("The scope cannot be null or empty.", nameof(scope)); + throw new ArgumentException(SR.GetResourceString(SR.ID1179), nameof(scope)); } return principal.HasClaim(Claims.Private.Scope, scope); @@ -1430,7 +1431,7 @@ namespace OpenIddict.Abstractions if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The token type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1187), nameof(type)); } return string.Equals(principal.GetTokenType(), type, StringComparison.OrdinalIgnoreCase); diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs index 98b2749f..fe48907c 100644 --- a/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs +++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs @@ -16,6 +16,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using JetBrains.Annotations; using Microsoft.Extensions.Primitives; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Abstractions { @@ -46,7 +47,7 @@ namespace OpenIddict.Abstractions { if (parameters.ValueKind != JsonValueKind.Object) { - throw new ArgumentException("The specified JSON element is not an object.", nameof(parameters)); + throw new ArgumentException(SR.GetResourceString(SR.ID1188), nameof(parameters)); } foreach (var parameter in parameters.EnumerateObject()) @@ -192,12 +193,12 @@ namespace OpenIddict.Abstractions { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The parameter name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1189), nameof(name)); } if (Parameters.ContainsKey(name)) { - throw new ArgumentException("A parameter with the same name already exists.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1190), nameof(name)); } Parameters.Add(name, value); @@ -214,7 +215,7 @@ namespace OpenIddict.Abstractions { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The parameter name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1189), nameof(name)); } if (Parameters.TryGetValue(name, out OpenIddictParameter value)) @@ -241,7 +242,7 @@ namespace OpenIddict.Abstractions { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The parameter name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1189), nameof(name)); } return Parameters.ContainsKey(name); @@ -256,7 +257,7 @@ namespace OpenIddict.Abstractions { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The parameter name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1189), nameof(name)); } Parameters.Remove(name); @@ -275,7 +276,7 @@ namespace OpenIddict.Abstractions { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The parameter name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1189), nameof(name)); } // If the parameter value is null or empty, remove the corresponding entry from the collection. @@ -302,7 +303,7 @@ namespace OpenIddict.Abstractions { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The parameter name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1189), nameof(name)); } return Parameters.TryGetValue(name, out value); diff --git a/src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs b/src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs index 7f976d25..88cee68f 100644 --- a/src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs +++ b/src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs @@ -13,6 +13,7 @@ using System.Linq; using System.Text.Encodings.Web; using System.Text.Json; using JetBrains.Annotations; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Abstractions { @@ -199,7 +200,7 @@ namespace OpenIddict.Abstractions { return false; } - + if (!Equals(property.Value, element)) { return false; @@ -298,7 +299,7 @@ namespace OpenIddict.Abstractions { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The item name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1191), nameof(name)); } if (Value is JsonElement element && element.ValueKind == JsonValueKind.Object) @@ -324,7 +325,7 @@ namespace OpenIddict.Abstractions { if (index < 0) { - throw new ArgumentOutOfRangeException(nameof(index), "The item index cannot be negative."); + throw new ArgumentOutOfRangeException(nameof(index), SR.GetResourceString(SR.ID1192)); } if (Value is string[] array) @@ -437,7 +438,7 @@ namespace OpenIddict.Abstractions { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The parameter name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1189), nameof(name)); } if (Value is JsonElement element && element.ValueKind == JsonValueKind.Object && @@ -499,7 +500,7 @@ namespace OpenIddict.Abstractions value.WriteTo(writer); break; - default: throw new InvalidOperationException("The type of the parameter value is not supported."); + default: throw new InvalidOperationException(SR.GetResourceString(SR.ID1193)); } } diff --git a/src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx b/src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx new file mode 100644 index 00000000..79dad147 --- /dev/null +++ b/src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx @@ -0,0 +1,1432 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + An identity cannot be extracted from this token request. +This generally indicates that the OpenIddict server stack was asked to validate a token for an invalid grant type (e.g password). + + + An identity cannot be extracted from this request. +This generally indicates that the OpenIddict server stack was asked to validate a token for an endpoint it doesn't manage. +To validate tokens received by custom API endpoints, the OpenIddict validation services must be used instead. + + + The token type is not supported. + + + The deserialized principal doesn't contain the mandatory 'oi_tkn_typ' claim. +When implementing custom token deserialization, a 'oi_tkn_typ' claim containing the type of the token being processed must be added to the security principal. + + + The type of token associated with the deserialized principal ({0}) doesn't match the expected token type ({1}). + + + A challenge response cannot be returned from this endpoint. + + + The authentication context cannot be found. + + + The device code identifier cannot be extracted from the principal. + + + The token identifier cannot be extracted from the principal. + + + A sign-in response cannot be returned from this endpoint. + + + The specified principal doesn't contain any claims-based identity. +Make sure that 'ClaimsPrincipal.Identity' is not null. + + + The specified principal contains an authenticated identity, which is not valid when the sign-in operation is triggered from the device authorization endpoint. +Make sure that 'ClaimsPrincipal.Identity.AuthenticationType' is null and that 'ClaimsPrincipal.Identity.IsAuthenticated' returns 'false'. + + + The specified principal contains a subject claim, which is not valid when the sign-in operation is triggered from the device authorization endpoint. + + + The specified principal doesn't contain a valid/authenticated identity. +Make sure that 'ClaimsPrincipal.Identity.AuthenticationType' is not null and that 'ClaimsPrincipal.Identity.IsAuthenticated' returns 'true'. + + + The specified principal was rejected because the mandatory subject claim was missing. + + + The core services must be registered when enabling the OpenIddict server feature. +To register the OpenIddict core services, reference the 'OpenIddict.Core' package and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'. +Alternatively, you can disable the built-in database-based server features by enabling the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'. + + + The application entry cannot be found in the database. + + + An unknown error occurred while creating an authorization entry. + + + An unknown error occurred while creating a token entry. + + + A token entry cannot be created from a null principal. + + + The token entry cannot be found in the database. + + + A token cannot be created from a null principal. + + + The issuer must be a non-null, non-empty absolute URL. + + + A sign-out response cannot be returned from this endpoint. + + + The token type cannot be resolved. + + + The payload associated with a reference token cannot be retrieved. +This may indicate that the token entry was corrupted. + + + The authorization request was not correctly extracted. +To extract authorization requests, create a class implementing 'IOpenIddictServerHandler<ExtractAuthorizationRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The request cannot be validated because no redirect_uri was specified. + + + The authorization request was not handled. +To handle authorization requests in a controller, create a custom action with the same route as the authorization endpoint and enable the pass-through mode in the server ASP.NET Core or OWIN options using 'services.AddOpenIddict().AddServer().UseAspNetCore().EnableAuthorizationEndpointPassthrough()'. +Alternatively, create a class implementing 'IOpenIddictServerHandler<HandleAuthorizationRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The authorization response was not correctly applied. +To apply authorization responses, create a class implementing 'IOpenIddictServerHandler<ApplyAuthorizationResponseContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The device request was not correctly extracted. +To extract device requests, create a class implementing 'IOpenIddictServerHandler<ExtractDeviceRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The client application details cannot be found in the database. + + + The device response was not correctly applied. +To apply device responses, create a class implementing 'IOpenIddictServerHandler<ApplyDeviceResponseContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The verification request was not correctly extracted. +To extract verification requests, create a class implementing 'IOpenIddictServerHandler<ExtractVerificationRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The verification request was not handled. +To handle verification requests in a controller, create a custom action with the same route as the verification endpoint and enable the pass-through mode in the server ASP.NET Core or OWIN options using 'services.AddOpenIddict().AddServer().UseAspNetCore().EnableVerificationEndpointPassthrough()'. +Alternatively, create a class implementing 'IOpenIddictServerHandler<HandleVerificationRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The verification response was not correctly applied. +To apply verification responses, create a class implementing 'IOpenIddictServerHandler<ApplyVerificationResponseContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The configuration request was not correctly extracted. +To extract configuration requests, create a class implementing 'IOpenIddictServerHandler<ExtractConfigurationRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The cryptography request was not correctly extracted. +To extract configuration requests, create a class implementing 'IOpenIddictServerHandler<ExtractCryptographyRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The cryptography response was not correctly applied. +To apply cryptography responses, create a class implementing 'IOpenIddictServerHandler<ApplyCryptographyResponseContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The token request was not correctly extracted. +To extract token requests, create a class implementing 'IOpenIddictServerHandler<ExtractTokenRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The token request was not handled. +To handle token requests in a controller, create a custom action with the same route as the token endpoint and enable the pass-through mode in the server ASP.NET Core or OWIN options using 'services.AddOpenIddict().AddServer().UseAspNetCore().EnableTokenEndpointPassthrough()'. +Alternatively, create a class implementing 'IOpenIddictServerHandler<HandleTokenRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The token response was not correctly applied. +To apply token responses, create a class implementing 'IOpenIddictServerHandler<ApplyTokenResponseContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The presenters list cannot be extracted from the authorization code. + + + The presenters list cannot be extracted from the device code. + + + The specified code challenge method is not supported. + + + The introspection request was not correctly extracted. +To extract introspection requests, create a class implementing 'IOpenIddictServerHandler<ExtractIntrospectionRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The introspection response was not correctly applied. +To apply introspection responses, create a class implementing 'IOpenIddictServerHandler<ApplyIntrospectionResponseContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The revocation request was not correctly extracted. +To extract revocation requests, create a class implementing 'IOpenIddictServerHandler<ExtractRevocationRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The revocation response was not correctly applied. +To apply revocation responses, create a class implementing 'IOpenIddictServerHandler<ApplyRevocationResponseContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The logout request was not correctly extracted. +To extract logout requests, create a class implementing 'IOpenIddictServerHandler<ExtractLogoutRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The logout request was not handled. +To handle logout requests in a controller, create a custom controller action with the same route as the logout endpoint and enable the pass-through mode in the server ASP.NET Core or OWIN options using 'services.AddOpenIddict().AddServer().UseAspNetCore().EnableLogoutEndpointPassthrough()'. +Alternatively, create a class implementing 'IOpenIddictServerHandler<HandleLogoutRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The logout response was not correctly applied. +To apply logout responses, create a class implementing 'IOpenIddictServerHandler<ApplyLogoutResponseContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The userinfo request was not correctly extracted. +To extract userinfo requests, create a class implementing 'IOpenIddictServerHandler<ExtractUserinfoRequestContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The userinfo response was not correctly applied. +To apply userinfo responses, create a class implementing 'IOpenIddictServerHandler<ApplyUserinfoResponseContext>' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The asymmetric encryption key doesn't contain the required private key. + + + An encryption algorithm cannot be automatically inferred from the encrypting key. +Consider using 'options.AddEncryptionCredentials(EncryptingCredentials)' instead. + + + The algorithm cannot be null or empty. + + + The specified algorithm is not supported. + + + RSA key generation failed. + + + The specified certificate is not a key encryption certificate. + + + The specified certificate doesn't contain the required private key. + + + The resource cannot be null or empty. + + + The password cannot be null or empty. + + + The certificate was not found in the specified assembly. + + + The thumbprint cannot be null or empty. + + + The certificate corresponding to the specified thumbprint was not found. + + + The asymmetric signing key doesn't contain the required private key. + + + A signature algorithm cannot be automatically inferred from the signing key. +Consider using 'options.AddSigningCredentials(SigningCredentials)' instead. + + + ECDSA signing keys are not supported on this platform. + + + The specified certificate is not a signing certificate. + + + The grant type cannot be null or empty. + + + One of the specified addresses is not valid. + + + Claims cannot be null or empty. + + + Scopes cannot be null or empty. + + + The security token handler cannot be null. + + + At least one OAuth 2.0/OpenID Connect flow must be enabled. + + + The authorization endpoint must be enabled to use the authorization code and implicit flows. + + + The device endpoint must be enabled to use the device flow. + + + The token endpoint must be enabled to use the authorization code, client credentials, device, password and refresh token flows. + + + The verification endpoint must be enabled to use the device flow. + + + The device and verification endpoints cannot be enabled when token storage is disabled. + + + The revocation endpoint cannot be enabled when token storage is disabled. + + + Reference tokens cannot be used when disabling token storage. + + + Sliding expiration must be disabled when turning off token storage if rolling tokens are not used. + + + At least one encryption key must be registered in the OpenIddict server options. +Consider registering a certificate using 'services.AddOpenIddict().AddServer().AddEncryptionCertificate()' or 'services.AddOpenIddict().AddServer().AddDevelopmentEncryptionCertificate()' or call 'services.AddOpenIddict().AddServer().AddEphemeralEncryptionKey()' to use an ephemeral key. + + + At least one asymmetric signing key must be registered in the OpenIddict server options. +Consider registering a certificate using 'services.AddOpenIddict().AddServer().AddSigningCertificate()' or 'services.AddOpenIddict().AddServer().AddDevelopmentSigningCertificate()' or call 'services.AddOpenIddict().AddServer().AddEphemeralSigningKey()' to use an ephemeral key. + + + When using X.509 encryption credentials, at least one of the registered certificates must be valid. +To use key rollover, register both the new certificate and the old one in the credentials collection. + + + When using X.509 signing credentials, at least one of the registered certificates must be valid. +To use key rollover, register both the new certificate and the old one in the credentials collection. + + + No custom authorization request validation handler was found. When enabling the degraded mode, a custom 'IOpenIddictServerHandler<ValidateAuthorizationRequestContext>' must be implemented to validate authorization requests (e.g to ensure the client_id and redirect_uri are valid). + + + No custom device request validation handler was found. When enabling the degraded mode, a custom 'IOpenIddictServerHandler<ValidateDeviceRequestContext>' must be implemented to validate device requests (e.g to ensure the client_id and client_secret are valid). + + + No custom introspection request validation handler was found. When enabling the degraded mode, a custom 'IOpenIddictServerHandler<ValidateIntrospectionRequestContext>' must be implemented to validate introspection requests (e.g to ensure the client_id and client_secret are valid). + + + No custom logout request validation handler was found. When enabling the degraded mode, a custom 'IOpenIddictServerHandler<ValidateLogoutRequestContext>' must be implemented to validate logout requests (e.g to ensure the post_logout_redirect_uri is valid). + + + No custom revocation request validation handler was found. When enabling the degraded mode, a custom 'IOpenIddictServerHandler<ValidateRevocationRequestContext>' must be implemented to validate revocation requests (e.g to ensure the client_id and client_secret are valid). + + + No custom token request validation handler was found. When enabling the degraded mode, a custom 'IOpenIddictServerHandler<ValidateTokenRequestContext>' must be implemented to validate token requests (e.g to ensure the client_id and client_secret are valid). + + + No custom verification request validation handler was found. When enabling the degraded mode, a custom 'IOpenIddictServerHandler<ValidateVerificationRequestContext>' must be implemented to validate verification requests (e.g to ensure the user_code is valid). + + + No custom verification authentication handler was found. When enabling the degraded mode, a custom 'IOpenIddictServerHandler<ProcessAuthenticationContext>' must be implemented to validate device and user codes (e.g by retrieving them from a database). + + + No custom verification sign-in handler was found. When enabling the degraded mode, a custom 'IOpenIddictServerHandler<ProcessSignInContext>' must be implemented to generate device and user codes and storing them in a database, if applicable. + + + The event handler of type '{0}' couldn't be resolved. +This may indicate that it was not properly registered in the dependency injection container. To register an event handler, use 'services.AddOpenIddict().AddServer().AddEventHandler()'. + + + The event handler filter of type '{0}' couldn't be resolved. +This may indicate that it was not properly registered in the dependency injection container. + + + The redirect_uri cannot be null or empty. + + + The authorization request cannot be validated because a different redirect_uri was specified by the client application. + + + The post_logout_redirect_uri cannot be null or empty. + + + The end session request cannot be validated because a different post_logout_redirect_uri was specified by the client application. + + + The specified service type is not valid. + + + No service descriptor was set. + + + The property name cannot be null or empty. + + + The realm cannot be null or empty. + + + The OpenIddict ASP.NET Core server handler cannot be registered as an authentication scheme. +This may indicate that an instance of another handler was registered with the same scheme. + + + The OpenIddict ASP.NET Core server cannot be used as the default scheme handler. +Make sure that neither DefaultAuthenticateScheme, DefaultChallengeScheme, DefaultForbidScheme, DefaultSignInScheme, DefaultSignOutScheme nor DefaultScheme point to an instance of the OpenIddict ASP.NET Core server handler. + + + The error pass-through mode cannot be used when the status code pages integration is enabled. + + + The OpenID Connect response was not correctly processed. +This may indicate that the event handler responsible of processing OpenID Connect responses was not registered or was explicitly removed from the handlers list. + + + An unknown error occurred while retrieving the OpenIddict server context. + + + An error occurred while authenticating the current request. + + + The ASP.NET Core HTTP request cannot be resolved. + + + Only strings, booleans, integers, arrays of strings and instances of type 'OpenIddictParameter' or 'JsonElement' can be returned as custom parameters. + + + A distributed cache instance must be registered when enabling request caching. +To register the default in-memory distributed cache implementation, reference the 'Microsoft.Extensions.Caching.Memory' package and call 'services.AddDistributedMemoryCache()' from 'ConfigureServices'. + + + The authorization request payload is malformed. + + + The logout request payload is malformed. + + + The OpenIddict OWIN server handler cannot be used as an active authentication handler. +Make sure that 'OpenIddictServerOwinOptions.AuthenticationMode' is not set to 'Active'. + + + The OWIN request cannot be resolved. + + + No service provider was found in the OWIN context. +For the OpenIddict server services to work correctly, a per-request 'IServiceProvider' must be attached to the OWIN environment with the dictionary key 'System.IServiceProvider'. +Note: when using a dependency injection container supporting middleware resolution (like Autofac), the 'app.UseOpenIddictServer()' extension MUST NOT be called. + + + The OpenIddict server services cannot be resolved from the DI container. +To register the server services, use 'services.AddOpenIddict().AddServer()'. + + + Audiences cannot be null or empty. + + + The client identifier cannot be null or empty. + + + The client secret cannot be null or empty. + + + The issuer cannot be null or empty. + + + The issuer must be a valid absolute URL. + + + An OAuth 2.0/OpenID Connect server configuration or an issuer address must be registered. +To use a local OpenIddict server, reference the 'OpenIddict.Validation.ServerIntegration' package and call 'services.AddOpenIddict().AddValidation().UseLocalServer()' to import the server settings. +To use a remote server, reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' and 'services.AddOpenIddict().AddValidation().SetIssuer()' to use server discovery. +Alternatively, you can register a static server configuration by calling 'services.AddOpenIddict().AddValidation().SetConfiguration()'. + + + An introspection client must be registered when using introspection. +Reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' to register the default System.Net.Http-based integration. + + + The issuer or the metadata address must be set when using introspection. + + + The client identifier cannot be null or empty when using introspection. + + + The client secret cannot be null or empty when using introspection. + + + Authorization validation cannot be enabled when using introspection. + + + Token validation cannot be enabled when using introspection. + + + A discovery client must be registered when using server discovery. +Reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' to register the default System.Net.Http-based integration. + + + The authority must be provided and must be an absolute URL. + + + The authority cannot contain a fragment or a query string. + + + The event handler of type '{0}' couldn't be resolved. +This may indicate that it was not properly registered in the dependency injection container. To register an event handler, use 'services.AddOpenIddict().AddValidation().AddEventHandler()'. + + + The core services must be registered when enabling token entry validation. +To register the OpenIddict core services, reference the 'OpenIddict.Core' package and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'. + + + An unknown error occurred while retrieving the server configuration. + + + An unknown error occurred while introspecting the access token. + + + The core services must be registered when enabling authorization entry validation. +To register the OpenIddict core services, reference the 'OpenIddict.Core' package and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'. + + + The address cannot be null or empty. + + + The address must be a valid absolute URI. + + + The server configuration couldn't be retrieved. + + + The JWKS URI couldn't be resolved from the provider metadata. + + + The server JSON Web Key set couldn't be retrieved. + + + An error occurred while preparing the configuration request. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while sending the configuration request. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while extracting the configuration response. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while handling the configuration response. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while preparing the cryptography request. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while sending the cryptography request. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while extracting the cryptography response. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while handling the cryptography response. + Error: {0} + Error description: {1} + Error URI: {2} + + + The token cannot be null or empty. + + + An unknown error occurred while introspecting the token. + + + An error occurred while preparing the introspection request. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while sending the introspection request. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while extracting the introspection response. + Error: {0} + Error description: {1} + Error URI: {2} + + + An error occurred while handling the introspection response. + Error: {0} + Error description: {1} + Error URI: {2} + + + The access token cannot be null or empty. + + + An error occurred while validating the access token. + Error: {0} + Error description: {1} + Error URI: {2} + + + The OpenIddict ASP.NET Core validation handler cannot be registered as an authentication scheme. +This may indicate that an instance of another handler was registered with the same scheme. + + + The OpenIddict ASP.NET Core validation cannot be used as the default sign-in/sign-out handler. +Make sure that neither DefaultSignInScheme nor DefaultSignOutScheme point to an instance of the OpenIddict ASP.NET Core validation handler. + + + An unknown error occurred while retrieving the OpenIddict validation context. + + + Generic token validation is not supported by the validation handler. + + + No service provider was found in the OWIN context. +For the OpenIddict validation services to work correctly, a per-request 'IServiceProvider' must be attached to the OWIN environment with the dictionary key 'System.IServiceProvider'. +Note: when using a dependency injection container supporting middleware resolution (like Autofac), the 'app.UseOpenIddictValidation()' extension MUST NOT be called. + + + The OpenIddict validation services cannot be resolved from the DI container. +To register the validation services, use 'services.AddOpenIddict().AddValidation()'. + + + The local server integration can only be used with direct validation. + + + Authorization entry validation cannot be enabled when authorization storage is disabled in the OpenIddict server options. + + + Token entry validation cannot be enabled when token storage is disabled in the OpenIddict server options. + + + The System.Net.Http request cannot be resolved. + + + An unknown error occurred while creating a System.Net.Http client. + + + An unknown error occurred while sending a System.Net.Http request. + + + The specified type is not supported. + + + The value cannot be null or empty. + + + The prompt cannot be null or empty. + + + The response type cannot be null or empty. + + + The scope cannot be null or empty. + + + The destination cannot be null or empty. + + + Destinations cannot be null or empty. + + + Conflicting destinations for the claim '{0}' were specified. + + + The claim type cannot be null or empty. + + + The claim value cannot be null or empty. + + + The audience cannot be null or empty. + + + The presenter cannot be null or empty. + + + The token type cannot be null or empty. + + + The specified JSON element is not an object. + + + The parameter name cannot be null or empty. + + + A parameter with the same name already exists. + + + The item name cannot be null or empty. + + + The item index cannot be negative. + + + The type of the parameter value is not supported. + + + The identifier cannot be null or empty. + + + The application identifier cannot be extracted. + + + An error occurred while creating an expiration signal. + + + The subject cannot be null or empty. + + + The status cannot be null or empty. + + + The type cannot be null or empty. + + + The authorization identifier cannot be extracted. + + + The scope name cannot be null or empty. + + + Scope names cannot be null or empty. + + + The scope identifier cannot be extracted. + + + The token identifier cannot be extracted. + + + The client secret hash cannot be set on the application entity. + + + One or more validation error(s) occurred while trying to create a new application: + + + An error occurred while trying to create a new application. + + + The client type cannot be null or empty. + + + The consent type cannot be null or empty. + + + The permission name cannot be null or empty. + + + The requirement name cannot be null or empty. + + + Callback URLs cannot be null or empty. + + + Callback URLs must be valid absolute URLs. + + + One or more validation error(s) occurred while trying to update an existing application: + + + The secret cannot be null or empty. + + + The specified hash algorithm is not valid. + + + The comparand cannot be null or empty. + + + One or more validation error(s) occurred while trying to create a new authorization: + + + An error occurred while trying to create a new authorization. + + + One or more validation error(s) occurred while trying to update an existing authorization: + + + One or more validation error(s) occurred while trying to create a new scope: + + + An error occurred while trying to create a new scope. + + + One or more validation error(s) occurred while trying to update an existing scope: + + + One or more validation error(s) occurred while trying to create a new token: + + + An error occurred while trying to create a new token + + + One or more validation error(s) occurred while trying to update an existing token: + + + No application store has been registered in the dependency injection container. +To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'. +To register a custom store, create an implementation of 'IOpenIddictApplicationStore' and use 'services.AddOpenIddict().AddCore().AddApplicationStore()' to add it to the DI container. + + + No authorization store has been registered in the dependency injection container. +To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'. +To register a custom store, create an implementation of 'IOpenIddictAuthorizationStore' and use 'services.AddOpenIddict().AddCore().AddAuthorizationStore()' to add it to the DI container. + + + No scope store has been registered in the dependency injection container. +To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'. +To register a custom store, create an implementation of 'IOpenIddictScopeStore' and use 'services.AddOpenIddict().AddCore().AddScopeStore()' to add it to the DI container. + + + No token store has been registered in the dependency injection container. +To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'. +To register a custom store, create an implementation of 'IOpenIddictTokenStore' and use 'services.AddOpenIddict().AddCore().AddTokenStore()' to add it to the DI container. + + + The specified type is invalid. + + + The cache size cannot be less than 10. + + + The specified application type is not compatible with the Entity Framework 6.x stores. +When enabling the Entity Framework 6.x stores, make sure you use the built-in 'OpenIddictEntityFrameworkApplication' entity or a custom entity that inherits from the generic 'OpenIddictEntityFrameworkApplication' entity. + + + No Entity Framework 6.x context was specified in the OpenIddict options. +To configure the OpenIddict Entity Framework 6.x stores to use a specific 'DbContext', use 'options.UseEntityFramework().UseDbContext<TContext>()'. + + + The specified authorization type is not compatible with the Entity Framework 6.x stores. +When enabling the Entity Framework 6.x stores, make sure you use the built-in 'OpenIddictEntityFrameworkAuthorization' entity or a custom entity that inherits from the generic 'OpenIddictEntityFrameworkAuthorization' entity. + + + The specified scope type is not compatible with the Entity Framework 6.x stores. +When enabling the Entity Framework 6.x stores, make sure you use the built-in 'OpenIddictEntityFrameworkScope' entity or a custom entity that inherits from the generic 'OpenIddictEntityFrameworkScope' entity. + + + The specified token type is not compatible with the Entity Framework 6.x stores. +When enabling the Entity Framework 6.x stores, make sure you use the built-in 'OpenIddictEntityFrameworkToken' entity or a custom entity that inherits from the generic 'OpenIddictEntityFrameworkToken' entity. + + + The application was concurrently updated and cannot be persisted in its current state. +Reload the application from the database and retry the operation. + + + An error occurred while trying to create a new application instance. +Make sure that the application entity is not abstract and has a public parameterless constructor or create a custom application store that overrides 'InstantiateAsync()' to use a custom factory. + + + The authorization was concurrently updated and cannot be persisted in its current state. +Reload the authorization from the database and retry the operation. + + + An error occurred while trying to create a new authorization instance. +Make sure that the authorization entity is not abstract and has a public parameterless constructor or create a custom authorization store that overrides 'InstantiateAsync()' to use a custom factory. + + + An error occurred while pruning authorizations. + + + The application associated with the authorization cannot be found. + + + The scope was concurrently updated and cannot be persisted in its current state. +Reload the scope from the database and retry the operation. + + + An error occurred while trying to create a new scope instance. +Make sure that the scope entity is not abstract and has a public parameterless constructor or create a custom scope store that overrides 'InstantiateAsync()' to use a custom factory. + + + The token was concurrently updated and cannot be persisted in its current state. +Reload the token from the database and retry the operation. + + + An error occurred while trying to create a new token instance. +Make sure that the token entity is not abstract and has a public parameterless constructor or create a custom token store that overrides 'InstantiateAsync()' to use a custom factory. + + + An error occurred while pruning tokens. + + + The application associated with the token cannot be found. + + + The authorization associated with the token cannot be found. + + + The specified application type is not compatible with the Entity Framework Core stores. +When enabling the Entity Framework Core stores, make sure you use the built-in 'OpenIddictEntityFrameworkCoreApplication' entity or a custom entity that inherits from the generic 'OpenIddictEntityFrameworkCoreApplication' entity. + + + No Entity Framework Core context was specified in the OpenIddict options. +To configure the OpenIddict Entity Framework Core stores to use a specific 'DbContext', use 'options.UseEntityFrameworkCore().UseDbContext<TContext>()'. + + + The specified authorization type is not compatible with the Entity Framework Core stores. +When enabling the Entity Framework Core stores, make sure you use the built-in 'OpenIddictEntityFrameworkCoreAuthorization' entity or a custom entity that inherits from the generic 'OpenIddictEntityFrameworkCoreAuthorization' entity. + + + The specified scope type is not compatible with the Entity Framework Core stores. +When enabling the Entity Framework Core stores, make sure you use the built-in 'OpenIddictEntityFrameworkCoreScope' entity or a custom entity that inherits from the generic 'OpenIddictEntityFrameworkCoreScope' entity. + + + The specified token type is not compatible with the Entity Framework Core stores. +When enabling the Entity Framework Core stores, make sure you use the built-in 'OpenIddictEntityFrameworkCoreToken' entity or a custom entity that inherits from the generic 'OpenIddictEntityFrameworkCoreToken' entity. + + + The specified application type is not compatible with the MongoDB stores. +When enabling the MongoDB stores, make sure you use the built-in 'OpenIddictMongoDbApplication' entity or a custom entity that inherits from the 'OpenIddictMongoDbApplication' entity. + + + The specified authorization type is not compatible with the MongoDB stores. +When enabling the MongoDB stores, make sure you use the built-in 'OpenIddictMongoDbAuthorization' entity or a custom entity that inherits from the 'OpenIddictMongoDbAuthorization' entity. + + + The specified scope type is not compatible with the MongoDB stores. +When enabling the MongoDB stores, make sure you use the built-in 'OpenIddictMongoDbScope' entity or a custom entity that inherits from the 'OpenIddictMongoDbScope' entity. + + + The specified token type is not compatible with the MongoDB stores. +When enabling the MongoDB stores, make sure you use the built-in 'OpenIddictMongoDbToken' entity or a custom entity that inherits from the 'OpenIddictMongoDbToken' entity. + + + The collection name cannot be null or empty. + + + No suitable MongoDB database service can be found. +To configure the OpenIddict MongoDB stores to use a specific database, use 'services.AddOpenIddict().AddCore().UseMongoDb().UseDatabase()' or register an 'IMongoDatabase' in the dependency injection container in 'ConfigureServices()'. + + + The second parameter must be a generic type definition. + + + X.509 certificate generation is not supported on this platform. + + + The token details cannot be found in the database. + + + No suitable signing credentials could be found. + + + The signing credentials algorithm is not valid. + + + The code challenge method cannot be retrieved from the authorization code. + + + The token usage of the JWT token is not supported. + + + The type of the JWT token cannot be resolved or inferred. + + + The type of the JWT token doesn't match the expected type. + + + The security token is missing. + + + The specified authorization code is invalid. + + + The specified device code is invalid. + + + The specified refresh token is invalid. + + + The specified token is invalid. + + + The specified token is not an authorization code. + + + The specified token is not an device code. + + + The specified token is not a refresh token. + + + The specified token is not an access token. + + + The specified identity token hint is invalid. + + + The specified authorization code has already been redeemed. + + + The specified device code has already been redeemed. + + + The specified refresh token has already been redeemed. + + + The specified token has already been redeemed. + + + The authorization has not been granted yet by the end user. + + + The authorization was denied by the resource owner. + + + The specified authorization code is no longer valid. + + + The specified device code is no longer valid. + + + The specified refresh token is no longer valid. + + + The specified token is no longer valid. + + + The authorization associated with the authorization code is no longer valid. + + + The authorization associated with the device code is no longer valid. + + + The authorization associated with the refresh token is no longer valid. + + + The authorization associated with the token is no longer valid. + + + The token request was rejected by the authorization server. + + + The user information access demand was rejected by the authorization server. + + + The specified user code is no longer valid. + + + The specified token is not valid. + + + The '{0}' parameter is not supported. + + + The mandatory '{0}' parameter is missing. + + + The '{0}' parameter must be a valid absolute URL. + + + The '{0}' parameter must not include a fragment. + + + The specified '{0}' is not supported. + + + The specified '{0}'/'{1}' combination is invalid. + + + The mandatory '{0}' scope is missing. + + + The '{0}' scope is not allowed. + + + The client identifier cannot be null or empty. + + + The '{0}' parameter cannot be used without '{1}'. + + + The status cannot be null or empty. + + + Scopes cannot be null or empty. + + + The '{0}' and '{1}' parameters can only be used with a response type containing '{2}'. + + + The specified '{0}' is not allowed when using PKCE. + + + Scopes cannot contain spaces. + + + The specified '{0}' is not valid for this client application. + + + The scope name cannot be null or empty. + + + The scope name cannot contain spaces. + + + This client application is not allowed to use the authorization endpoint. + + + The client application is not allowed to use the authorization code flow. + + + The client application is not allowed to use the implicit flow. + + + The client application is not allowed to use the hybrid flow. + + + The client application is not allowed to use the 'offline_access' scope. + + + This client application is not allowed to use the specified scope. + + + The specified '{0}' is invalid. + + + The '{0}' parameter is not valid for this client application. + + + The '{0}' parameter required for this client application is missing. + + + The specified client credentials are invalid. + + + This client application is not allowed to use the device endpoint. + + + The '{0}' and '{1}' parameters are required when using the client credentials grant. + + + The '{0}' parameter is required when using the device code grant. + + + The mandatory '{0}' and/or '{1}' parameters are missing. + + + A scope with the same name already exists. + + + The '{0}' parameter is not valid for this client application. + + + The '{0}' parameter required for this client application is missing. + + + This client application is not allowed to use the token endpoint. + + + This client application is not allowed to use the specified grant type. + + + The client application is not allowed to use the '{0}' scope. + + + The specified authorization code cannot be used without specifying a client identifier. + + + The specified device code cannot be used without specifying a client identifier. + + + The specified refresh token cannot be used without specifying a client identifier. + + + The specified authorization code cannot be used by this client application. + + + The specified device code cannot be used by this client application. + + + The specified refresh token cannot be used by this client application. + + + The specified '{0}' parameter doesn't match the client redirection endpoint the authorization code was initially sent to. + + + The '{0}' parameter is uncalled for in this request. + + + The '{0}' parameter is not valid in this context. + + + This client application is not allowed to use the introspection endpoint. + + + The specified token cannot be introspected. + + + The client application is not allowed to introspect the specified token. + + + This client application is not allowed to use the revocation endpoint. + + + This token cannot be revoked. + + + The client application is not allowed to revoke the specified token. + + + The mandatory '{0}' header is missing. + + + The specified '{0}' header is invalid. + + + This server only accepts HTTPS requests. + + + The specified HTTP method is not valid. + + + A token with the same reference identifier already exists. + + + The token type cannot be null or empty. + + + Multiple client credentials cannot be specified. + + + The issuer associated to the specified token is not valid. + + + The specified token is not of the expected type. + + + The signing key associated to the specified token was not found. + + + The signature associated to the specified token is not valid. + + + This resource server is currently unavailable. Try again later. + + + The specified token doesn't contain any audience. + + + The specified token cannot be used with this resource server. + + + The user represented by the token is not allowed to perform the requested action. + + + No issuer could be found in the discovery document. + + + A discovery response containing an invalid issuer was returned. + + + The issuer returned by the discovery endpoint is not valid. + + + No JWKS endpoint could be found in the discovery document. + + + A discovery response containing an invalid JWKS endpoint URL was returned. + + + A discovery response containing an invalid introspection endpoint URL was returned. + + + The JWKS document didn't contain a valid '{0}' node with at least one key. + + + A JWKS response containing an unsupported key was returned. + + + A JWKS response containing an invalid key was returned. + + + The mandatory '{0}' parameter couldn't be found in the introspection response. + + + The token was rejected by the remote authorization server. + + + The '{0}' claim is malformed or isn't of the expected type. + + + An introspection response containing an invalid issuer was returned. + + + The issuer returned in the introspection response is not valid. + + + The type of the introspection token doesn't match the expected type. + + + An application with the same client identifier already exists. + + + Only confidential, hybrid or public applications are supported by the default application manager. + + + The client secret cannot be null or empty for a confidential application. + + + A client secret cannot be associated with a public application. + + + Callback URLs cannot contain a fragment. + + + The authorization type cannot be null or empty. + + + The specified authorization type is not supported by the default token manager. + + + The client type cannot be null or empty. + + + Callback URLs cannot be null or empty. + + + Callback URLs must be valid absolute URLs. + + \ No newline at end of file diff --git a/src/OpenIddict.Abstractions/Stores/IOpenIddictApplicationStore.cs b/src/OpenIddict.Abstractions/Stores/IOpenIddictApplicationStore.cs index 4f77cd95..2ef81444 100644 --- a/src/OpenIddict.Abstractions/Stores/IOpenIddictApplicationStore.cs +++ b/src/OpenIddict.Abstractions/Stores/IOpenIddictApplicationStore.cs @@ -7,12 +7,12 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Globalization; using System.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; -using System.Text.Json; -using System.Globalization; namespace OpenIddict.Abstractions { diff --git a/src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs b/src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs index f83d9373..5a005816 100644 --- a/src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs @@ -8,10 +8,10 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; -using System.Text.Json; namespace OpenIddict.Abstractions { diff --git a/src/OpenIddict.Abstractions/Stores/IOpenIddictScopeStore.cs b/src/OpenIddict.Abstractions/Stores/IOpenIddictScopeStore.cs index e41c9f71..ac34d0be 100644 --- a/src/OpenIddict.Abstractions/Stores/IOpenIddictScopeStore.cs +++ b/src/OpenIddict.Abstractions/Stores/IOpenIddictScopeStore.cs @@ -7,12 +7,12 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Globalization; using System.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; -using System.Text.Json; -using System.Globalization; namespace OpenIddict.Abstractions { diff --git a/src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs b/src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs index 83b40b5c..b5adbc07 100644 --- a/src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs +++ b/src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs @@ -8,10 +8,10 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; -using System.Text.Json; namespace OpenIddict.Abstractions { diff --git a/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs b/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs index 88c17bc2..ea90c0e1 100644 --- a/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs +++ b/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs @@ -16,6 +16,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using OpenIddict.Abstractions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -124,7 +125,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var parameters = new @@ -166,7 +167,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var parameters = new @@ -206,7 +207,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } return ExecuteAsync(cancellationToken); @@ -253,7 +254,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } return ExecuteAsync(cancellationToken); @@ -305,7 +306,7 @@ namespace OpenIddict.Core var identifier = await _store.GetIdAsync(application, cancellationToken); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The application identifier cannot be extracted."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1195)); } if (_signals.TryRemove(identifier, out CancellationTokenSource signal)) @@ -337,7 +338,7 @@ namespace OpenIddict.Core var signal = await CreateExpirationSignalAsync(application, cancellationToken); if (signal == null) { - throw new InvalidOperationException("An error occurred while creating an expiration signal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1196)); } entry.AddExpirationToken(signal); @@ -369,7 +370,7 @@ namespace OpenIddict.Core var signal = await CreateExpirationSignalAsync(application, cancellationToken); if (signal == null) { - throw new InvalidOperationException("An error occurred while creating an expiration signal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1196)); } entry.AddExpirationToken(signal); @@ -400,7 +401,7 @@ namespace OpenIddict.Core var identifier = await _store.GetIdAsync(application, cancellationToken); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The application identifier cannot be extracted."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1195)); } var signal = _signals.GetOrAdd(identifier, _ => new CancellationTokenSource()); diff --git a/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs b/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs index 2deb8cf5..a114b35f 100644 --- a/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs +++ b/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs @@ -16,6 +16,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using OpenIddict.Abstractions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -132,12 +133,12 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } return ExecuteAsync(cancellationToken); @@ -188,17 +189,17 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } return ExecuteAsync(cancellationToken); @@ -251,22 +252,22 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } return ExecuteAsync(cancellationToken); @@ -322,22 +323,22 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } // Note: this method is only partially cached. @@ -366,7 +367,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return ExecuteAsync(cancellationToken); @@ -415,7 +416,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var parameters = new @@ -455,7 +456,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } return ExecuteAsync(cancellationToken); @@ -507,7 +508,7 @@ namespace OpenIddict.Core var identifier = await _store.GetIdAsync(authorization, cancellationToken); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The application identifier cannot be extracted."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1195)); } if (_signals.TryRemove(identifier, out CancellationTokenSource signal)) @@ -539,7 +540,7 @@ namespace OpenIddict.Core var signal = await CreateExpirationSignalAsync(authorization, cancellationToken); if (signal == null) { - throw new InvalidOperationException("An error occurred while creating an expiration signal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1196)); } entry.AddExpirationToken(signal); @@ -571,7 +572,7 @@ namespace OpenIddict.Core var signal = await CreateExpirationSignalAsync(authorization, cancellationToken); if (signal == null) { - throw new InvalidOperationException("An error occurred while creating an expiration signal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1196)); } entry.AddExpirationToken(signal); @@ -602,7 +603,7 @@ namespace OpenIddict.Core var identifier = await _store.GetIdAsync(authorization, cancellationToken); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The authorization identifier cannot be extracted."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1200)); } var signal = _signals.GetOrAdd(identifier, _ => new CancellationTokenSource()); diff --git a/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs b/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs index ccb121b8..32ba44da 100644 --- a/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs +++ b/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs @@ -17,6 +17,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using OpenIddict.Abstractions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -116,7 +117,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var parameters = new @@ -158,7 +159,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The scope name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1201), nameof(name)); } var parameters = new @@ -197,7 +198,7 @@ namespace OpenIddict.Core { if (names.Any(name => string.IsNullOrEmpty(name))) { - throw new ArgumentException("Scope names cannot be null or empty.", nameof(names)); + throw new ArgumentException(SR.GetResourceString(SR.ID1202), nameof(names)); } // Note: this method is only partially cached. @@ -225,7 +226,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(resource)) { - throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); + throw new ArgumentException(SR.GetResourceString(SR.ID1061), nameof(resource)); } return ExecuteAsync(cancellationToken); @@ -277,7 +278,7 @@ namespace OpenIddict.Core var identifier = await _store.GetIdAsync(scope, cancellationToken); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The application identifier cannot be extracted."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1195)); } if (_signals.TryRemove(identifier, out CancellationTokenSource signal)) @@ -309,7 +310,7 @@ namespace OpenIddict.Core var signal = await CreateExpirationSignalAsync(scope, cancellationToken); if (signal == null) { - throw new InvalidOperationException("An error occurred while creating an expiration signal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1196)); } entry.AddExpirationToken(signal); @@ -341,7 +342,7 @@ namespace OpenIddict.Core var signal = await CreateExpirationSignalAsync(scope, cancellationToken); if (signal == null) { - throw new InvalidOperationException("An error occurred while creating an expiration signal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1196)); } entry.AddExpirationToken(signal); @@ -371,7 +372,7 @@ namespace OpenIddict.Core var identifier = await _store.GetIdAsync(scope, cancellationToken); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The scope identifier cannot be extracted."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1203)); } var signal = _signals.GetOrAdd(identifier, _ => new CancellationTokenSource()); diff --git a/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs b/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs index 4317a093..03d3b92f 100644 --- a/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs +++ b/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs @@ -16,6 +16,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using OpenIddict.Abstractions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -148,12 +149,12 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } return ExecuteAsync(cancellationToken); @@ -204,17 +205,17 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } return ExecuteAsync(cancellationToken); @@ -267,22 +268,22 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } return ExecuteAsync(cancellationToken); @@ -332,7 +333,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return ExecuteAsync(cancellationToken); @@ -379,7 +380,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return ExecuteAsync(cancellationToken); @@ -428,7 +429,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var parameters = new @@ -471,7 +472,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var parameters = new @@ -510,7 +511,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } return ExecuteAsync(cancellationToken); @@ -562,7 +563,7 @@ namespace OpenIddict.Core var identifier = await _store.GetIdAsync(token, cancellationToken); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The application identifier cannot be extracted."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1204)); } if (_signals.TryRemove(identifier, out CancellationTokenSource signal)) @@ -594,7 +595,7 @@ namespace OpenIddict.Core var signal = await CreateExpirationSignalAsync(token, cancellationToken); if (signal == null) { - throw new InvalidOperationException("An error occurred while creating an expiration signal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1196)); } entry.AddExpirationToken(signal); @@ -626,7 +627,7 @@ namespace OpenIddict.Core var signal = await CreateExpirationSignalAsync(token, cancellationToken); if (signal == null) { - throw new InvalidOperationException("An error occurred while creating an expiration signal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1196)); } entry.AddExpirationToken(signal); @@ -656,7 +657,7 @@ namespace OpenIddict.Core var identifier = await _store.GetIdAsync(token, cancellationToken); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The token identifier cannot be extracted."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1204)); } var signal = _signals.GetOrAdd(identifier, _ => new CancellationTokenSource()); diff --git a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs index 2af8a372..e240bf19 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs @@ -17,10 +17,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; +using OpenIddict.Abstractions.Resources; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute; #if !SUPPORTS_KEY_DERIVATION_WITH_SPECIFIED_HASH_ALGORITHM @@ -49,14 +52,16 @@ namespace OpenIddict.Core { public OpenIddictApplicationManager( [NotNull] IOpenIddictApplicationCache cache, - [NotNull] IOpenIddictApplicationStoreResolver resolver, + [NotNull] IStringLocalizer localizer, [NotNull] ILogger> logger, - [NotNull] IOptionsMonitor options) + [NotNull] IOptionsMonitor options, + [NotNull] IOpenIddictApplicationStoreResolver resolver) { Cache = cache; - Store = resolver.Get(); + Localizer = localizer; Logger = logger; Options = options; + Store = resolver.Get(); } /// @@ -64,6 +69,11 @@ namespace OpenIddict.Core /// protected IOpenIddictApplicationCache Cache { get; } + /// + /// Gets the string localizer associated with the current manager. + /// + protected IStringLocalizer Localizer { get; } + /// /// Gets the logger associated with the current manager. /// @@ -144,7 +154,7 @@ namespace OpenIddict.Core if (!string.IsNullOrEmpty(await Store.GetClientSecretAsync(application, cancellationToken))) { - throw new ArgumentException("The client secret hash cannot be set on the application entity.", nameof(application)); + throw new ArgumentException(SR.GetResourceString(SR.ID1205), nameof(application)); } // If no client type was specified, assume it's a public application if no secret was provided. @@ -166,7 +176,7 @@ namespace OpenIddict.Core if (results.Any(result => result != ValidationResult.Success)) { var builder = new StringBuilder(); - builder.AppendLine("One or more validation error(s) occurred while trying to create a new application:"); + builder.AppendLine(SR.GetResourceString(SR.ID1206)); builder.AppendLine(); foreach (var result in results) @@ -220,7 +230,7 @@ namespace OpenIddict.Core var application = await Store.InstantiateAsync(cancellationToken); if (application == null) { - throw new InvalidOperationException("An error occurred while trying to create a new application."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1207)); } await PopulateAsync(application, descriptor, cancellationToken); @@ -276,7 +286,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var application = Options.CurrentValue.DisableEntityCaching ? @@ -313,7 +323,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var application = Options.CurrentValue.DisableEntityCaching ? @@ -348,7 +358,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } var applications = Options.CurrentValue.DisableEntityCaching ? @@ -390,7 +400,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } var applications = Options.CurrentValue.DisableEntityCaching ? @@ -755,7 +765,7 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The client type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1208), nameof(type)); } return string.Equals(await GetClientTypeAsync(application, cancellationToken), type, StringComparison.OrdinalIgnoreCase); @@ -778,7 +788,7 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The consent type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1209), nameof(type)); } return string.Equals(await GetConsentTypeAsync(application, cancellationToken), type, StringComparison.OrdinalIgnoreCase); @@ -801,7 +811,7 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(permission)) { - throw new ArgumentException("The permission name cannot be null or empty.", nameof(permission)); + throw new ArgumentException(SR.GetResourceString(SR.ID1210), nameof(permission)); } return (await GetPermissionsAsync(application, cancellationToken)).Contains(permission, StringComparer.Ordinal); @@ -824,7 +834,7 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(requirement)) { - throw new ArgumentException("The requirement name cannot be null or empty.", nameof(requirement)); + throw new ArgumentException(SR.GetResourceString(SR.ID1211), nameof(requirement)); } return (await GetRequirementsAsync(application, cancellationToken)).Contains(requirement, StringComparer.Ordinal); @@ -961,13 +971,13 @@ namespace OpenIddict.Core // Ensure the address is not null or empty. if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("Callback URLs cannot be null or empty."); + throw new ArgumentException(SR.GetResourceString(SR.ID1212)); } // Ensure the address is a valid absolute URL. if (!Uri.TryCreate(address, UriKind.Absolute, out Uri uri) || !uri.IsWellFormedOriginalString()) { - throw new ArgumentException("Callback URLs must be valid absolute URLs."); + throw new ArgumentException(SR.GetResourceString(SR.ID1213)); } descriptor.PostLogoutRedirectUris.Add(uri); @@ -979,13 +989,13 @@ namespace OpenIddict.Core // Ensure the address is not null or empty. if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("Callback URLs cannot be null or empty."); + throw new ArgumentException(SR.GetResourceString(SR.ID1212)); } // Ensure the address is a valid absolute URL. if (!Uri.TryCreate(address, UriKind.Absolute, out Uri uri) || !uri.IsWellFormedOriginalString()) { - throw new ArgumentException("Callback URLs must be valid absolute URLs."); + throw new ArgumentException(SR.GetResourceString(SR.ID1213)); } descriptor.RedirectUris.Add(uri); @@ -1011,7 +1021,7 @@ namespace OpenIddict.Core if (results.Any(result => result != ValidationResult.Success)) { var builder = new StringBuilder(); - builder.AppendLine("One or more validation error(s) occurred while trying to update an existing application:"); + builder.AppendLine(SR.GetResourceString(SR.ID1214)); builder.AppendLine(); foreach (var result in results) @@ -1133,7 +1143,7 @@ namespace OpenIddict.Core var identifier = await Store.GetClientIdAsync(application, cancellationToken); if (string.IsNullOrEmpty(identifier)) { - yield return new ValidationResult("The client identifier cannot be null or empty."); + yield return new ValidationResult(Localizer[SR.ID3036]); } else @@ -1147,14 +1157,14 @@ namespace OpenIddict.Core await Store.GetIdAsync(other, cancellationToken), await Store.GetIdAsync(application, cancellationToken), StringComparison.Ordinal)) { - yield return new ValidationResult("An application with the same client identifier already exists."); + yield return new ValidationResult(Localizer[SR.ID3111]); } } var type = await Store.GetClientTypeAsync(application, cancellationToken); if (string.IsNullOrEmpty(type)) { - yield return new ValidationResult("The client type cannot be null or empty."); + yield return new ValidationResult(Localizer[SR.ID3118]); } else @@ -1164,21 +1174,20 @@ namespace OpenIddict.Core !string.Equals(type, ClientTypes.Hybrid, StringComparison.OrdinalIgnoreCase) && !string.Equals(type, ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { - yield return new ValidationResult("Only 'confidential', 'hybrid' or 'public' applications are " + - "supported by the default application manager."); + yield return new ValidationResult(Localizer[SR.ID3112]); } // Ensure a client secret was specified if the client is a confidential application. var secret = await Store.GetClientSecretAsync(application, cancellationToken); if (string.IsNullOrEmpty(secret) && string.Equals(type, ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase)) { - yield return new ValidationResult("The client secret cannot be null or empty for a confidential application."); + yield return new ValidationResult(Localizer[SR.ID3113]); } // Ensure no client secret was specified if the client is a public application. else if (!string.IsNullOrEmpty(secret) && string.Equals(type, ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { - yield return new ValidationResult("A client secret cannot be associated with a public application."); + yield return new ValidationResult(Localizer[SR.ID3114]); } } @@ -1191,7 +1200,7 @@ namespace OpenIddict.Core // Ensure the address is not null or empty. if (string.IsNullOrEmpty(address)) { - yield return new ValidationResult("Callback URLs cannot be null or empty."); + yield return new ValidationResult(Localizer[SR.ID3119]); break; } @@ -1199,7 +1208,7 @@ namespace OpenIddict.Core // Ensure the address is a valid absolute URL. if (!Uri.TryCreate(address, UriKind.Absolute, out Uri uri) || !uri.IsWellFormedOriginalString()) { - yield return new ValidationResult("Callback URLs must be valid absolute URLs."); + yield return new ValidationResult(Localizer[SR.ID3120]); break; } @@ -1207,7 +1216,7 @@ namespace OpenIddict.Core // Ensure the address doesn't contain a fragment. if (!string.IsNullOrEmpty(uri.Fragment)) { - yield return new ValidationResult("Callback URLs cannot contain a fragment."); + yield return new ValidationResult(Localizer[SR.ID3115]); break; } @@ -1234,7 +1243,7 @@ namespace OpenIddict.Core } if (string.IsNullOrEmpty(secret)) { - throw new ArgumentException("The secret cannot be null or empty.", nameof(secret)); + throw new ArgumentException(SR.GetResourceString(SR.ID1215), nameof(secret)); } if (await HasClientTypeAsync(application, ClientTypes.Public, cancellationToken)) @@ -1285,7 +1294,7 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } foreach (var uri in await Store.GetRedirectUrisAsync(application, cancellationToken)) @@ -1317,7 +1326,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(secret)) { - throw new ArgumentException("The secret cannot be null or empty.", nameof(secret)); + throw new ArgumentException(SR.GetResourceString(SR.ID1215), nameof(secret)); } // Note: the PRF, iteration count, salt length and key length currently all match the default values @@ -1362,7 +1371,7 @@ namespace OpenIddict.Core var name when name == HashAlgorithmName.SHA256 => 1, var name when name == HashAlgorithmName.SHA512 => 2, - _ => throw new InvalidOperationException("The specified HMAC algorithm is not valid.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1216)) }); // Write the iteration count of the algorithm. @@ -1397,12 +1406,12 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(secret)) { - throw new ArgumentException("The secret cannot be null or empty.", nameof(secret)); + throw new ArgumentException(SR.GetResourceString(SR.ID1215), nameof(secret)); } if (string.IsNullOrEmpty(comparand)) { - throw new ArgumentException("The comparand cannot be null or empty.", nameof(comparand)); + throw new ArgumentException(SR.GetResourceString(SR.ID1217), nameof(comparand)); } try @@ -1443,7 +1452,7 @@ namespace OpenIddict.Core 1 => HashAlgorithmName.SHA256, 2 => HashAlgorithmName.SHA512, - _ => throw new InvalidOperationException("The specified hash algorithm is not valid.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1216)) }; // Read the iteration count of the algorithm. @@ -1493,7 +1502,7 @@ namespace OpenIddict.Core var name when name == HashAlgorithmName.SHA256 => new Sha256Digest(), var name when name == HashAlgorithmName.SHA512 => new Sha512Digest(), - _ => throw new InvalidOperationException("The specified hash algorithm is not valid.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1216)) }); generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(secret.ToCharArray()), salt.ToArray(), iterations); diff --git a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs index 8903999c..0fc219b4 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs @@ -15,11 +15,14 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; +using OpenIddict.Abstractions.Resources; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Abstractions.OpenIddictExceptions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -36,14 +39,16 @@ namespace OpenIddict.Core { public OpenIddictAuthorizationManager( [NotNull] IOpenIddictAuthorizationCache cache, - [NotNull] IOpenIddictAuthorizationStoreResolver resolver, + [NotNull] IStringLocalizer localizer, [NotNull] ILogger> logger, - [NotNull] IOptionsMonitor options) + [NotNull] IOptionsMonitor options, + [NotNull] IOpenIddictAuthorizationStoreResolver resolver) { Cache = cache; - Store = resolver.Get(); + Localizer = localizer; Logger = logger; Options = options; + Store = resolver.Get(); } /// @@ -51,6 +56,11 @@ namespace OpenIddict.Core /// protected IOpenIddictAuthorizationCache Cache { get; } + /// + /// Gets the string localizer associated with the current manager. + /// + protected IStringLocalizer Localizer { get; } + /// /// Gets the logger associated with the current manager. /// @@ -123,7 +133,7 @@ namespace OpenIddict.Core if (results.Any(result => result != ValidationResult.Success)) { var builder = new StringBuilder(); - builder.AppendLine("One or more validation error(s) occurred while trying to create a new authorization:"); + builder.AppendLine(SR.GetResourceString(SR.ID1218)); builder.AppendLine(); foreach (var result in results) @@ -174,7 +184,7 @@ namespace OpenIddict.Core var authorization = await Store.InstantiateAsync(cancellationToken); if (authorization == null) { - throw new InvalidOperationException("An error occurred while trying to create a new authorization."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1219)); } await PopulateAsync(authorization, descriptor, cancellationToken); @@ -206,17 +216,17 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } var descriptor = new OpenIddictAuthorizationDescriptor @@ -269,12 +279,12 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } var authorizations = Options.CurrentValue.DisableEntityCaching ? @@ -322,17 +332,17 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } var authorizations = Options.CurrentValue.DisableEntityCaching ? @@ -377,22 +387,22 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } var authorizations = Options.CurrentValue.DisableEntityCaching ? @@ -439,22 +449,22 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } var authorizations = Options.CurrentValue.DisableEntityCaching ? @@ -502,7 +512,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var authorizations = Options.CurrentValue.DisableEntityCaching ? @@ -545,7 +555,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var authorization = Options.CurrentValue.DisableEntityCaching ? @@ -580,7 +590,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } var authorizations = Options.CurrentValue.DisableEntityCaching ? @@ -810,7 +820,7 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } return string.Equals(await Store.GetStatusAsync(authorization, cancellationToken), status, StringComparison.OrdinalIgnoreCase); @@ -833,7 +843,7 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } return string.Equals(await Store.GetTypeAsync(authorization, cancellationToken), type, StringComparison.OrdinalIgnoreCase); @@ -1047,7 +1057,7 @@ namespace OpenIddict.Core if (results.Any(result => result != ValidationResult.Success)) { var builder = new StringBuilder(); - builder.AppendLine("One or more validation error(s) occurred while trying to update an existing authorization:"); + builder.AppendLine(SR.GetResourceString(SR.ID1220)); builder.AppendLine(); foreach (var result in results) @@ -1123,18 +1133,18 @@ namespace OpenIddict.Core var type = await Store.GetTypeAsync(authorization, cancellationToken); if (string.IsNullOrEmpty(type)) { - yield return new ValidationResult("The authorization type cannot be null or empty."); + yield return new ValidationResult(Localizer[SR.ID3116]); } else if (!string.Equals(type, AuthorizationTypes.AdHoc, StringComparison.OrdinalIgnoreCase) && !string.Equals(type, AuthorizationTypes.Permanent, StringComparison.OrdinalIgnoreCase)) { - yield return new ValidationResult("The specified authorization type is not supported by the default token manager."); + yield return new ValidationResult(Localizer[SR.ID3117]); } if (string.IsNullOrEmpty(await Store.GetStatusAsync(authorization, cancellationToken))) { - yield return new ValidationResult("The status cannot be null or empty."); + yield return new ValidationResult(Localizer[SR.ID3038]); } // Ensure that the scopes are not null or empty and do not contain spaces. @@ -1142,14 +1152,14 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(scope)) { - yield return new ValidationResult("Scopes cannot be null or empty."); + yield return new ValidationResult(Localizer[SR.ID3039]); break; } if (scope.Contains(Separators.Space[0])) { - yield return new ValidationResult("Scopes cannot contain spaces."); + yield return new ValidationResult(Localizer[SR.ID3042]); break; } diff --git a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs index 8ce33f07..577c6f63 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs @@ -15,10 +15,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; +using OpenIddict.Abstractions.Resources; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -35,14 +38,16 @@ namespace OpenIddict.Core { public OpenIddictScopeManager( [NotNull] IOpenIddictScopeCache cache, - [NotNull] IOpenIddictScopeStoreResolver resolver, + [NotNull] IStringLocalizer localizer, [NotNull] ILogger> logger, - [NotNull] IOptionsMonitor options) + [NotNull] IOptionsMonitor options, + [NotNull] IOpenIddictScopeStoreResolver resolver) { Cache = cache; - Store = resolver.Get(); + Localizer = localizer; Logger = logger; Options = options; + Store = resolver.Get(); } /// @@ -50,6 +55,11 @@ namespace OpenIddict.Core /// protected IOpenIddictScopeCache Cache { get; } + /// + /// Gets the string localizer associated with the current manager. + /// + protected IStringLocalizer Localizer { get; } + /// /// Gets the logger associated with the current manager. /// @@ -116,7 +126,7 @@ namespace OpenIddict.Core if (results.Any(result => result != ValidationResult.Success)) { var builder = new StringBuilder(); - builder.AppendLine("One or more validation error(s) occurred while trying to create a new scope:"); + builder.AppendLine(SR.GetResourceString(SR.ID1221)); builder.AppendLine(); foreach (var result in results) @@ -167,7 +177,7 @@ namespace OpenIddict.Core var scope = await Store.InstantiateAsync(cancellationToken); if (scope == null) { - throw new InvalidOperationException("An error occurred while trying to create a new scope."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1222)); } await PopulateAsync(scope, descriptor, cancellationToken); @@ -212,7 +222,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var scope = Options.CurrentValue.DisableEntityCaching ? @@ -249,7 +259,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The scope name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1201), nameof(name)); } var scope = Options.CurrentValue.DisableEntityCaching ? @@ -285,7 +295,7 @@ namespace OpenIddict.Core { if (names.Any(name => string.IsNullOrEmpty(name))) { - throw new ArgumentException("Scope names cannot be null or empty.", nameof(names)); + throw new ArgumentException(SR.GetResourceString(SR.ID1202), nameof(names)); } var scopes = Options.CurrentValue.DisableEntityCaching ? @@ -326,7 +336,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(resource)) { - throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); + throw new ArgumentException(SR.GetResourceString(SR.ID1061), nameof(resource)); } var scopes = Options.CurrentValue.DisableEntityCaching ? @@ -833,7 +843,7 @@ namespace OpenIddict.Core if (results.Any(result => result != ValidationResult.Success)) { var builder = new StringBuilder(); - builder.AppendLine("One or more validation error(s) occurred while trying to update an existing scope:"); + builder.AppendLine(SR.GetResourceString(SR.ID1223)); builder.AppendLine(); foreach (var result in results) @@ -911,12 +921,12 @@ namespace OpenIddict.Core var name = await Store.GetNameAsync(scope, cancellationToken); if (string.IsNullOrEmpty(name)) { - yield return new ValidationResult("The scope name cannot be null or empty."); + yield return new ValidationResult(Localizer[SR.ID3044]); } else if (name.Contains(Separators.Space[0])) { - yield return new ValidationResult("The scope name cannot contain spaces."); + yield return new ValidationResult(Localizer[SR.ID3045]); } else @@ -930,7 +940,7 @@ namespace OpenIddict.Core await Store.GetIdAsync(other, cancellationToken), await Store.GetIdAsync(scope, cancellationToken), StringComparison.Ordinal)) { - yield return new ValidationResult("A scope with the same name already exists."); + yield return new ValidationResult(Localizer[SR.ID3060]); } } } diff --git a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs index 63258748..5a77869f 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs @@ -15,11 +15,14 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; +using OpenIddict.Abstractions.Resources; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Abstractions.OpenIddictExceptions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -36,14 +39,16 @@ namespace OpenIddict.Core { public OpenIddictTokenManager( [NotNull] IOpenIddictTokenCache cache, - [NotNull] IOpenIddictTokenStoreResolver resolver, + [NotNull] IStringLocalizer localizer, [NotNull] ILogger> logger, - [NotNull] IOptionsMonitor options) + [NotNull] IOptionsMonitor options, + [NotNull] IOpenIddictTokenStoreResolver resolver) { Cache = cache; - Store = resolver.Get(); + Localizer = localizer; Logger = logger; Options = options; + Store = resolver.Get(); } /// @@ -51,6 +56,11 @@ namespace OpenIddict.Core /// protected IOpenIddictTokenCache Cache { get; } + /// + /// Gets the string localizer associated with the current manager. + /// + protected IStringLocalizer Localizer { get; } + /// /// Gets the logger associated with the current manager. /// @@ -131,7 +141,7 @@ namespace OpenIddict.Core if (results.Any(result => result != ValidationResult.Success)) { var builder = new StringBuilder(); - builder.AppendLine("One or more validation error(s) occurred while trying to create a new token:"); + builder.AppendLine(SR.GetResourceString(SR.ID1224)); builder.AppendLine(); foreach (var result in results) @@ -182,7 +192,7 @@ namespace OpenIddict.Core var token = await Store.InstantiateAsync(cancellationToken); if (token == null) { - throw new InvalidOperationException("An error occurred while trying to create a new token"); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1225)); } await PopulateAsync(token, descriptor, cancellationToken); @@ -227,12 +237,12 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } var tokens = Options.CurrentValue.DisableEntityCaching ? @@ -276,17 +286,17 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } var tokens = Options.CurrentValue.DisableEntityCaching ? @@ -331,22 +341,22 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } var tokens = Options.CurrentValue.DisableEntityCaching ? @@ -387,7 +397,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var tokens = Options.CurrentValue.DisableEntityCaching ? @@ -428,7 +438,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var tokens = Options.CurrentValue.DisableEntityCaching ? @@ -471,7 +481,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var token = Options.CurrentValue.DisableEntityCaching ? @@ -509,7 +519,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } identifier = await ObfuscateReferenceIdAsync(identifier, cancellationToken); @@ -547,7 +557,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } var tokens = Options.CurrentValue.DisableEntityCaching ? @@ -830,7 +840,7 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } return string.Equals(await Store.GetStatusAsync(token, cancellationToken), status, StringComparison.OrdinalIgnoreCase); @@ -852,7 +862,7 @@ namespace OpenIddict.Core if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } return string.Equals(await Store.GetTypeAsync(token, cancellationToken), type, StringComparison.OrdinalIgnoreCase); @@ -1250,7 +1260,7 @@ namespace OpenIddict.Core if (results.Any(result => result != ValidationResult.Success)) { var builder = new StringBuilder(); - builder.AppendLine("One or more validation error(s) occurred while trying to update an existing token:"); + builder.AppendLine(SR.GetResourceString(SR.ID1226)); builder.AppendLine(); foreach (var result in results) @@ -1348,26 +1358,19 @@ namespace OpenIddict.Core await Store.GetIdAsync(other, cancellationToken), await Store.GetIdAsync(token, cancellationToken), StringComparison.Ordinal)) { - yield return new ValidationResult("A token with the same reference identifier already exists."); + yield return new ValidationResult(Localizer[SR.ID3085]); } } var type = await Store.GetTypeAsync(token, cancellationToken); if (string.IsNullOrEmpty(type)) { - yield return new ValidationResult("The token type cannot be null or empty."); + yield return new ValidationResult(Localizer[SR.ID3086]); } if (string.IsNullOrEmpty(await Store.GetStatusAsync(token, cancellationToken))) { - yield return new ValidationResult("The status cannot be null or empty."); - } - - if (string.IsNullOrEmpty(await Store.GetSubjectAsync(token, cancellationToken)) && - !string.Equals(type, TokenTypeHints.DeviceCode, StringComparison.OrdinalIgnoreCase) && - !string.Equals(type, TokenTypeHints.UserCode, StringComparison.OrdinalIgnoreCase)) - { - yield return new ValidationResult("The subject cannot be null or empty."); + yield return new ValidationResult(Localizer[SR.ID3038]); } } @@ -1384,7 +1387,7 @@ namespace OpenIddict.Core { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } // Compute the digest of the generated identifier and use it as the hashed identifier of the reference token. diff --git a/src/OpenIddict.Core/OpenIddict.Core.csproj b/src/OpenIddict.Core/OpenIddict.Core.csproj index 256be712..e651c40b 100644 --- a/src/OpenIddict.Core/OpenIddict.Core.csproj +++ b/src/OpenIddict.Core/OpenIddict.Core.csproj @@ -15,6 +15,7 @@ + diff --git a/src/OpenIddict.Core/OpenIddictCoreBuilder.cs b/src/OpenIddict.Core/OpenIddictCoreBuilder.cs index baa948f4..7daa11f7 100644 --- a/src/OpenIddict.Core/OpenIddictCoreBuilder.cs +++ b/src/OpenIddict.Core/OpenIddictCoreBuilder.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using OpenIddict.Abstractions; using OpenIddict.Core; using OpenIddict.Extensions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace Microsoft.Extensions.DependencyInjection { @@ -83,7 +84,7 @@ namespace Microsoft.Extensions.DependencyInjection var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictApplicationStore<>)); if (root == null) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictApplicationStore<>) @@ -92,7 +93,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (type.GetGenericArguments().Length != 1) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictApplicationStore<>), type, lifetime)); @@ -140,7 +141,7 @@ namespace Microsoft.Extensions.DependencyInjection var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictAuthorizationStore<>)); if (root == null) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictAuthorizationStore<>) @@ -149,7 +150,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (type.GetGenericArguments().Length != 1) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictAuthorizationStore<>), type, lifetime)); @@ -197,7 +198,7 @@ namespace Microsoft.Extensions.DependencyInjection var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictScopeStore<>)); if (root == null) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictScopeStore<>) @@ -206,7 +207,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (type.GetGenericArguments().Length != 1) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictScopeStore<>), type, lifetime)); @@ -254,7 +255,7 @@ namespace Microsoft.Extensions.DependencyInjection var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictTokenStore<>)); if (root == null) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictTokenStore<>) @@ -263,7 +264,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (type.GetGenericArguments().Length != 1) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictTokenStore<>), type, lifetime)); @@ -308,7 +309,7 @@ namespace Microsoft.Extensions.DependencyInjection var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictApplicationManager<>)); if (root == null) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictApplicationManager<>) @@ -317,7 +318,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (type.GetGenericArguments().Length != 1) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(ServiceDescriptor.Scoped(type, type)); @@ -364,7 +365,7 @@ namespace Microsoft.Extensions.DependencyInjection if (!typeof(IOpenIddictApplicationStoreResolver).IsAssignableFrom(type)) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictApplicationStoreResolver), type, lifetime)); @@ -402,7 +403,7 @@ namespace Microsoft.Extensions.DependencyInjection var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictAuthorizationManager<>)); if (root == null) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictAuthorizationManager<>) @@ -411,7 +412,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (type.GetGenericArguments().Length != 1) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(ServiceDescriptor.Scoped(type, type)); @@ -458,7 +459,7 @@ namespace Microsoft.Extensions.DependencyInjection if (!typeof(IOpenIddictAuthorizationStoreResolver).IsAssignableFrom(type)) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictAuthorizationStoreResolver), type, lifetime)); @@ -496,7 +497,7 @@ namespace Microsoft.Extensions.DependencyInjection var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictScopeManager<>)); if (root == null) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictScopeManager<>) @@ -505,7 +506,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (type.GetGenericArguments().Length != 1) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(ServiceDescriptor.Scoped(type, type)); @@ -552,7 +553,7 @@ namespace Microsoft.Extensions.DependencyInjection if (!typeof(IOpenIddictScopeStoreResolver).IsAssignableFrom(type)) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictScopeStoreResolver), type, lifetime)); @@ -590,7 +591,7 @@ namespace Microsoft.Extensions.DependencyInjection var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictTokenManager<>)); if (root == null) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictTokenManager<>) @@ -599,7 +600,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (type.GetGenericArguments().Length != 1) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(ServiceDescriptor.Scoped(type, type)); @@ -646,7 +647,7 @@ namespace Microsoft.Extensions.DependencyInjection if (!typeof(IOpenIddictTokenStoreResolver).IsAssignableFrom(type)) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictTokenStoreResolver), type, lifetime)); @@ -695,7 +696,7 @@ namespace Microsoft.Extensions.DependencyInjection if (type.IsValueType) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } return Configure(options => options.DefaultApplicationType = type); @@ -722,7 +723,7 @@ namespace Microsoft.Extensions.DependencyInjection if (type.IsValueType) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } return Configure(options => options.DefaultAuthorizationType = type); @@ -749,7 +750,7 @@ namespace Microsoft.Extensions.DependencyInjection if (type.IsValueType) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } return Configure(options => options.DefaultScopeType = type); @@ -776,7 +777,7 @@ namespace Microsoft.Extensions.DependencyInjection if (type.IsValueType) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } return Configure(options => options.DefaultTokenType = type); @@ -792,7 +793,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (limit < 10) { - throw new ArgumentException("The cache size cannot be less than 10.", nameof(limit)); + throw new ArgumentException(SR.GetResourceString(SR.ID1232), nameof(limit)); } return Configure(options => options.EntityCacheLimit = limit); diff --git a/src/OpenIddict.Core/OpenIddictCoreExtensions.cs b/src/OpenIddict.Core/OpenIddictCoreExtensions.cs index 72a75698..0f684ad9 100644 --- a/src/OpenIddict.Core/OpenIddictCoreExtensions.cs +++ b/src/OpenIddict.Core/OpenIddictCoreExtensions.cs @@ -8,12 +8,16 @@ using System; using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging.Abstractions; using OpenIddict.Abstractions; +using OpenIddict.Abstractions.Resources; using OpenIddict.Core; namespace Microsoft.Extensions.DependencyInjection { + using Microsoft.Extensions.Options; + /// /// Exposes extensions allowing to register the OpenIddict core services. /// @@ -32,6 +36,7 @@ namespace Microsoft.Extensions.DependencyInjection throw new ArgumentNullException(nameof(builder)); } + builder.Services.AddLocalization(); builder.Services.AddLogging(); builder.Services.AddMemoryCache(); builder.Services.AddOptions(); @@ -119,6 +124,18 @@ namespace Microsoft.Extensions.DependencyInjection typeof(OpenIddictTokenManager<>).MakeGenericType(options.DefaultTokenType)); }); + builder.Services.TryAddSingleton>(provider => + { + // Note: the string localizer factory is deliberately not resolved from + // the DI container to ensure the built-in .resx files are always used + // even if the factory was replaced by a different implementation in DI. + var factory = new ResourceManagerStringLocalizerFactory( + localizationOptions: Options.Create(new LocalizationOptions()), + loggerFactory: NullLoggerFactory.Instance); + + return new StringLocalizer(factory); + }); + return new OpenIddictCoreBuilder(builder.Services); } diff --git a/src/OpenIddict.Core/Resolvers/OpenIddictApplicationStoreResolver.cs b/src/OpenIddict.Core/Resolvers/OpenIddictApplicationStoreResolver.cs index f42f818c..bc700090 100644 --- a/src/OpenIddict.Core/Resolvers/OpenIddictApplicationStoreResolver.cs +++ b/src/OpenIddict.Core/Resolvers/OpenIddictApplicationStoreResolver.cs @@ -1,8 +1,8 @@ using System; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using OpenIddict.Abstractions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -23,20 +23,7 @@ namespace OpenIddict.Core /// The type of the Application entity. /// An . public IOpenIddictApplicationStore Get() where TApplication : class - { - var store = _provider.GetService>(); - if (store == null) - { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No application store has been registered in the dependency injection container.") - .Append("To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' ") - .AppendLine("package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'.") - .Append("To register a custom store, create an implementation of 'IOpenIddictApplicationStore' and ") - .Append("use 'services.AddOpenIddict().AddCore().AddApplicationStore()' to add it to the DI container.") - .ToString()); - } - - return store; - } + => _provider.GetService>() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID1227)); } } diff --git a/src/OpenIddict.Core/Resolvers/OpenIddictAuthorizationStoreResolver.cs b/src/OpenIddict.Core/Resolvers/OpenIddictAuthorizationStoreResolver.cs index ad57df18..aa92cff8 100644 --- a/src/OpenIddict.Core/Resolvers/OpenIddictAuthorizationStoreResolver.cs +++ b/src/OpenIddict.Core/Resolvers/OpenIddictAuthorizationStoreResolver.cs @@ -1,8 +1,8 @@ using System; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using OpenIddict.Abstractions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -23,20 +23,7 @@ namespace OpenIddict.Core /// The type of the Authorization entity. /// An . public IOpenIddictAuthorizationStore Get() where TAuthorization : class - { - var store = _provider.GetService>(); - if (store == null) - { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No authorization store has been registered in the dependency injection container.") - .Append("To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' ") - .AppendLine("package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'.") - .Append("To register a custom store, create an implementation of 'IOpenIddictAuthorizationStore' and ") - .Append("use 'services.AddOpenIddict().AddCore().AddAuthorizationStore()' to add it to the DI container.") - .ToString()); - } - - return store; - } + => _provider.GetService>() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID1228)); } } diff --git a/src/OpenIddict.Core/Resolvers/OpenIddictScopeStoreResolver.cs b/src/OpenIddict.Core/Resolvers/OpenIddictScopeStoreResolver.cs index 3d9efcbe..ee981bf1 100644 --- a/src/OpenIddict.Core/Resolvers/OpenIddictScopeStoreResolver.cs +++ b/src/OpenIddict.Core/Resolvers/OpenIddictScopeStoreResolver.cs @@ -1,8 +1,8 @@ using System; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using OpenIddict.Abstractions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -23,20 +23,7 @@ namespace OpenIddict.Core /// The type of the Scope entity. /// An . public IOpenIddictScopeStore Get() where TScope : class - { - var store = _provider.GetService>(); - if (store == null) - { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No scope store has been registered in the dependency injection container.") - .Append("To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' ") - .AppendLine("package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'.") - .Append("To register a custom store, create an implementation of 'IOpenIddictScopeStore' and ") - .Append("use 'services.AddOpenIddict().AddCore().AddScopeStore()' to add it to the DI container.") - .ToString()); - } - - return store; - } + => _provider.GetService>() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID1229)); } } diff --git a/src/OpenIddict.Core/Resolvers/OpenIddictTokenStoreResolver.cs b/src/OpenIddict.Core/Resolvers/OpenIddictTokenStoreResolver.cs index e400ac5b..0f68e888 100644 --- a/src/OpenIddict.Core/Resolvers/OpenIddictTokenStoreResolver.cs +++ b/src/OpenIddict.Core/Resolvers/OpenIddictTokenStoreResolver.cs @@ -1,8 +1,8 @@ using System; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using OpenIddict.Abstractions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core { @@ -23,20 +23,7 @@ namespace OpenIddict.Core /// The type of the Token entity. /// An . public IOpenIddictTokenStore Get() where TToken : class - { - var store = _provider.GetService>(); - if (store == null) - { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No token store has been registered in the dependency injection container.") - .Append("To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' ") - .AppendLine("package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'.") - .Append("To register a custom store, create an implementation of 'IOpenIddictTokenStore' and ") - .Append("use 'services.AddOpenIddict().AddCore().AddTokenStore()' to add it to the DI container.") - .ToString()); - } - - return store; - } + => _provider.GetService>() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID1230)); } } diff --git a/src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs b/src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs index 4c88011c..b7ac8b73 100644 --- a/src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs +++ b/src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs @@ -13,6 +13,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using OpenIddict.Core; using OpenIddict.EntityFramework; using OpenIddict.EntityFramework.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace Microsoft.Extensions.DependencyInjection { @@ -111,7 +112,7 @@ namespace Microsoft.Extensions.DependencyInjection if (!typeof(DbContext).IsAssignableFrom(type)) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } Services.TryAddScoped(type); diff --git a/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolver.cs b/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolver.cs index c97e407f..e98a8a79 100644 --- a/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolver.cs +++ b/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolver.cs @@ -6,13 +6,13 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; using OpenIddict.Extensions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework { @@ -54,22 +54,13 @@ namespace OpenIddict.EntityFramework var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictEntityFrameworkApplication<,,>)); if (root == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified application type is not compatible with the Entity Framework 6.x stores.") - .Append("When enabling the Entity Framework 6.x stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkApplication' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkApplication' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1233)); } var context = _options.CurrentValue.DbContextType; if (context == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No Entity Framework 6.x context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework 6.x stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFramework().UseDbContext()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1234)); } return typeof(OpenIddictEntityFrameworkApplicationStore<,,,,>).MakeGenericType( diff --git a/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolver.cs b/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolver.cs index 75972584..ebc9c07d 100644 --- a/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolver.cs +++ b/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolver.cs @@ -6,13 +6,13 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; using OpenIddict.Extensions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework { @@ -54,22 +54,13 @@ namespace OpenIddict.EntityFramework var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictEntityFrameworkAuthorization<,,>)); if (root == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified authorization type is not compatible with the Entity Framework 6.x stores.") - .Append("When enabling the Entity Framework 6.x stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkAuthorization' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkAuthorization' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1235)); } var context = _options.CurrentValue.DbContextType; if (context == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No Entity Framework 6.x context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework 6.x stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFramework().UseDbContext()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1234)); } return typeof(OpenIddictEntityFrameworkAuthorizationStore<,,,,>).MakeGenericType( diff --git a/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkScopeStoreResolver.cs b/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkScopeStoreResolver.cs index 2a381b08..68420102 100644 --- a/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkScopeStoreResolver.cs +++ b/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkScopeStoreResolver.cs @@ -6,13 +6,13 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; using OpenIddict.Extensions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework { @@ -54,22 +54,13 @@ namespace OpenIddict.EntityFramework var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictEntityFrameworkScope<>)); if (root == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified scope type is not compatible with the Entity Framework 6.x stores.") - .Append("When enabling the Entity Framework 6.x stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkScope' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkScope' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1236)); } var context = _options.CurrentValue.DbContextType; if (context == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No Entity Framework 6.x context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework 6.x stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFramework().UseDbContext()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1234)); } return typeof(OpenIddictEntityFrameworkScopeStore<,,>).MakeGenericType( diff --git a/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkTokenStoreResolver.cs b/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkTokenStoreResolver.cs index 80a8ce75..ffccf2cc 100644 --- a/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkTokenStoreResolver.cs +++ b/src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkTokenStoreResolver.cs @@ -6,13 +6,13 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; using OpenIddict.Extensions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework { @@ -54,22 +54,13 @@ namespace OpenIddict.EntityFramework var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictEntityFrameworkToken<,,>)); if (root == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified token type is not compatible with the Entity Framework 6.x stores.") - .Append("When enabling the Entity Framework 6.x stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkToken' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkToken' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1237)); } var context = _options.CurrentValue.DbContextType; if (context == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No Entity Framework 6.x context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework 6.x stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFramework().UseDbContext()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1234)); } return typeof(OpenIddictEntityFrameworkTokenStore<,,,,>).MakeGenericType( diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs index ef7bfa77..876744e9 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs @@ -25,6 +25,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework { @@ -236,10 +237,7 @@ namespace OpenIddict.EntityFramework Context.Entry(token).State = EntityState.Unchanged; } - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The application was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the application from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1238), exception); } } @@ -256,7 +254,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -279,7 +277,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return await (from application in Applications @@ -298,7 +296,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } // To optimize the efficiency of the query a bit, only applications whose stringified @@ -337,7 +335,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } // To optimize the efficiency of the query a bit, only applications whose stringified @@ -734,11 +732,7 @@ namespace OpenIddict.EntityFramework catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new application instance.") - .Append("Make sure that the application entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom application store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1239), exception))); } } @@ -1119,10 +1113,7 @@ namespace OpenIddict.EntityFramework // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(application).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The application was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the application from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1238), exception); } } diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs index 22604b87..48924283 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs @@ -13,7 +13,6 @@ using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Linq; using System.Runtime.CompilerServices; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading; @@ -23,6 +22,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework { @@ -210,10 +210,7 @@ namespace OpenIddict.EntityFramework Context.Entry(token).State = EntityState.Unchanged; } - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The authorization was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the authorization from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1240), exception); } } @@ -230,12 +227,12 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } var key = ConvertIdentifierFromString(client); @@ -261,17 +258,17 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } var key = ConvertIdentifierFromString(client); @@ -299,22 +296,22 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } var key = ConvertIdentifierFromString(client); @@ -345,22 +342,22 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } return ExecuteAsync(cancellationToken); @@ -398,7 +395,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -421,7 +418,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -442,7 +439,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } return (from authorization in Authorizations.Include(authorization => authorization.Application) @@ -675,11 +672,7 @@ namespace OpenIddict.EntityFramework catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new authorization instance.") - .Append("Make sure that the authorization entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom authorization store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1241), exception))); } } @@ -810,7 +803,7 @@ namespace OpenIddict.EntityFramework if (exceptions != null) { - throw new AggregateException("An error occurred while pruning authorizations.", exceptions); + throw new AggregateException(SR.GetResourceString(SR.ID1242), exceptions); } } @@ -836,7 +829,7 @@ namespace OpenIddict.EntityFramework var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier)); if (application == null) { - throw new InvalidOperationException("The application associated with the authorization cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1243)); } authorization.Application = application; @@ -1025,10 +1018,7 @@ namespace OpenIddict.EntityFramework // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(authorization).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The authorization was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the authorization from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1240), exception); } } diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs index c43a3c24..76a07d61 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs @@ -24,6 +24,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework { @@ -159,10 +160,7 @@ namespace OpenIddict.EntityFramework // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(scope).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The scope was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the scope from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1244), exception); } } @@ -179,7 +177,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -202,7 +200,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The scope name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1201), nameof(name)); } return await (from scope in Scopes @@ -221,7 +219,7 @@ namespace OpenIddict.EntityFramework { if (names.Any(name => string.IsNullOrEmpty(name))) { - throw new ArgumentException("Scope names cannot be null or empty.", nameof(names)); + throw new ArgumentException(SR.GetResourceString(SR.ID1202), nameof(names)); } // Note: Enumerable.Contains() is deliberately used without the extension method syntax to ensure @@ -242,7 +240,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(resource)) { - throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); + throw new ArgumentException(SR.GetResourceString(SR.ID1061), nameof(resource)); } // To optimize the efficiency of the query a bit, only scopes whose stringified @@ -530,11 +528,7 @@ namespace OpenIddict.EntityFramework catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new scope instance.") - .Append("Make sure that the scope entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom scope store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1245), exception))); } } @@ -823,10 +817,7 @@ namespace OpenIddict.EntityFramework // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(scope).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The scope was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the scope from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1244), exception); } } diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs index 0d3e0b34..53a05a2e 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs @@ -12,7 +12,6 @@ using System.Data; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Linq; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading; @@ -22,6 +21,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework { @@ -173,10 +173,7 @@ namespace OpenIddict.EntityFramework // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(token).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The token was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the token from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1246), exception); } } @@ -193,12 +190,12 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } var key = ConvertIdentifierFromString(client); @@ -224,17 +221,17 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } var key = ConvertIdentifierFromString(client); @@ -262,22 +259,22 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } var key = ConvertIdentifierFromString(client); @@ -301,7 +298,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -322,7 +319,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -346,7 +343,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -370,7 +367,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return await (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization) @@ -388,7 +385,7 @@ namespace OpenIddict.EntityFramework { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } return (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization) @@ -701,11 +698,7 @@ namespace OpenIddict.EntityFramework catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new token instance.") - .Append("Make sure that the token entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom token store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1247), exception))); } } @@ -833,7 +826,7 @@ namespace OpenIddict.EntityFramework if (exceptions != null) { - throw new AggregateException("An error occurred while pruning tokens.", exceptions); + throw new AggregateException(SR.GetResourceString(SR.ID1248), exceptions); } } @@ -857,7 +850,7 @@ namespace OpenIddict.EntityFramework var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier)); if (application == null) { - throw new InvalidOperationException("The application associated with the token cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1249)); } token.Application = application; @@ -901,7 +894,7 @@ namespace OpenIddict.EntityFramework var authorization = await Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier)); if (authorization == null) { - throw new InvalidOperationException("The authorization associated with the token cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1250)); } token.Authorization = authorization; @@ -1124,10 +1117,7 @@ namespace OpenIddict.EntityFramework // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(token).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The token was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the token from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1246), exception); } } diff --git a/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs b/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs index 6acc5a6b..2ca6bd8b 100644 --- a/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs +++ b/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs @@ -11,6 +11,7 @@ using Microsoft.EntityFrameworkCore; using OpenIddict.Core; using OpenIddict.EntityFrameworkCore; using OpenIddict.EntityFrameworkCore.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace Microsoft.Extensions.DependencyInjection { @@ -108,7 +109,7 @@ namespace Microsoft.Extensions.DependencyInjection if (!typeof(DbContext).IsAssignableFrom(type)) { - throw new ArgumentException("The specified type is invalid.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1231), nameof(type)); } return Configure(options => options.DbContextType = type); diff --git a/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolver.cs b/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolver.cs index 4086f0b7..cbc82eff 100644 --- a/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolver.cs +++ b/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolver.cs @@ -6,13 +6,13 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; using OpenIddict.Extensions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore { @@ -54,22 +54,13 @@ namespace OpenIddict.EntityFrameworkCore var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictEntityFrameworkCoreApplication<,,>)); if (root == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified application type is not compatible with the Entity Framework Core stores.") - .Append("When enabling the Entity Framework Core stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkCoreApplication' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkCoreApplication' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1251)); } var context = _options.CurrentValue.DbContextType; if (context == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No Entity Framework Core context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework Core stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFrameworkCore().UseDbContext()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1252)); } return typeof(OpenIddictEntityFrameworkCoreApplicationStore<,,,,>).MakeGenericType( diff --git a/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolver.cs b/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolver.cs index 8039ee01..8756a005 100644 --- a/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolver.cs +++ b/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolver.cs @@ -6,13 +6,13 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; using OpenIddict.Extensions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore { @@ -54,22 +54,13 @@ namespace OpenIddict.EntityFrameworkCore var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictEntityFrameworkCoreAuthorization<,,>)); if (root == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified authorization type is not compatible with the Entity Framework Core stores.") - .Append("When enabling the Entity Framework Core stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkCoreAuthorization' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkCoreAuthorization' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1253)); } var context = _options.CurrentValue.DbContextType; if (context == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No Entity Framework Core context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework Core stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFrameworkCore().UseDbContext()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1252)); } return typeof(OpenIddictEntityFrameworkCoreAuthorizationStore<,,,,>).MakeGenericType( diff --git a/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolver.cs b/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolver.cs index 1a5fcf61..985dd44c 100644 --- a/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolver.cs +++ b/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolver.cs @@ -6,13 +6,13 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; using OpenIddict.Extensions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore { @@ -54,22 +54,13 @@ namespace OpenIddict.EntityFrameworkCore var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictEntityFrameworkCoreScope<>)); if (root == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified scope type is not compatible with the Entity Framework Core stores.") - .Append("When enabling the Entity Framework Core stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkCoreScope' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkCoreScope' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1254)); } var context = _options.CurrentValue.DbContextType; if (context == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No Entity Framework Core context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework Core stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFrameworkCore().UseDbContext()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1252)); } return typeof(OpenIddictEntityFrameworkCoreScopeStore<,,>).MakeGenericType( diff --git a/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolver.cs b/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolver.cs index e1cfa2a0..5dc9b1df 100644 --- a/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolver.cs +++ b/src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolver.cs @@ -6,13 +6,13 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; using OpenIddict.Extensions; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore { @@ -54,22 +54,13 @@ namespace OpenIddict.EntityFrameworkCore var root = OpenIddictHelpers.FindGenericBaseType(key, typeof(OpenIddictEntityFrameworkCoreToken<,,>)); if (root == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified token type is not compatible with the Entity Framework Core stores.") - .Append("When enabling the Entity Framework Core stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkCoreToken' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkCoreToken' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1255)); } var context = _options.CurrentValue.DbContextType; if (context == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("No Entity Framework Core context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework Core stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFrameworkCore().UseDbContext()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1252)); } return typeof(OpenIddictEntityFrameworkCoreTokenStore<,,,,>).MakeGenericType( diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs index 8c885386..df2e736f 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs @@ -26,6 +26,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore { @@ -280,10 +281,7 @@ namespace OpenIddict.EntityFrameworkCore Context.Entry(token).State = EntityState.Unchanged; } - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The application was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the application from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1238), exception); } } @@ -300,7 +298,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return await (from application in Applications.AsTracking() @@ -321,7 +319,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -342,7 +340,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } // To optimize the efficiency of the query a bit, only applications whose stringified @@ -381,7 +379,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } // To optimize the efficiency of the query a bit, only applications whose stringified @@ -778,11 +776,7 @@ namespace OpenIddict.EntityFrameworkCore catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new application instance.") - .Append("Make sure that the application entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom application store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1239), exception))); } } @@ -1163,10 +1157,7 @@ namespace OpenIddict.EntityFrameworkCore // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(application).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The application was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the application from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1238), exception); } } diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs index 9b11064e..dbc251d0 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs @@ -11,7 +11,6 @@ using System.ComponentModel; using System.Data; using System.Linq; using System.Runtime.CompilerServices; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading; @@ -24,6 +23,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore { @@ -248,10 +248,7 @@ namespace OpenIddict.EntityFrameworkCore Context.Entry(token).State = EntityState.Unchanged; } - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The authorization was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the authorization from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1240), exception); } } @@ -268,12 +265,12 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be @@ -304,17 +301,17 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be @@ -346,22 +343,22 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be @@ -397,22 +394,22 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } return ExecuteAsync(cancellationToken); @@ -455,7 +452,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be @@ -481,7 +478,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -502,7 +499,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } return (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking() @@ -736,11 +733,7 @@ namespace OpenIddict.EntityFrameworkCore catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new authorization instance.") - .Append("Make sure that the authorization entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom authorization store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1241), exception))); } } @@ -883,7 +876,7 @@ namespace OpenIddict.EntityFrameworkCore if (exceptions != null) { - throw new AggregateException("An error occurred while pruning authorizations.", exceptions); + throw new AggregateException(SR.GetResourceString(SR.ID1242), exceptions); } } @@ -913,7 +906,7 @@ namespace OpenIddict.EntityFrameworkCore if (application == null) { - throw new InvalidOperationException("The application associated with the authorization cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1243)); } authorization.Application = application; @@ -1090,10 +1083,7 @@ namespace OpenIddict.EntityFrameworkCore // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(authorization).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The authorization was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the authorization from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1240), exception); } } diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs index 305f60f6..975c2cd9 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs @@ -23,6 +23,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore { @@ -175,10 +176,7 @@ namespace OpenIddict.EntityFrameworkCore // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(scope).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The scope was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the scope from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1244), exception); } } @@ -195,7 +193,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -218,7 +216,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The scope name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1201), nameof(name)); } return await (from scope in Scopes.AsTracking() @@ -237,7 +235,7 @@ namespace OpenIddict.EntityFrameworkCore { if (names.Any(name => string.IsNullOrEmpty(name))) { - throw new ArgumentException("Scope names cannot be null or empty.", nameof(names)); + throw new ArgumentException(SR.GetResourceString(SR.ID1202), nameof(names)); } // Note: Enumerable.Contains() is deliberately used without the extension method syntax to ensure @@ -258,7 +256,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(resource)) { - throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); + throw new ArgumentException(SR.GetResourceString(SR.ID1061), nameof(resource)); } // To optimize the efficiency of the query a bit, only scopes whose stringified @@ -546,11 +544,7 @@ namespace OpenIddict.EntityFrameworkCore catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new scope instance.") - .Append("Make sure that the scope entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom scope store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1245), exception))); } } @@ -839,10 +833,7 @@ namespace OpenIddict.EntityFrameworkCore // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(scope).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The scope was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the scope from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1244), exception); } } diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs index 463fbf24..d7cbf2cc 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs @@ -10,7 +10,6 @@ using System.Collections.Immutable; using System.ComponentModel; using System.Data; using System.Linq; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading; @@ -23,6 +22,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore { @@ -195,10 +195,7 @@ namespace OpenIddict.EntityFrameworkCore // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(token).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The token was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the token from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1246), exception); } } @@ -215,12 +212,12 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be @@ -251,17 +248,17 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be @@ -294,22 +291,22 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be @@ -338,7 +335,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } // Note: due to a bug in Entity Framework Core's query visitor, the tokens can't be @@ -364,7 +361,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } // Note: due to a bug in Entity Framework Core's query visitor, the tokens can't be @@ -393,7 +390,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var key = ConvertIdentifierFromString(identifier); @@ -417,7 +414,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return await (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() @@ -435,7 +432,7 @@ namespace OpenIddict.EntityFrameworkCore { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } return (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking() @@ -749,11 +746,7 @@ namespace OpenIddict.EntityFrameworkCore catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new token instance.") - .Append("Make sure that the token entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom token store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1247), exception))); } } @@ -892,7 +885,7 @@ namespace OpenIddict.EntityFrameworkCore if (exceptions != null) { - throw new AggregateException("An error occurred while pruning tokens.", exceptions); + throw new AggregateException(SR.GetResourceString(SR.ID1248), exceptions); } } @@ -924,7 +917,7 @@ namespace OpenIddict.EntityFrameworkCore if (application == null) { - throw new InvalidOperationException("The application associated with the token cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1249)); } token.Application = application; @@ -976,7 +969,7 @@ namespace OpenIddict.EntityFrameworkCore if (authorization == null) { - throw new InvalidOperationException("The authorization associated with the token cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1250)); } token.Authorization = authorization; @@ -1217,10 +1210,7 @@ namespace OpenIddict.EntityFrameworkCore // Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing. Context.Entry(token).State = EntityState.Unchanged; - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The token was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the token from the database and retry the operation.") - .ToString(), exception); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1246), exception); } } diff --git a/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs b/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs index 1961adfa..6f09abe9 100644 --- a/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs +++ b/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs @@ -11,6 +11,7 @@ using MongoDB.Driver; using OpenIddict.Core; using OpenIddict.MongoDb; using OpenIddict.MongoDb.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace Microsoft.Extensions.DependencyInjection { @@ -107,7 +108,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The collection name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1260), nameof(name)); } return Configure(options => options.ApplicationsCollectionName = name); @@ -122,7 +123,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The collection name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1260), nameof(name)); } return Configure(options => options.AuthorizationsCollectionName = name); @@ -137,7 +138,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The collection name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1260), nameof(name)); } return Configure(options => options.ScopesCollectionName = name); @@ -152,7 +153,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The collection name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1260), nameof(name)); } return Configure(options => options.TokensCollectionName = name); diff --git a/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs b/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs index 5914cfa2..b53a10c7 100644 --- a/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs +++ b/src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs @@ -5,13 +5,13 @@ */ using System; -using System.Text; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using MongoDB.Driver; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb { @@ -54,12 +54,7 @@ namespace OpenIddict.MongoDb if (database == null) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("No suitable MongoDB database service can be found.") - .Append("To configure the OpenIddict MongoDB stores to use a specific database, use ") - .Append("'services.AddOpenIddict().AddCore().UseMongoDb().UseDatabase()' or register an ") - .Append("'IMongoDatabase' in the dependency injection container in 'ConfigureServices()'.") - .ToString()))); + new InvalidOperationException(SR.GetResourceString(SR.ID1261)))); } return new ValueTask(database); diff --git a/src/OpenIddict.MongoDb/OpenIddictMongoDbOptions.cs b/src/OpenIddict.MongoDb/OpenIddictMongoDbOptions.cs index 7191d9fc..d8abbec3 100644 --- a/src/OpenIddict.MongoDb/OpenIddictMongoDbOptions.cs +++ b/src/OpenIddict.MongoDb/OpenIddictMongoDbOptions.cs @@ -4,7 +4,6 @@ * the license and the contributors participating to this project. */ -using System; using MongoDB.Driver; namespace OpenIddict.MongoDb diff --git a/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbApplicationStoreResolver.cs b/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbApplicationStoreResolver.cs index 0d0a7cf9..d6defcc6 100644 --- a/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbApplicationStoreResolver.cs +++ b/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbApplicationStoreResolver.cs @@ -6,11 +6,11 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb { @@ -43,12 +43,7 @@ namespace OpenIddict.MongoDb { if (!typeof(OpenIddictMongoDbApplication).IsAssignableFrom(key)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified application type is not compatible with the MongoDB stores.") - .Append("When enabling the MongoDB stores, make sure you use the built-in ") - .Append("'OpenIddictMongoDbApplication' entity or a custom entity that inherits ") - .Append("from the 'OpenIddictMongoDbApplication' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1256)); } return typeof(OpenIddictMongoDbApplicationStore<>).MakeGenericType(key); diff --git a/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbAuthorizationStoreResolver.cs b/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbAuthorizationStoreResolver.cs index f4668025..8c7fbe60 100644 --- a/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbAuthorizationStoreResolver.cs +++ b/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbAuthorizationStoreResolver.cs @@ -6,11 +6,11 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb { @@ -43,12 +43,7 @@ namespace OpenIddict.MongoDb { if (!typeof(OpenIddictMongoDbAuthorization).IsAssignableFrom(key)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified authorization type is not compatible with the MongoDB stores.") - .Append("When enabling the MongoDB stores, make sure you use the built-in ") - .Append("'OpenIddictMongoDbAuthorization' entity or a custom entity that inherits ") - .Append("from the 'OpenIddictMongoDbAuthorization' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1257)); } return typeof(OpenIddictMongoDbAuthorizationStore<>).MakeGenericType(key); diff --git a/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbScopeStoreResolver.cs b/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbScopeStoreResolver.cs index 59df8e04..deb0e4be 100644 --- a/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbScopeStoreResolver.cs +++ b/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbScopeStoreResolver.cs @@ -6,11 +6,11 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb { @@ -43,12 +43,7 @@ namespace OpenIddict.MongoDb { if (!typeof(OpenIddictMongoDbScope).IsAssignableFrom(key)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified scope type is not compatible with the MongoDB stores.") - .Append("When enabling the MongoDB stores, make sure you use the built-in ") - .Append("'OpenIddictMongoDbScope' entity or a custom entity that inherits ") - .Append("from the 'OpenIddictMongoDbScope' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1258)); } return typeof(OpenIddictMongoDbScopeStore<>).MakeGenericType(key); diff --git a/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbTokenStoreResolver.cs b/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbTokenStoreResolver.cs index 24273380..981641ab 100644 --- a/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbTokenStoreResolver.cs +++ b/src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbTokenStoreResolver.cs @@ -6,11 +6,11 @@ using System; using System.Collections.Concurrent; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb { @@ -43,12 +43,7 @@ namespace OpenIddict.MongoDb { if (!typeof(OpenIddictMongoDbToken).IsAssignableFrom(key)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified token type is not compatible with the MongoDB stores.") - .Append("When enabling the MongoDB stores, make sure you use the built-in ") - .Append("'OpenIddictMongoDbToken' entity or a custom entity that inherits ") - .Append("from the 'OpenIddictMongoDbToken' entity.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1259)); } return typeof(OpenIddictMongoDbTokenStore<>).MakeGenericType(key); diff --git a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs index 7a0a4272..b62881fa 100644 --- a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs +++ b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs @@ -10,7 +10,6 @@ using System.Collections.Immutable; using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading; @@ -22,6 +21,7 @@ using MongoDB.Driver; using MongoDB.Driver.Linq; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb { @@ -129,10 +129,7 @@ namespace OpenIddict.MongoDb entity.Id == application.Id && entity.ConcurrencyToken == application.ConcurrencyToken)).DeletedCount == 0) { - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The application was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the application from the database and retry the operation.") - .ToString()); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1238)); } // Delete the authorizations associated with the application. @@ -157,7 +154,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var database = await Context.GetDatabaseAsync(cancellationToken); @@ -179,7 +176,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var database = await Context.GetDatabaseAsync(cancellationToken); @@ -200,7 +197,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } return ExecuteAsync(cancellationToken); @@ -229,7 +226,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } return ExecuteAsync(cancellationToken); @@ -556,11 +553,7 @@ namespace OpenIddict.MongoDb catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new application instance.") - .Append("Make sure that the application entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom application store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1239), exception))); } } @@ -912,10 +905,7 @@ namespace OpenIddict.MongoDb entity.Id == application.Id && entity.ConcurrencyToken == timestamp, application, null as ReplaceOptions, cancellationToken)).MatchedCount == 0) { - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The application was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the application from the database and retry the operation.") - .ToString()); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1238)); } } } diff --git a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs index 0c5e1728..0c502daa 100644 --- a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs +++ b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs @@ -9,7 +9,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Runtime.CompilerServices; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading; @@ -21,6 +20,7 @@ using MongoDB.Driver; using MongoDB.Driver.Linq; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb { @@ -128,10 +128,7 @@ namespace OpenIddict.MongoDb entity.Id == authorization.Id && entity.ConcurrencyToken == authorization.ConcurrencyToken)).DeletedCount == 0) { - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The authorization was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the authorization from the database and retry the operation.") - .ToString()); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1240)); } // Delete the tokens associated with the authorization. @@ -152,12 +149,12 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } return ExecuteAsync(cancellationToken); @@ -190,17 +187,17 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } return ExecuteAsync(cancellationToken); @@ -235,22 +232,22 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } return ExecuteAsync(cancellationToken); @@ -288,22 +285,22 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } return ExecuteAsync(cancellationToken); @@ -338,7 +335,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return ExecuteAsync(cancellationToken); @@ -369,7 +366,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var database = await Context.GetDatabaseAsync(cancellationToken); @@ -390,7 +387,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } return ExecuteAsync(cancellationToken); @@ -598,11 +595,7 @@ namespace OpenIddict.MongoDb catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new authorization instance.") - .Append("Make sure that the authorization entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom authorization store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1241), exception))); } } @@ -903,10 +896,7 @@ namespace OpenIddict.MongoDb entity.Id == authorization.Id && entity.ConcurrencyToken == timestamp, authorization, null as ReplaceOptions, cancellationToken)).MatchedCount == 0) { - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The authorization was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the authorization from the database and retry the operation.") - .ToString()); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1240)); } } } diff --git a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs index b4d3fa51..8a06dac8 100644 --- a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs +++ b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs @@ -10,7 +10,6 @@ using System.Collections.Immutable; using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading; @@ -22,6 +21,7 @@ using MongoDB.Driver; using MongoDB.Driver.Linq; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb { @@ -129,10 +129,7 @@ namespace OpenIddict.MongoDb entity.Id == scope.Id && entity.ConcurrencyToken == scope.ConcurrencyToken)).DeletedCount == 0) { - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The scope was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the scope from the database and retry the operation.") - .ToString()); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1244)); } } @@ -149,7 +146,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var database = await Context.GetDatabaseAsync(cancellationToken); @@ -171,7 +168,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The scope name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1201), nameof(name)); } var database = await Context.GetDatabaseAsync(cancellationToken); @@ -191,7 +188,7 @@ namespace OpenIddict.MongoDb { if (names.Any(name => string.IsNullOrEmpty(name))) { - throw new ArgumentException("Scope names cannot be null or empty.", nameof(names)); + throw new ArgumentException(SR.GetResourceString(SR.ID1202), nameof(names)); } return ExecuteAsync(cancellationToken); @@ -221,7 +218,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(resource)) { - throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); + throw new ArgumentException(SR.GetResourceString(SR.ID1061), nameof(resource)); } return ExecuteAsync(cancellationToken); @@ -456,11 +453,7 @@ namespace OpenIddict.MongoDb catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new scope instance.") - .Append("Make sure that the scope entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom scope store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1245), exception))); } } @@ -706,10 +699,7 @@ namespace OpenIddict.MongoDb entity.Id == scope.Id && entity.ConcurrencyToken == timestamp, scope, null as ReplaceOptions, cancellationToken)).MatchedCount == 0) { - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The scope was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the scope from the database and retry the operation.") - .ToString()); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1244)); } } } diff --git a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs index ab34e825..4ced317e 100644 --- a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs +++ b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs @@ -9,7 +9,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Runtime.CompilerServices; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading; @@ -21,6 +20,7 @@ using MongoDB.Driver; using MongoDB.Driver.Linq; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb { @@ -128,10 +128,7 @@ namespace OpenIddict.MongoDb entity.Id == token.Id && entity.ConcurrencyToken == token.ConcurrencyToken)).DeletedCount == 0) { - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The token was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the token from the database and retry the operation.") - .ToString()); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1246)); } } @@ -148,12 +145,12 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } return ExecuteAsync(cancellationToken); @@ -186,17 +183,17 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } return ExecuteAsync(cancellationToken); @@ -231,22 +228,22 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } if (string.IsNullOrEmpty(client)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(client)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(client)); } if (string.IsNullOrEmpty(status)) { - throw new ArgumentException("The status cannot be null or empty.", nameof(status)); + throw new ArgumentException(SR.GetResourceString(SR.ID1198), nameof(status)); } if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1199), nameof(type)); } return ExecuteAsync(cancellationToken); @@ -278,7 +275,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return ExecuteAsync(cancellationToken); @@ -307,7 +304,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } return ExecuteAsync(cancellationToken); @@ -338,7 +335,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var database = await Context.GetDatabaseAsync(cancellationToken); @@ -361,7 +358,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1194), nameof(identifier)); } var database = await Context.GetDatabaseAsync(cancellationToken); @@ -380,7 +377,7 @@ namespace OpenIddict.MongoDb { if (string.IsNullOrEmpty(subject)) { - throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); + throw new ArgumentException(SR.GetResourceString(SR.ID1197), nameof(subject)); } return ExecuteAsync(cancellationToken); @@ -659,11 +656,7 @@ namespace OpenIddict.MongoDb catch (MemberAccessException exception) { return new ValueTask(Task.FromException( - new InvalidOperationException(new StringBuilder() - .AppendLine("An error occurred while trying to create a new token instance.") - .Append("Make sure that the token entity is not abstract and has a public parameterless constructor ") - .Append("or create a custom token store that overrides 'InstantiateAsync()' to use a custom factory.") - .ToString(), exception))); + new InvalidOperationException(SR.GetResourceString(SR.ID1247), exception))); } } @@ -993,10 +986,7 @@ namespace OpenIddict.MongoDb entity.Id == token.Id && entity.ConcurrencyToken == timestamp, token, null as ReplaceOptions, cancellationToken)).MatchedCount == 0) { - throw new OpenIddictExceptions.ConcurrencyException(new StringBuilder() - .AppendLine("The token was concurrently updated and cannot be persisted in its current state.") - .Append("Reload the token from the database and retry the operation.") - .ToString()); + throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1246)); } } } diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs index 6a46075c..03ece7e8 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs @@ -11,6 +11,7 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Distributed; using OpenIddict.Server.AspNetCore; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace Microsoft.Extensions.DependencyInjection { @@ -158,7 +159,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(realm)) { - throw new ArgumentException("The realm cannot be null or empty.", nameof(realm)); + throw new ArgumentException(SR.GetResourceString(SR.ID1106), nameof(realm)); } return Configure(options => options.Realm = realm); diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreConfiguration.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreConfiguration.cs index 895ea390..60f3fbfd 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreConfiguration.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreConfiguration.cs @@ -6,10 +6,10 @@ using System; using System.Collections.Generic; -using System.Text; using JetBrains.Annotations; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore { @@ -36,10 +36,7 @@ namespace OpenIddict.Server.AspNetCore if (options.SchemeMap.TryGetValue(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, out var builder) && builder.HandlerType != typeof(OpenIddictServerAspNetCoreHandler)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The OpenIddict ASP.NET Core server handler cannot be registered as an authentication scheme.") - .Append("This may indicate that an instance of another handler was registered with the same scheme.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1107)); } options.AddScheme( @@ -87,12 +84,7 @@ namespace OpenIddict.Server.AspNetCore !TryValidate(options.SchemeMap, options.DefaultSignInScheme) || !TryValidate(options.SchemeMap, options.DefaultSignOutScheme)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The OpenIddict ASP.NET Core server cannot be used as the default scheme handler.") - .Append("Make sure that neither DefaultAuthenticateScheme, DefaultChallengeScheme, ") - .Append("DefaultForbidScheme, DefaultSignInScheme, DefaultSignOutScheme nor DefaultScheme ") - .Append("point to an instance of the OpenIddict ASP.NET Core server handler.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1108)); } } @@ -111,9 +103,7 @@ namespace OpenIddict.Server.AspNetCore if (options.EnableErrorPassthrough && options.EnableStatusCodePagesIntegration) { - throw new InvalidOperationException(new StringBuilder() - .Append("The error pass-through mode cannot be used when the status code pages integration is enabled.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1109)); } } } diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs index 6e70d05b..5234b058 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; using System.Security.Claims; -using System.Text; using System.Text.Encodings.Web; using System.Threading.Tasks; using JetBrains.Annotations; @@ -18,6 +17,7 @@ using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore { @@ -101,11 +101,7 @@ namespace OpenIddict.Server.AspNetCore return false; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } return false; @@ -114,7 +110,7 @@ namespace OpenIddict.Server.AspNetCore protected override async Task HandleAuthenticateAsync() { var transaction = Context.Features.Get()?.Transaction ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); // Note: in many cases, the authentication token was already validated by the time this action is called // (generally later in the pipeline, when using the pass-through mode). To avoid having to re-validate it, @@ -152,7 +148,7 @@ namespace OpenIddict.Server.AspNetCore [OpenIddictServerAspNetCoreConstants.Properties.ErrorUri] = context.ErrorUri }); - return AuthenticateResult.Fail("An error occurred while authenticating the current request.", properties); + return AuthenticateResult.Fail(SR.GetResourceString(SR.ID1112), properties); } else @@ -178,7 +174,7 @@ namespace OpenIddict.Server.AspNetCore protected override async Task HandleChallengeAsync([CanBeNull] AuthenticationProperties properties) { var transaction = Context.Features.Get()?.Transaction ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); transaction.Properties[typeof(AuthenticationProperties).FullName] = properties ?? new AuthenticationProperties(); @@ -213,11 +209,7 @@ namespace OpenIddict.Server.AspNetCore return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } } @@ -232,7 +224,7 @@ namespace OpenIddict.Server.AspNetCore } var transaction = Context.Features.Get()?.Transaction ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); transaction.Properties[typeof(AuthenticationProperties).FullName] = properties ?? new AuthenticationProperties(); @@ -268,18 +260,14 @@ namespace OpenIddict.Server.AspNetCore return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } } public async Task SignOutAsync([CanBeNull] AuthenticationProperties properties) { var transaction = Context.Features.Get()?.Transaction ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); var context = new ProcessSignOutContext(transaction) { @@ -314,11 +302,7 @@ namespace OpenIddict.Server.AspNetCore return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } } } diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs index 26c759ed..9ac21822 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs @@ -28,6 +28,7 @@ using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreConstants; using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilters; using static OpenIddict.Server.OpenIddictServerEvents; using JsonWebTokenTypes = OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreConstants.JsonWebTokenTypes; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore { @@ -69,12 +70,7 @@ namespace OpenIddict.Server.AspNetCore { private readonly IDistributedCache _cache; - public RestoreCachedRequestParameters() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public RestoreCachedRequestParameters() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public RestoreCachedRequestParameters([NotNull] IDistributedCache cache) => _cache = cache; @@ -123,7 +119,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The specified 'request_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.RequestId]); return; } @@ -141,7 +137,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The specified 'request_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.RequestId]); return; } @@ -150,7 +146,7 @@ namespace OpenIddict.Server.AspNetCore Base64UrlEncoder.Decode(((JsonWebToken) result.SecurityToken).InnerToken.EncodedPayload)); if (document.RootElement.ValueKind != JsonValueKind.Object) { - throw new InvalidOperationException("The authorization request payload is malformed."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1116)); } // Restore the authorization request parameters from the serialized payload. @@ -176,12 +172,7 @@ namespace OpenIddict.Server.AspNetCore private readonly IDistributedCache _cache; private readonly IOptionsMonitor _options; - public CacheRequestParameters() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public CacheRequestParameters() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public CacheRequestParameters( [NotNull] IDistributedCache cache, @@ -222,7 +213,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // Don't cache the request if the request doesn't include any parameter. @@ -294,12 +285,7 @@ namespace OpenIddict.Server.AspNetCore { private readonly IDistributedCache _cache; - public RemoveCachedRequest() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public RemoveCachedRequest() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public RemoveCachedRequest([NotNull] IDistributedCache cache) => _cache = cache; @@ -386,7 +372,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (string.IsNullOrEmpty(context.RedirectUri) || @@ -483,7 +469,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (string.IsNullOrEmpty(context.RedirectUri) || @@ -554,7 +540,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (string.IsNullOrEmpty(context.RedirectUri) || diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs index 0f3ad61f..6f9f3a95 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs @@ -10,7 +10,6 @@ using System.Collections.Immutable; using System.Linq; using System.Security.Claims; using System.Security.Cryptography; -using System.Text; using System.Text.Json; using System.Threading.Tasks; using JetBrains.Annotations; @@ -26,6 +25,7 @@ using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreConstants; using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilters; using static OpenIddict.Server.OpenIddictServerEvents; using JsonWebTokenTypes = OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreConstants.JsonWebTokenTypes; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore { @@ -67,12 +67,7 @@ namespace OpenIddict.Server.AspNetCore { private readonly IDistributedCache _cache; - public RestoreCachedRequestParameters() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public RestoreCachedRequestParameters() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public RestoreCachedRequestParameters([NotNull] IDistributedCache cache) => _cache = cache; @@ -121,7 +116,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The specified 'request_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.RequestId]); return; } @@ -139,7 +134,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The specified 'request_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.RequestId]); return; } @@ -148,7 +143,7 @@ namespace OpenIddict.Server.AspNetCore Base64UrlEncoder.Decode(((JsonWebToken) result.SecurityToken).InnerToken.EncodedPayload)); if (document.RootElement.ValueKind != JsonValueKind.Object) { - throw new InvalidOperationException("The logout request payload is malformed."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1117)); } // Restore the authorization request parameters from the serialized payload. @@ -174,12 +169,7 @@ namespace OpenIddict.Server.AspNetCore private readonly IDistributedCache _cache; private readonly IOptionsMonitor _options; - public CacheRequestParameters() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public CacheRequestParameters() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public CacheRequestParameters( [NotNull] IDistributedCache cache, @@ -220,7 +210,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // Don't cache the request if the request doesn't include any parameter. @@ -292,12 +282,7 @@ namespace OpenIddict.Server.AspNetCore { private readonly IDistributedCache _cache; - public RemoveCachedRequest() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public RemoveCachedRequest() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public RemoveCachedRequest([NotNull] IDistributedCache cache) => _cache = cache; @@ -379,7 +364,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (string.IsNullOrEmpty(context.PostLogoutRedirectUri)) diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs index 2d50d1e1..aaa8293f 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs @@ -28,6 +28,7 @@ using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilte using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlers; using Properties = OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreConstants.Properties; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore { @@ -102,7 +103,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } context.EndpointType = @@ -205,7 +206,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // Don't require that the request host be present if the request is not handled @@ -219,7 +220,7 @@ namespace OpenIddict.Server.AspNetCore { context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'Host' header is missing."); + description: context.Localizer[SR.ID3081]); return default; } @@ -229,7 +230,7 @@ namespace OpenIddict.Server.AspNetCore { context.Reject( error: Errors.InvalidRequest, - description: "The specified 'Host' header is invalid."); + description: context.Localizer[SR.ID3082]); return default; } @@ -277,7 +278,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // Don't require that the host be present if the request is not handled by OpenIddict. @@ -291,7 +292,7 @@ namespace OpenIddict.Server.AspNetCore { context.Reject( error: Errors.InvalidRequest, - description: "This server only accepts HTTPS requests."); + description: context.Localizer[SR.ID3083]); return default; } @@ -394,10 +395,7 @@ namespace OpenIddict.Server.AspNetCore string value => value, string[] value => value, - _ => throw new InvalidOperationException(new StringBuilder() - .Append("Only strings, booleans, integers, arrays of strings and instances of type ") - .Append("'OpenIddictParameter' or 'JsonElement' can be returned as custom parameters.") - .ToString()) + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1114)) }); } @@ -441,7 +439,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (HttpMethods.IsGet(request.Method)) @@ -456,7 +454,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The specified HTTP method is not valid."); + description: context.Localizer[SR.ID3084]); return default; } @@ -501,7 +499,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (HttpMethods.IsGet(request.Method)) @@ -518,7 +516,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'Content-Type' header must be specified."); + description: context.Localizer[SR.ID3081, HeaderNames.ContentType]); return; } @@ -531,7 +529,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The specified 'Content-Type' header is not valid."); + description: context.Localizer[SR.ID3082, HeaderNames.ContentType]); return; } @@ -546,7 +544,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The specified HTTP method is not valid."); + description: context.Localizer[SR.ID3084]); return; } @@ -589,7 +587,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (HttpMethods.IsPost(request.Method)) @@ -601,7 +599,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'Content-Type' header must be specified."); + description: context.Localizer[SR.ID3081, HeaderNames.ContentType]); return; } @@ -614,7 +612,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The specified 'Content-Type' header is not valid."); + description: context.Localizer[SR.ID3082, HeaderNames.ContentType]); return; } @@ -629,7 +627,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "The specified HTTP method is not valid."); + description: context.Localizer[SR.ID3084]); return; } @@ -673,7 +671,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } string header = request.Headers[HeaderNames.Authorization]; @@ -690,7 +688,7 @@ namespace OpenIddict.Server.AspNetCore context.Reject( error: Errors.InvalidRequest, - description: "Multiple client credentials cannot be specified."); + description: context.Localizer[SR.ID3087]); return default; } @@ -705,7 +703,7 @@ namespace OpenIddict.Server.AspNetCore { context.Reject( error: Errors.InvalidRequest, - description: "The specified client credentials are invalid."); + description: context.Localizer[SR.ID3055]); return default; } @@ -721,7 +719,7 @@ namespace OpenIddict.Server.AspNetCore { context.Reject( error: Errors.InvalidRequest, - description: "The specified client credentials are invalid."); + description: context.Localizer[SR.ID3055]); return default; } @@ -775,7 +773,7 @@ namespace OpenIddict.Server.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } string header = request.Headers[HeaderNames.Authorization]; @@ -867,7 +865,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // When client authentication is made using basic authentication, the authorization server MUST return @@ -931,7 +929,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // Prevent the response from being cached. @@ -984,7 +982,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // When client authentication is made using basic authentication, the authorization server MUST return @@ -1102,7 +1100,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // If the response doesn't contain a WWW-Authenticate header, don't return an empty response. @@ -1154,7 +1152,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } context.Logger.LogInformation("The response was successfully returned as a JSON document: {Response}.", context.Response); @@ -1217,7 +1215,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (string.IsNullOrEmpty(context.Response.Error)) @@ -1269,7 +1267,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (string.IsNullOrEmpty(context.Response.Error)) @@ -1332,7 +1330,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (string.IsNullOrEmpty(context.Response.Error)) @@ -1414,7 +1412,7 @@ namespace OpenIddict.Server.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } var properties = context.Transaction.GetProperty(typeof(AuthenticationProperties).FullName); diff --git a/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs b/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs index e0dece81..049dc2f8 100644 --- a/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs +++ b/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs @@ -24,6 +24,7 @@ using static OpenIddict.Server.OpenIddictServerHandlerFilters; using static OpenIddict.Server.OpenIddictServerHandlers; using Properties = OpenIddict.Server.OpenIddictServerConstants.Properties; using Schemes = OpenIddict.Server.DataProtection.OpenIddictServerDataProtectionConstants.Purposes.Schemes; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.DataProtection { @@ -35,7 +36,7 @@ namespace OpenIddict.Server.DataProtection * Authentication processing: */ ValidateDataProtectionToken.Descriptor, - + /* * Sign-in processing: */ @@ -108,7 +109,7 @@ namespace OpenIddict.Server.DataProtection OpenIddictServerEndpointType.Token => Errors.InvalidGrant, _ => Errors.InvalidToken }, - description: "The specified token is not valid."); + description: context.Localizer[SR.ID3027]); return default; } @@ -146,7 +147,7 @@ namespace OpenIddict.Server.DataProtection TokenTypeHints.RefreshToken => new[] { Handlers.Server, Formats.RefreshToken, Schemes.Server }, TokenTypeHints.UserCode => new[] { Handlers.Server, Formats.UserCode, Schemes.Server }, - _ => throw new InvalidOperationException("The specified token type is not supported.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1002)) }); try diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs index 3a6a6a6e..a49a5a1f 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Caching.Distributed; using Microsoft.Owin; using OpenIddict.Server.Owin; using Owin; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace Microsoft.Extensions.DependencyInjection { @@ -147,7 +148,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(realm)) { - throw new ArgumentException("The realm cannot be null or empty.", nameof(realm)); + throw new ArgumentException(SR.GetResourceString(SR.ID1106), nameof(realm)); } return Configure(options => options.Realm = realm); diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinConfiguration.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinConfiguration.cs index f87105d0..16f166f7 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinConfiguration.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinConfiguration.cs @@ -5,10 +5,10 @@ */ using System; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.Options; using Microsoft.Owin.Security; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin { @@ -38,10 +38,7 @@ namespace OpenIddict.Server.Owin if (options.AuthenticationMode == AuthenticationMode.Active) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The OpenIddict OWIN server handler cannot be used as an active authentication handler.") - .Append("Make sure that 'OpenIddictServerOwinOptions.AuthenticationMode' is not set to 'Active'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1118)); } } } diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs index 233e944a..09e7587b 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; using System.Security.Claims; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Owin; @@ -16,6 +15,7 @@ using Microsoft.Owin.Security.Infrastructure; using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin { @@ -70,10 +70,10 @@ namespace OpenIddict.Server.Owin // active authentication is used, as AuthenticateCoreAsync() is always called before InvokeAsync() in this case. var transaction = Context.Get(typeof(OpenIddictServerTransaction).FullName) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); var context = transaction.GetProperty(typeof(ProcessRequestContext).FullName) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); if (context.IsRequestHandled) { @@ -108,12 +108,8 @@ namespace OpenIddict.Server.Owin { return false; } + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); } return false; @@ -124,7 +120,7 @@ namespace OpenIddict.Server.Owin var transaction = Context.Get(typeof(OpenIddictServerTransaction).FullName); if (transaction == null) { - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); } // Note: in many cases, the authentication token was already validated by the time this action is called @@ -200,7 +196,7 @@ namespace OpenIddict.Server.Owin if (challenge != null && (Response.StatusCode == 401 || Response.StatusCode == 403)) { var transaction = Context.Get(typeof(OpenIddictServerTransaction).FullName) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); transaction.Properties[typeof(AuthenticationProperties).FullName] = challenge.Properties ?? new AuthenticationProperties(); @@ -235,11 +231,7 @@ namespace OpenIddict.Server.Owin return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } } @@ -247,7 +239,7 @@ namespace OpenIddict.Server.Owin if (signin != null) { var transaction = Context.Get(typeof(OpenIddictServerTransaction).FullName) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); transaction.Properties[typeof(AuthenticationProperties).FullName] = signin.Properties ?? new AuthenticationProperties(); @@ -283,11 +275,7 @@ namespace OpenIddict.Server.Owin return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } } @@ -295,7 +283,7 @@ namespace OpenIddict.Server.Owin if (signout != null) { var transaction = Context.Get(typeof(OpenIddictServerTransaction).FullName) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1111)); transaction.Properties[typeof(AuthenticationProperties).FullName] = signout.Properties ?? new AuthenticationProperties(); @@ -330,11 +318,7 @@ namespace OpenIddict.Server.Owin return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } } } diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs index d58448b5..10d39d0c 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs @@ -28,6 +28,7 @@ using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.Owin.OpenIddictServerOwinConstants; using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters; using JsonWebTokenTypes = OpenIddict.Server.Owin.OpenIddictServerOwinConstants.JsonWebTokenTypes; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin { @@ -68,12 +69,7 @@ namespace OpenIddict.Server.Owin { private readonly IDistributedCache _cache; - public RestoreCachedRequestParameters() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public RestoreCachedRequestParameters() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public RestoreCachedRequestParameters([NotNull] IDistributedCache cache) => _cache = cache; @@ -122,7 +118,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The specified 'request_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.RequestId]); return; } @@ -140,7 +136,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The specified 'request_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.RequestId]); return; } @@ -149,7 +145,7 @@ namespace OpenIddict.Server.Owin Base64UrlEncoder.Decode(((JsonWebToken) result.SecurityToken).InnerToken.EncodedPayload)); if (document.RootElement.ValueKind != JsonValueKind.Object) { - throw new InvalidOperationException("The authorization request payload is malformed."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1116)); } // Restore the authorization request parameters from the serialized payload. @@ -175,12 +171,7 @@ namespace OpenIddict.Server.Owin private readonly IDistributedCache _cache; private readonly IOptionsMonitor _options; - public CacheRequestParameters() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public CacheRequestParameters() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public CacheRequestParameters( [NotNull] IDistributedCache cache, @@ -221,7 +212,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // Don't cache the request if the request doesn't include any parameter. @@ -288,12 +279,7 @@ namespace OpenIddict.Server.Owin { private readonly IDistributedCache _cache; - public RemoveCachedRequest() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public RemoveCachedRequest() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public RemoveCachedRequest([NotNull] IDistributedCache cache) => _cache = cache; @@ -380,7 +366,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.IsNullOrEmpty(context.RedirectUri) || @@ -478,7 +464,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.IsNullOrEmpty(context.RedirectUri) || @@ -549,7 +535,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.IsNullOrEmpty(context.RedirectUri) || diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Device.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Device.cs index f544df5b..ed1dc39f 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Device.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Device.cs @@ -5,8 +5,8 @@ */ using System.Collections.Immutable; -using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters; using static OpenIddict.Server.OpenIddictServerEvents; +using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters; namespace OpenIddict.Server.Owin { diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs index 5c5b3e75..a0265143 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs @@ -10,7 +10,6 @@ using System.Collections.Immutable; using System.Linq; using System.Security.Claims; using System.Security.Cryptography; -using System.Text; using System.Text.Json; using System.Threading.Tasks; using JetBrains.Annotations; @@ -26,6 +25,7 @@ using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.Owin.OpenIddictServerOwinConstants; using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters; using JsonWebTokenTypes = OpenIddict.Server.Owin.OpenIddictServerOwinConstants.JsonWebTokenTypes; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin { @@ -66,12 +66,7 @@ namespace OpenIddict.Server.Owin { private readonly IDistributedCache _cache; - public RestoreCachedRequestParameters() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public RestoreCachedRequestParameters() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public RestoreCachedRequestParameters([NotNull] IDistributedCache cache) => _cache = cache; @@ -120,7 +115,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The specified 'request_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.RequestId]); return; } @@ -138,7 +133,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The specified 'request_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.RequestId]); return; } @@ -147,7 +142,7 @@ namespace OpenIddict.Server.Owin Base64UrlEncoder.Decode(((JsonWebToken) result.SecurityToken).InnerToken.EncodedPayload)); if (document.RootElement.ValueKind != JsonValueKind.Object) { - throw new InvalidOperationException("The logout request payload is malformed."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1117)); } // Restore the authorization request parameters from the serialized payload @@ -173,12 +168,7 @@ namespace OpenIddict.Server.Owin private readonly IDistributedCache _cache; private readonly IOptionsMonitor _options; - public CacheRequestParameters() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public CacheRequestParameters() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public CacheRequestParameters( [NotNull] IDistributedCache cache, @@ -219,7 +209,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // Don't cache the request if the request doesn't include any parameter. @@ -286,12 +276,7 @@ namespace OpenIddict.Server.Owin { private readonly IDistributedCache _cache; - public RemoveCachedRequest() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("A distributed cache instance must be registered when enabling request caching.") - .Append("To register the default in-memory distributed cache implementation, reference the ") - .Append("'Microsoft.Extensions.Caching.Memory' package and call ") - .Append("'services.AddDistributedMemoryCache()' from 'ConfigureServices'.") - .ToString()); + public RemoveCachedRequest() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1115)); public RemoveCachedRequest([NotNull] IDistributedCache cache) => _cache = cache; @@ -373,7 +358,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.IsNullOrEmpty(context.PostLogoutRedirectUri)) diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs index 679fe9d3..bbbc8819 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs @@ -25,6 +25,7 @@ using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlers; using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlerFilters; using Properties = OpenIddict.Server.Owin.OpenIddictServerOwinConstants.Properties; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin { @@ -38,7 +39,7 @@ namespace OpenIddict.Server.Owin InferEndpointType.Descriptor, InferIssuerFromHost.Descriptor, ValidateTransportSecurityRequirement.Descriptor, - + /* * Challenge processing: */ @@ -90,7 +91,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } context.EndpointType = @@ -193,7 +194,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // Don't require that the request host be present if the request is not handled @@ -207,7 +208,7 @@ namespace OpenIddict.Server.Owin { context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'Host' header is missing."); + description: context.Localizer[SR.ID3081]); return default; } @@ -217,7 +218,7 @@ namespace OpenIddict.Server.Owin { context.Reject( error: Errors.InvalidRequest, - description: "The specified 'Host' header is invalid."); + description: context.Localizer[SR.ID3082]); return default; } @@ -265,7 +266,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // Don't require that the host be present if the request is not handled by OpenIddict. @@ -279,7 +280,7 @@ namespace OpenIddict.Server.Owin { context.Reject( error: Errors.InvalidRequest, - description: "This server only accepts HTTPS requests."); + description: context.Localizer[SR.ID3083]); return default; } @@ -371,7 +372,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.Equals(request.Method, "GET", StringComparison.OrdinalIgnoreCase)) @@ -386,7 +387,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The specified HTTP method is not valid."); + description: context.Localizer[SR.ID3084]); return default; } @@ -431,7 +432,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.Equals(request.Method, "GET", StringComparison.OrdinalIgnoreCase)) @@ -448,7 +449,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'Content-Type' header must be specified."); + description: context.Localizer[SR.ID3081, "Content-Type"]); return; } @@ -461,7 +462,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The specified 'Content-Type' header is not valid."); + description: context.Localizer[SR.ID3082, "Content-Type"]); return; } @@ -476,7 +477,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The specified HTTP method is not valid."); + description: context.Localizer[SR.ID3084]); return; } @@ -519,7 +520,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.Equals(request.Method, "POST", StringComparison.OrdinalIgnoreCase)) @@ -531,7 +532,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'Content-Type' header must be specified."); + description: context.Localizer[SR.ID3081, "Content-Type"]); return; } @@ -544,7 +545,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The specified 'Content-Type' header is not valid."); + description: context.Localizer[SR.ID3082, "Content-Type"]); return; } @@ -559,7 +560,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "The specified HTTP method is not valid."); + description: context.Localizer[SR.ID3084]); return; } @@ -603,7 +604,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } var header = request.Headers["Authorization"]; @@ -620,7 +621,7 @@ namespace OpenIddict.Server.Owin context.Reject( error: Errors.InvalidRequest, - description: "Multiple client credentials cannot be specified."); + description: context.Localizer[SR.ID3087]); return default; } @@ -635,7 +636,7 @@ namespace OpenIddict.Server.Owin { context.Reject( error: Errors.InvalidRequest, - description: "The specified client credentials are invalid."); + description: context.Localizer[SR.ID3055]); return default; } @@ -651,7 +652,7 @@ namespace OpenIddict.Server.Owin { context.Reject( error: Errors.InvalidRequest, - description: "The specified client credentials are invalid."); + description: context.Localizer[SR.ID3055]); return default; } @@ -705,7 +706,7 @@ namespace OpenIddict.Server.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } var header = request.Headers["Authorization"]; @@ -797,7 +798,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // When client authentication is made using basic authentication, the authorization server MUST return @@ -861,7 +862,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // Prevent the response from being cached. @@ -914,7 +915,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // When client authentication is made using basic authentication, the authorization server MUST return @@ -1032,7 +1033,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // If the response doesn't contain a WWW-Authenticate header, don't return an empty response. @@ -1084,7 +1085,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } context.Logger.LogInformation("The response was successfully returned as a JSON document: {Response}.", context.Response); @@ -1147,7 +1148,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.IsNullOrEmpty(context.Response.Error)) @@ -1201,7 +1202,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.IsNullOrEmpty(context.Response.Error)) @@ -1283,7 +1284,7 @@ namespace OpenIddict.Server.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } var properties = context.Transaction.GetProperty(typeof(AuthenticationProperties).FullName); diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinMiddlewareFactory.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinMiddlewareFactory.cs index 44b45754..794cbb59 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinMiddlewareFactory.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinMiddlewareFactory.cs @@ -5,12 +5,12 @@ */ using System; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Microsoft.Owin; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin { @@ -48,13 +48,7 @@ namespace OpenIddict.Server.Owin var provider = context.Get(typeof(IServiceProvider).FullName); if (provider == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("No service provider was found in the OWIN context. For the OpenIddict server ") - .Append("services to work correctly, a per-request 'IServiceProvider' must be attached ") - .AppendLine("to the OWIN environment with the dictionary key 'System.IServiceProvider'.") - .Append("Note: when using a dependency injection container supporting middleware resolution ") - .Append("(like Autofac), the 'app.UseOpenIddictServer()' extension MUST NOT be called.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1120)); } // Note: the Microsoft.Extensions.DependencyInjection container doesn't support resolving services @@ -69,11 +63,8 @@ namespace OpenIddict.Server.Owin return middleware.Invoke(context); - static T GetRequiredService(IServiceProvider provider) - => provider.GetService() ?? throw new InvalidOperationException(new StringBuilder() - .AppendLine("The OpenIddict server services cannot be resolved from the DI container.") - .Append("To register the OWIN services, use 'services.AddOpenIddict().AddServer().UseOwin()'.") - .ToString()); + static T GetRequiredService(IServiceProvider provider) => provider.GetService() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID1121)); } } } diff --git a/src/OpenIddict.Server/OpenIddict.Server.csproj b/src/OpenIddict.Server/OpenIddict.Server.csproj index aea5e1c0..f0514752 100644 --- a/src/OpenIddict.Server/OpenIddict.Server.csproj +++ b/src/OpenIddict.Server/OpenIddict.Server.csproj @@ -17,6 +17,7 @@ To use the server feature on ASP.NET Core or OWIN/Katana, reference the OpenIddi + diff --git a/src/OpenIddict.Server/OpenIddictServerBuilder.cs b/src/OpenIddict.Server/OpenIddictServerBuilder.cs index 2973c5a8..35f325d7 100644 --- a/src/OpenIddict.Server/OpenIddictServerBuilder.cs +++ b/src/OpenIddict.Server/OpenIddictServerBuilder.cs @@ -12,12 +12,12 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.IdentityModel.Tokens; using OpenIddict.Server; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute; namespace Microsoft.Extensions.DependencyInjection @@ -171,7 +171,7 @@ namespace Microsoft.Extensions.DependencyInjection if (key is AsymmetricSecurityKey asymmetricSecurityKey && asymmetricSecurityKey.PrivateKeyStatus == PrivateKeyStatus.DoesNotExist) { - throw new InvalidOperationException("The asymmetric encryption key doesn't contain the required private key."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1054)); } if (key.IsSupportedAlgorithm(SecurityAlgorithms.Aes256KW)) @@ -186,10 +186,7 @@ namespace Microsoft.Extensions.DependencyInjection SecurityAlgorithms.RsaOAEP, SecurityAlgorithms.Aes256CbcHmacSha512)); } - throw new InvalidOperationException(new StringBuilder() - .AppendLine("An encryption algorithm cannot be automatically inferred from the encrypting key.") - .Append("Consider using 'options.AddEncryptionCredentials(EncryptingCredentials)' instead.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1055)); } /// @@ -277,7 +274,7 @@ namespace Microsoft.Extensions.DependencyInjection return AddEncryptionCertificate(certificate); #else - throw new PlatformNotSupportedException("X.509 certificate generation is not supported on this platform."); + throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID1263)); #endif } @@ -303,7 +300,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(algorithm)) { - throw new ArgumentException("The algorithm cannot be null or empty.", nameof(algorithm)); + throw new ArgumentException(SR.GetResourceString(SR.ID1056), nameof(algorithm)); } switch (algorithm) @@ -317,7 +314,7 @@ namespace Microsoft.Extensions.DependencyInjection return AddEncryptionCredentials(new EncryptingCredentials(CreateRsaSecurityKey(2048), algorithm, SecurityAlgorithms.Aes256CbcHmacSha512)); - default: throw new InvalidOperationException("The specified algorithm is not supported."); + default: throw new InvalidOperationException(SR.GetResourceString(SR.ID1057)); } static SymmetricSecurityKey CreateSymmetricSecurityKey(int size) @@ -359,7 +356,7 @@ namespace Microsoft.Extensions.DependencyInjection if (algorithm.KeySize < size) { - throw new InvalidOperationException("RSA key generation failed."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1058)); } return new RsaSecurityKey(algorithm); @@ -386,13 +383,13 @@ namespace Microsoft.Extensions.DependencyInjection var extensions = certificate.Extensions.OfType().ToList(); if (extensions.Count != 0 && !extensions.Any(extension => extension.KeyUsages.HasFlag(X509KeyUsageFlags.KeyEncipherment))) { - throw new InvalidOperationException("The specified certificate is not a key encryption certificate."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1059)); } } if (!certificate.HasPrivateKey) { - throw new InvalidOperationException("The specified certificate doesn't contain the required private key."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1060)); } return AddEncryptionKey(new X509SecurityKey(certificate)); @@ -435,18 +432,18 @@ namespace Microsoft.Extensions.DependencyInjection if (string.IsNullOrEmpty(resource)) { - throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); + throw new ArgumentException(SR.GetResourceString(SR.ID1061), nameof(resource)); } if (string.IsNullOrEmpty(password)) { - throw new ArgumentException("The password cannot be null or empty.", nameof(password)); + throw new ArgumentException(SR.GetResourceString(SR.ID1062), nameof(password)); } using var stream = assembly.GetManifestResourceStream(resource); if (stream == null) { - throw new InvalidOperationException("The certificate was not found in the specified assembly."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1063)); } return AddEncryptionCertificate(stream, password, flags); @@ -490,7 +487,7 @@ namespace Microsoft.Extensions.DependencyInjection if (string.IsNullOrEmpty(password)) { - throw new ArgumentException("The password cannot be null or empty.", nameof(password)); + throw new ArgumentException(SR.GetResourceString(SR.ID1062), nameof(password)); } using var buffer = new MemoryStream(); @@ -508,13 +505,13 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(thumbprint)) { - throw new ArgumentException("The thumbprint cannot be null or empty.", nameof(thumbprint)); + throw new ArgumentException(SR.GetResourceString(SR.ID1064), nameof(thumbprint)); } var certificate = GetCertificate(StoreLocation.CurrentUser, thumbprint) ?? GetCertificate(StoreLocation.LocalMachine, thumbprint); if (certificate == null) { - throw new InvalidOperationException("The certificate corresponding to the specified thumbprint was not found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1065)); } return AddEncryptionCertificate(certificate); @@ -542,7 +539,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(thumbprint)) { - throw new ArgumentException("The thumbprint cannot be null or empty.", nameof(thumbprint)); + throw new ArgumentException(SR.GetResourceString(SR.ID1064), nameof(thumbprint)); } using var store = new X509Store(name, location); @@ -554,7 +551,7 @@ namespace Microsoft.Extensions.DependencyInjection if (certificate == null) { - throw new InvalidOperationException("The certificate corresponding to the specified thumbprint was not found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1065)); } return AddEncryptionCertificate(certificate); @@ -591,7 +588,7 @@ namespace Microsoft.Extensions.DependencyInjection if (key is AsymmetricSecurityKey asymmetricSecurityKey && asymmetricSecurityKey.PrivateKeyStatus == PrivateKeyStatus.DoesNotExist) { - throw new InvalidOperationException("The asymmetric signing key doesn't contain the required private key."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1066)); } if (key.IsSupportedAlgorithm(SecurityAlgorithms.RsaSha256)) @@ -625,14 +622,11 @@ namespace Microsoft.Extensions.DependencyInjection key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha384) || key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha512)) { - throw new PlatformNotSupportedException("ECDSA signing keys are not supported on this platform."); + throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID1068)); } #endif - throw new InvalidOperationException(new StringBuilder() - .AppendLine("A signature algorithm cannot be automatically inferred from the signing key.") - .Append("Consider using 'options.AddSigningCredentials(SigningCredentials)' instead.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1067)); } /// @@ -720,7 +714,7 @@ namespace Microsoft.Extensions.DependencyInjection return AddSigningCertificate(certificate); #else - throw new PlatformNotSupportedException("X.509 certificate generation is not supported on this platform."); + throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID1263)); #endif } @@ -748,7 +742,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(algorithm)) { - throw new ArgumentException("The algorithm cannot be null or empty.", nameof(algorithm)); + throw new ArgumentException(SR.GetResourceString(SR.ID1056), nameof(algorithm)); } switch (algorithm) @@ -790,10 +784,10 @@ namespace Microsoft.Extensions.DependencyInjection case SecurityAlgorithms.EcdsaSha256Signature: case SecurityAlgorithms.EcdsaSha384Signature: case SecurityAlgorithms.EcdsaSha512Signature: - throw new PlatformNotSupportedException("ECDSA signing keys are not supported on this platform."); + throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID1068)); #endif - default: throw new InvalidOperationException("The specified algorithm is not supported."); + default: throw new InvalidOperationException(SR.GetResourceString(SR.ID1057)); } [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", @@ -821,7 +815,7 @@ namespace Microsoft.Extensions.DependencyInjection if (algorithm.KeySize < size) { - throw new InvalidOperationException("RSA key generation failed."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1058)); } return new RsaSecurityKey(algorithm); @@ -848,13 +842,13 @@ namespace Microsoft.Extensions.DependencyInjection var extensions = certificate.Extensions.OfType().ToList(); if (extensions.Count != 0 && !extensions.Any(extension => extension.KeyUsages.HasFlag(X509KeyUsageFlags.DigitalSignature))) { - throw new InvalidOperationException("The specified certificate is not a signing certificate."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1069)); } } if (!certificate.HasPrivateKey) { - throw new InvalidOperationException("The specified certificate doesn't contain the required private key."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1060)); } return AddSigningKey(new X509SecurityKey(certificate)); @@ -897,18 +891,18 @@ namespace Microsoft.Extensions.DependencyInjection if (string.IsNullOrEmpty(resource)) { - throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); + throw new ArgumentException(SR.GetResourceString(SR.ID1061), nameof(resource)); } if (string.IsNullOrEmpty(password)) { - throw new ArgumentException("The password cannot be null or empty.", nameof(password)); + throw new ArgumentException(SR.GetResourceString(SR.ID1062), nameof(password)); } using var stream = assembly.GetManifestResourceStream(resource); if (stream == null) { - throw new InvalidOperationException("The certificate was not found in the specified assembly."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1063)); } return AddSigningCertificate(stream, password, flags); @@ -952,7 +946,7 @@ namespace Microsoft.Extensions.DependencyInjection if (string.IsNullOrEmpty(password)) { - throw new ArgumentException("The password cannot be null or empty.", nameof(password)); + throw new ArgumentException(SR.GetResourceString(SR.ID1062), nameof(password)); } using var buffer = new MemoryStream(); @@ -970,13 +964,13 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(thumbprint)) { - throw new ArgumentException("The thumbprint cannot be null or empty.", nameof(thumbprint)); + throw new ArgumentException(SR.GetResourceString(SR.ID1064), nameof(thumbprint)); } var certificate = GetCertificate(StoreLocation.CurrentUser, thumbprint) ?? GetCertificate(StoreLocation.LocalMachine, thumbprint); if (certificate == null) { - throw new InvalidOperationException("The certificate corresponding to the specified thumbprint was not found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1065)); } return AddSigningCertificate(certificate); @@ -1004,7 +998,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(thumbprint)) { - throw new ArgumentException("The thumbprint cannot be null or empty.", nameof(thumbprint)); + throw new ArgumentException(SR.GetResourceString(SR.ID1064), nameof(thumbprint)); } using var store = new X509Store(name, location); @@ -1016,7 +1010,7 @@ namespace Microsoft.Extensions.DependencyInjection if (certificate == null) { - throw new InvalidOperationException("The certificate corresponding to the specified thumbprint was not found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1065)); } return AddSigningCertificate(certificate); @@ -1049,7 +1043,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(type)) { - throw new ArgumentException("The grant type cannot be null or empty.", nameof(type)); + throw new ArgumentException(SR.GetResourceString(SR.ID1070), nameof(type)); } return Configure(options => options.GrantTypes.Add(type)); @@ -1122,7 +1116,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1165,7 +1159,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1208,7 +1202,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1251,7 +1245,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1294,7 +1288,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1337,7 +1331,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1380,7 +1374,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1423,7 +1417,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1466,7 +1460,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1509,7 +1503,7 @@ namespace Microsoft.Extensions.DependencyInjection if (addresses.Any(address => !address.IsWellFormedOriginalString())) { - throw new ArgumentException("One of the specified addresses is not valid.", nameof(addresses)); + throw new ArgumentException(SR.GetResourceString(SR.ID1071), nameof(addresses)); } return Configure(options => @@ -1616,7 +1610,7 @@ namespace Microsoft.Extensions.DependencyInjection if (claims.Any(claim => string.IsNullOrEmpty(claim))) { - throw new ArgumentException("Claims cannot be null or empty.", nameof(claims)); + throw new ArgumentException(SR.GetResourceString(SR.ID1072), nameof(claims)); } return Configure(options => options.Claims.UnionWith(claims)); @@ -1637,7 +1631,7 @@ namespace Microsoft.Extensions.DependencyInjection if (scopes.Any(scope => string.IsNullOrEmpty(scope))) { - throw new ArgumentException("Scopes cannot be null or empty.", nameof(scopes)); + throw new ArgumentException(SR.GetResourceString(SR.ID1073), nameof(scopes)); } return Configure(options => options.Scopes.UnionWith(scopes)); diff --git a/src/OpenIddict.Server/OpenIddictServerConfiguration.cs b/src/OpenIddict.Server/OpenIddictServerConfiguration.cs index 66c24cb3..7fc89f18 100644 --- a/src/OpenIddict.Server/OpenIddictServerConfiguration.cs +++ b/src/OpenIddict.Server/OpenIddictServerConfiguration.cs @@ -7,13 +7,13 @@ using System; using System.Diagnostics; using System.Linq; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -37,13 +37,13 @@ namespace OpenIddict.Server if (options.JsonWebTokenHandler == null) { - throw new InvalidOperationException("The security token handler cannot be null."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1074)); } // Ensure at least one flow has been enabled. if (options.GrantTypes.Count == 0) { - throw new InvalidOperationException("At least one OAuth 2.0/OpenID Connect flow must be enabled."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1075)); } // Ensure the authorization endpoint has been enabled when @@ -51,15 +51,13 @@ namespace OpenIddict.Server if (options.AuthorizationEndpointUris.Count == 0 && (options.GrantTypes.Contains(GrantTypes.AuthorizationCode) || options.GrantTypes.Contains(GrantTypes.Implicit))) { - throw new InvalidOperationException(new StringBuilder() - .Append("The authorization endpoint must be enabled to use the authorization code and implicit flows.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1076)); } // Ensure the device endpoint has been enabled when the device grant is supported. if (options.DeviceEndpointUris.Count == 0 && options.GrantTypes.Contains(GrantTypes.DeviceCode)) { - throw new InvalidOperationException("The device endpoint must be enabled to use the device flow."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1077)); } // Ensure the token endpoint has been enabled when the authorization code, @@ -70,83 +68,60 @@ namespace OpenIddict.Server options.GrantTypes.Contains(GrantTypes.Password) || options.GrantTypes.Contains(GrantTypes.RefreshToken))) { - throw new InvalidOperationException(new StringBuilder() - .Append("The token endpoint must be enabled to use the authorization code, ") - .Append("client credentials, device, password and refresh token flows.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1078)); } // Ensure the verification endpoint has been enabled when the device grant is supported. if (options.VerificationEndpointUris.Count == 0 && options.GrantTypes.Contains(GrantTypes.DeviceCode)) { - throw new InvalidOperationException("The verification endpoint must be enabled to use the device flow."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1079)); } if (options.DisableTokenStorage) { if (options.DeviceEndpointUris.Count != 0 || options.VerificationEndpointUris.Count != 0) { - throw new InvalidOperationException(new StringBuilder() - .Append("The device and verification endpoints cannot be enabled when token storage is disabled.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1080)); } if (options.RevocationEndpointUris.Count != 0) { - throw new InvalidOperationException("The revocation endpoint cannot be enabled when token storage is disabled."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1081)); } if (options.UseReferenceAccessTokens || options.UseReferenceRefreshTokens) { - throw new InvalidOperationException("Reference tokens cannot be used when disabling token storage."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1082)); } if (!options.DisableSlidingRefreshTokenExpiration && !options.UseRollingRefreshTokens) { - throw new InvalidOperationException(new StringBuilder() - .Append("Sliding expiration must be disabled when turning off token storage if rolling tokens are not used.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1083)); } } if (options.EncryptionCredentials.Count == 0) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("At least one encryption key must be registered in the OpenIddict server options.") - .Append("Consider registering a certificate using 'services.AddOpenIddict().AddServer().AddEncryptionCertificate()' ") - .Append("or 'services.AddOpenIddict().AddServer().AddDevelopmentEncryptionCertificate()' or call ") - .Append("'services.AddOpenIddict().AddServer().AddEphemeralEncryptionKey()' to use an ephemeral key.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1084)); } if (!options.SigningCredentials.Any(credentials => credentials.Key is AsymmetricSecurityKey)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("At least one asymmetric signing key must be registered in the OpenIddict server options.") - .Append("Consider registering a certificate using 'services.AddOpenIddict().AddServer().AddSigningCertificate()' ") - .Append("or 'services.AddOpenIddict().AddServer().AddDevelopmentSigningCertificate()' or call ") - .Append("'services.AddOpenIddict().AddServer().AddEphemeralSigningKey()' to use an ephemeral key.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1085)); } // If all the registered encryption credentials are backed by a X.509 certificate, at least one of them must be valid. if (options.EncryptionCredentials.All(credentials => credentials.Key is X509SecurityKey x509SecurityKey && (x509SecurityKey.Certificate.NotBefore > DateTime.Now || x509SecurityKey.Certificate.NotAfter < DateTime.Now))) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("When using X.509 encryption credentials, at least one of the registered certificates must be valid.") - .Append("To use key rollover, register both the new certificate and the old one in the credentials collection.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1086)); } // If all the registered signing credentials are backed by a X.509 certificate, at least one of them must be valid. if (options.SigningCredentials.All(credentials => credentials.Key is X509SecurityKey x509SecurityKey && (x509SecurityKey.Certificate.NotBefore > DateTime.Now || x509SecurityKey.Certificate.NotAfter < DateTime.Now))) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("When using X.509 signing credentials, at least one of the registered certificates must be valid.") - .Append("To use key rollover, register both the new certificate and the old one in the credentials collection.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1087)); } if (options.EnableDegradedMode) @@ -159,11 +134,7 @@ namespace OpenIddict.Server descriptor.Type == OpenIddictServerHandlerType.Custom && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { - throw new InvalidOperationException(new StringBuilder() - .Append("No custom authorization request validation handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to validate authorization requests (e.g to ensure the client_id and redirect_uri are valid).") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1088)); } if (options.DeviceEndpointUris.Count != 0 && !options.Handlers.Any( @@ -171,11 +142,7 @@ namespace OpenIddict.Server descriptor.Type == OpenIddictServerHandlerType.Custom && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { - throw new InvalidOperationException(new StringBuilder() - .Append("No custom device request validation handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to validate device requests (e.g to ensure the client_id and client_secret are valid).") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1089)); } if (options.IntrospectionEndpointUris.Count != 0 && !options.Handlers.Any( @@ -183,11 +150,7 @@ namespace OpenIddict.Server descriptor.Type == OpenIddictServerHandlerType.Custom && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { - throw new InvalidOperationException(new StringBuilder() - .Append("No custom introspection request validation handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to validate introspection requests (e.g to ensure the client_id and client_secret are valid).") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1090)); } if (options.LogoutEndpointUris.Count != 0 && !options.Handlers.Any( @@ -195,11 +158,7 @@ namespace OpenIddict.Server descriptor.Type == OpenIddictServerHandlerType.Custom && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { - throw new InvalidOperationException(new StringBuilder() - .Append("No custom logout request validation handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to validate logout requests (e.g to ensure the post_logout_redirect_uri is valid).") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1091)); } if (options.RevocationEndpointUris.Count != 0 && !options.Handlers.Any( @@ -207,11 +166,7 @@ namespace OpenIddict.Server descriptor.Type == OpenIddictServerHandlerType.Custom && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { - throw new InvalidOperationException(new StringBuilder() - .Append("No custom revocation request validation handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to validate revocation requests (e.g to ensure the client_id and client_secret are valid).") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1092)); } if (options.TokenEndpointUris.Count != 0 && !options.Handlers.Any( @@ -219,11 +174,7 @@ namespace OpenIddict.Server descriptor.Type == OpenIddictServerHandlerType.Custom && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { - throw new InvalidOperationException(new StringBuilder() - .Append("No custom token request validation handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to validate token requests (e.g to ensure the client_id and client_secret are valid).") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1093)); } if (options.VerificationEndpointUris.Count != 0 && !options.Handlers.Any( @@ -231,11 +182,7 @@ namespace OpenIddict.Server descriptor.Type == OpenIddictServerHandlerType.Custom && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { - throw new InvalidOperationException(new StringBuilder() - .Append("No custom verification request validation handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to validate verification requests (e.g to ensure the user_code is valid).") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1094)); } // If the degraded mode was enabled, ensure custom authentication/sign-in handlers @@ -248,11 +195,7 @@ namespace OpenIddict.Server descriptor.Type == OpenIddictServerHandlerType.Custom && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { - throw new InvalidOperationException(new StringBuilder() - .Append("No custom verification authentication handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to validate device and user codes (e.g by retrieving them from a database).") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1095)); } if (!options.Handlers.Any( @@ -260,11 +203,7 @@ namespace OpenIddict.Server descriptor.Type == OpenIddictServerHandlerType.Custom && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { - throw new InvalidOperationException(new StringBuilder() - .Append("No custom verification sign-in handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to generate device and user codes and storing them in a database, if applicable.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1096)); } } } diff --git a/src/OpenIddict.Server/OpenIddictServerDispatcher.cs b/src/OpenIddict.Server/OpenIddictServerDispatcher.cs index 9bae35c0..d29f4126 100644 --- a/src/OpenIddict.Server/OpenIddictServerDispatcher.cs +++ b/src/OpenIddict.Server/OpenIddictServerDispatcher.cs @@ -6,12 +6,12 @@ using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -115,11 +115,7 @@ namespace OpenIddict.Server if (handler == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine($"The event handler of type '{descriptor.ServiceDescriptor.ServiceType}' couldn't be resolved.") - .AppendLine("This may indicate that it was not properly registered in the dependency injection container.") - .Append("To register an event handler, use 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.FormatID1097(descriptor.ServiceDescriptor.ServiceType)); } yield return handler; @@ -132,10 +128,7 @@ namespace OpenIddict.Server { if (!(_provider.GetService(descriptor.FilterTypes[index]) is IOpenIddictServerHandlerFilter filter)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine($"The event handler filter of type '{descriptor.FilterTypes[index]}' couldn't be resolved.") - .AppendLine("This may indicate that it was not properly registered in the dependency injection container.") - .ToString()); + throw new InvalidOperationException(SR.FormatID1098(descriptor.FilterTypes[index])); } if (!await filter.IsActiveAsync(context)) diff --git a/src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs b/src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs index 8904a789..21d23884 100644 --- a/src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs +++ b/src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs @@ -7,6 +7,7 @@ using System; using System.Security.Claims; using JetBrains.Annotations; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -61,7 +62,7 @@ namespace OpenIddict.Server { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The redirect_uri cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1099), nameof(address)); } // Don't allow validation to alter the redirect_uri parameter extracted @@ -69,9 +70,7 @@ namespace OpenIddict.Server if (!string.IsNullOrEmpty(Request.RedirectUri) && !string.Equals(Request.RedirectUri, address, StringComparison.Ordinal)) { - throw new InvalidOperationException( - "The authorization request cannot be validated because a different " + - "redirect_uri was specified by the client application."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1100)); } RedirectUri = address; diff --git a/src/OpenIddict.Server/OpenIddictServerEvents.Session.cs b/src/OpenIddict.Server/OpenIddictServerEvents.Session.cs index b5b6aa1d..64657d5d 100644 --- a/src/OpenIddict.Server/OpenIddictServerEvents.Session.cs +++ b/src/OpenIddict.Server/OpenIddictServerEvents.Session.cs @@ -6,6 +6,7 @@ using System; using JetBrains.Annotations; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -53,7 +54,7 @@ namespace OpenIddict.Server { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The post_logout_redirect_uri cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1101), nameof(address)); } // Don't allow validation to alter the post_logout_redirect_uri parameter extracted @@ -61,9 +62,7 @@ namespace OpenIddict.Server if (!string.IsNullOrEmpty(Request.PostLogoutRedirectUri) && !string.Equals(Request.PostLogoutRedirectUri, address, StringComparison.Ordinal)) { - throw new InvalidOperationException( - "The end session request cannot be validated because a different " + - "post_logout_redirect_uri was specified by the client application."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1102)); } PostLogoutRedirectUri = address; diff --git a/src/OpenIddict.Server/OpenIddictServerEvents.Userinfo.cs b/src/OpenIddict.Server/OpenIddictServerEvents.Userinfo.cs index d6f0dfe0..417f0501 100644 --- a/src/OpenIddict.Server/OpenIddictServerEvents.Userinfo.cs +++ b/src/OpenIddict.Server/OpenIddictServerEvents.Userinfo.cs @@ -7,8 +7,8 @@ using System; using System.Collections.Generic; using System.Security.Claims; -using JetBrains.Annotations; using System.Text.Json; +using JetBrains.Annotations; using OpenIddict.Abstractions; namespace OpenIddict.Server diff --git a/src/OpenIddict.Server/OpenIddictServerEvents.cs b/src/OpenIddict.Server/OpenIddictServerEvents.cs index 6d909183..b8121cd8 100644 --- a/src/OpenIddict.Server/OpenIddictServerEvents.cs +++ b/src/OpenIddict.Server/OpenIddictServerEvents.cs @@ -5,10 +5,10 @@ */ using System; -using System.Collections.Generic; using System.ComponentModel; using System.Security.Claims; using JetBrains.Annotations; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using OpenIddict.Abstractions; @@ -51,6 +51,11 @@ namespace OpenIddict.Server set => Transaction.EndpointType = value; } + /// + /// Gets the localizer used to localize the messages generated by OpenIddict. + /// + public IStringLocalizer Localizer => Transaction.Localizer; + /// /// Gets the logger responsible of logging processed operations. /// diff --git a/src/OpenIddict.Server/OpenIddictServerExtensions.cs b/src/OpenIddict.Server/OpenIddictServerExtensions.cs index 2394a51c..f8054bd0 100644 --- a/src/OpenIddict.Server/OpenIddictServerExtensions.cs +++ b/src/OpenIddict.Server/OpenIddictServerExtensions.cs @@ -8,13 +8,17 @@ using System; using System.Linq; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging.Abstractions; +using OpenIddict.Abstractions.Resources; using OpenIddict.Server; using static OpenIddict.Server.OpenIddictServerHandlerFilters; using static OpenIddict.Server.OpenIddictServerHandlers; namespace Microsoft.Extensions.DependencyInjection { + using Microsoft.Extensions.Options; + /// /// Exposes extensions allowing to register the OpenIddict server services. /// @@ -33,6 +37,7 @@ namespace Microsoft.Extensions.DependencyInjection throw new ArgumentNullException(nameof(builder)); } + builder.Services.AddLocalization(); builder.Services.AddLogging(); builder.Services.AddOptions(); @@ -75,6 +80,18 @@ namespace Microsoft.Extensions.DependencyInjection builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); + builder.Services.TryAddSingleton>(provider => + { + // Note: the string localizer factory is deliberately not resolved from + // the DI container to ensure the built-in .resx files are always used + // even if the factory was replaced by a different implementation in DI. + var factory = new ResourceManagerStringLocalizerFactory( + localizationOptions: Options.Create(new LocalizationOptions()), + loggerFactory: NullLoggerFactory.Instance); + + return new StringLocalizer(factory); + }); + // Note: TryAddEnumerable() is used here to ensure the initializer is registered only once. builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< IPostConfigureOptions, OpenIddictServerConfiguration>()); diff --git a/src/OpenIddict.Server/OpenIddictServerFactory.cs b/src/OpenIddict.Server/OpenIddictServerFactory.cs index 65795518..4a0cfa84 100644 --- a/src/OpenIddict.Server/OpenIddictServerFactory.cs +++ b/src/OpenIddict.Server/OpenIddictServerFactory.cs @@ -6,23 +6,28 @@ using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using OpenIddict.Abstractions.Resources; namespace OpenIddict.Server { public class OpenIddictServerFactory : IOpenIddictServerFactory { - private readonly ILogger _logger; + private readonly IStringLocalizer _localizer; + private readonly ILogger _logger; private readonly IOptionsMonitor _options; /// /// Creates a new instance of the class. /// public OpenIddictServerFactory( + [NotNull] IStringLocalizer localizer, [NotNull] ILogger logger, [NotNull] IOptionsMonitor options) { + _localizer = localizer; _logger = logger; _options = options; } @@ -31,6 +36,7 @@ namespace OpenIddict.Server => new ValueTask(new OpenIddictServerTransaction { Issuer = _options.CurrentValue.Issuer, + Localizer = _localizer, Logger = _logger, Options = _options.CurrentValue }); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlerDescriptor.cs b/src/OpenIddict.Server/OpenIddictServerHandlerDescriptor.cs index 760cb926..ce89b067 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlerDescriptor.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlerDescriptor.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -86,7 +87,7 @@ namespace OpenIddict.Server if (!typeof(IOpenIddictServerHandlerFilter<>).MakeGenericType(typeof(TContext)).IsAssignableFrom(type)) { - throw new InvalidOperationException("The specified service type is not valid."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1103)); } _filterTypes.Add(type); @@ -118,7 +119,7 @@ namespace OpenIddict.Server var type = descriptor.ServiceType; if (!typeof(IOpenIddictServerHandler<>).MakeGenericType(typeof(TContext)).IsAssignableFrom(type)) { - throw new InvalidOperationException("The specified service type is not valid."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1103)); } _descriptor = descriptor; @@ -216,7 +217,7 @@ namespace OpenIddict.Server ContextType = typeof(TContext), FilterTypes = _filterTypes.ToImmutableArray(), Order = _order, - ServiceDescriptor = _descriptor ?? throw new InvalidOperationException("No service descriptor was set."), + ServiceDescriptor = _descriptor ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID1104)), Type = _type }; } diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs index 392c118e..7f0901fc 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Logging; @@ -16,6 +15,7 @@ using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -125,11 +125,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The authorization request was not correctly extracted. To extract authorization requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1026)); } context.Logger.LogInformation("The authorization request was successfully extracted: {Request}.", notification.Request); @@ -201,7 +197,7 @@ namespace OpenIddict.Server if (string.IsNullOrEmpty(notification.RedirectUri)) { - throw new InvalidOperationException("The request cannot be validated because no redirect_uri was specified."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1027)); } context.Logger.LogInformation("The authorization request was successfully validated."); @@ -299,14 +295,7 @@ namespace OpenIddict.Server } } - throw new InvalidOperationException(new StringBuilder() - .Append("The authorization request was not handled. To handle authorization requests in a controller, ") - .Append("create a custom controller action with the same route as the authorization endpoint ") - .Append("and enable the pass-through mode in the server ASP.NET Core or OWIN options using ") - .AppendLine("'services.AddOpenIddict().AddServer().UseAspNetCore().EnableAuthorizationEndpointPassthrough()'.") - .Append("Alternatively, create a class implementing 'IOpenIddictServerHandler' ") - .Append("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1028)); } } @@ -360,11 +349,7 @@ namespace OpenIddict.Server return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The authorization response was not correctly applied. To apply authorization responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1029)); } } @@ -401,11 +386,11 @@ namespace OpenIddict.Server if (!string.IsNullOrEmpty(context.Request.Request)) { context.Logger.LogError("The authorization request was rejected because it contained " + - "an unsupported parameter: {Parameter}.", "request"); + "an unsupported parameter: {Parameter}.", Parameters.Request); context.Reject( error: Errors.RequestNotSupported, - description: "The 'request' parameter is not supported."); + description: context.Localizer[SR.ID3028, Parameters.Request]); return default; } @@ -447,11 +432,11 @@ namespace OpenIddict.Server if (!string.IsNullOrEmpty(context.Request.RequestUri)) { context.Logger.LogError("The authorization request was rejected because it contained " + - "an unsupported parameter: {Parameter}.", "request_uri"); + "an unsupported parameter: {Parameter}.", Parameters.RequestUri); context.Reject( error: Errors.RequestUriNotSupported, - description: "The 'request_uri' parameter is not supported."); + description: context.Localizer[SR.ID3028, Parameters.RequestUri]); return default; } @@ -498,7 +483,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'client_id' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.ClientId]); return default; } @@ -550,7 +535,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'redirect_uri' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.RedirectUri]); return default; } @@ -573,7 +558,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The 'redirect_uri' parameter must be a valid absolute URL."); + description: context.Localizer[SR.ID3030, Parameters.RedirectUri]); return default; } @@ -588,7 +573,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The 'redirect_uri' parameter must not include a fragment."); + description: context.Localizer[SR.ID3031, Parameters.RedirectUri]); return default; } @@ -634,7 +619,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'response_type' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.ResponseType]); return default; } @@ -649,7 +634,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnsupportedResponseType, - description: "The specified 'response_type' parameter is not allowed."); + description: context.Localizer[SR.ID3032, Parameters.ResponseType]); return default; } @@ -699,7 +684,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The specified 'response_type'/'response_mode' combination is invalid."); + description: context.Localizer[SR.ID3033, Parameters.ResponseType, Parameters.ResponseMode]); return default; } @@ -713,7 +698,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The specified 'response_mode' parameter is not supported."); + description: context.Localizer[SR.ID3032, Parameters.ResponseMode]); return default; } @@ -783,7 +768,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'openid' scope is missing."); + description: context.Localizer[SR.ID3034, Scopes.OpenId]); return default; } @@ -793,7 +778,7 @@ namespace OpenIddict.Server { context.Reject( error: Errors.InvalidRequest, - description: "The 'offline_access' scope is not allowed."); + description: context.Localizer[SR.ID3035, Scopes.OfflineAccess]); return default; } @@ -847,7 +832,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'nonce' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.Nonce]); return default; } @@ -894,7 +879,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The specified 'prompt' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.Prompt]); return default; } @@ -945,7 +930,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The 'code_challenge_method' parameter cannot be used without 'code_challenge'."); + description: context.Localizer[SR.ID3037, Parameters.CodeChallengeMethod, Parameters.CodeChallenge]); return default; } @@ -960,7 +945,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The 'code_challenge_method' parameter must be specified."); + description: context.Localizer[SR.ID3029, Parameters.CodeChallengeMethod]); return default; } @@ -974,7 +959,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The specified 'code_challenge_method' parameter is not supported."); + description: context.Localizer[SR.ID3032, Parameters.CodeChallengeMethod]); return default; } @@ -987,8 +972,8 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The 'code_challenge' and 'code_challenge_method' parameters " + - "can only be used with a response type containing 'code'."); + description: context.Localizer[SR.ID3040, Parameters.CodeChallenge, + Parameters.CodeChallengeMethod, ResponseTypes.Code]); return default; } @@ -1001,7 +986,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The specified 'response_type' parameter is not allowed when using PKCE."); + description: context.Localizer[SR.ID3041, Parameters.ResponseType]); return default; } @@ -1018,13 +1003,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientId() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientId() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientId([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1062,7 +1041,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The specified 'client_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.ClientId]); return; } @@ -1078,13 +1057,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientType() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientType() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientType([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1117,7 +1090,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // To prevent downgrade attacks, ensure that authorization requests returning an access token directly @@ -1132,7 +1105,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "The specified 'response_type' parameter is not valid for this client application."); + description: context.Localizer[SR.ID3043, Parameters.ResponseType]); return; } @@ -1147,13 +1120,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientRedirectUri() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientRedirectUri() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientRedirectUri([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1186,7 +1153,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // If no explicit redirect_uri was specified, retrieve the addresses associated with @@ -1201,7 +1168,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'redirect_uri' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.RedirectUri]); return; } @@ -1219,7 +1186,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The specified 'redirect_uri' parameter is not valid for this client application."); + description: context.Localizer[SR.ID3043, Parameters.RedirectUri]); return; } @@ -1234,13 +1201,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictScopeManager _scopeManager; - public ValidateScopes() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateScopes() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateScopes([NotNull] IOpenIddictScopeManager scopeManager) => _scopeManager = scopeManager; @@ -1291,7 +1252,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidScope, - description: "The specified 'scope' parameter is not valid."); + description: context.Localizer[SR.ID3052, Parameters.Scope]); return; } @@ -1306,13 +1267,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateEndpointPermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateEndpointPermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1346,7 +1301,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // Reject the request if the application is not allowed to use the authorization endpoint. @@ -1357,7 +1312,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "This client application is not allowed to use the authorization endpoint."); + description: context.Localizer[SR.ID3046]); return; } @@ -1372,13 +1327,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateGrantTypePermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateGrantTypePermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1412,7 +1361,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // Reject the request if the application is not allowed to use the authorization code flow. @@ -1424,7 +1373,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "The client application is not allowed to use the authorization code flow."); + description: context.Localizer[SR.ID3047]); return; } @@ -1438,7 +1387,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "The client application is not allowed to use the implicit flow."); + description: context.Localizer[SR.ID3048]); return; } @@ -1453,7 +1402,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "The client application is not allowed to use the hybrid flow."); + description: context.Localizer[SR.ID3049]); return; } @@ -1468,7 +1417,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The client application is not allowed to use the 'offline_access' scope."); + description: context.Localizer[SR.ID3050]); return; } @@ -1483,13 +1432,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateScopePermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateScopePermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1523,7 +1466,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } foreach (var scope in context.Request.GetScopes()) @@ -1543,7 +1486,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "This client application is not allowed to use the specified scope."); + description: context.Localizer[SR.ID3051]); return; } @@ -1560,13 +1503,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateProofKeyForCodeExchangeRequirement([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1606,7 +1543,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange)) @@ -1616,7 +1553,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'code_challenge' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.CodeChallenge]); return; } diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs index 7f347ab8..55a90dd9 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Security.Claims; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Logging; @@ -16,6 +15,7 @@ using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -56,7 +56,7 @@ namespace OpenIddict.Server ApplyVerificationResponse.Descriptor, ApplyVerificationResponse.Descriptor, ApplyVerificationResponse.Descriptor, - + /* * Verification request handling: */ @@ -123,11 +123,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The device request was not correctly extracted. To extract device requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1030)); } context.Logger.LogInformation("The device request was successfully extracted: {Request}.", notification.Request); @@ -346,11 +342,7 @@ namespace OpenIddict.Server return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The device response was not correctly applied. To apply device responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1032)); } } @@ -391,7 +383,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The mandatory 'client_id' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.ClientId]); return default; } @@ -408,13 +400,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictScopeManager _scopeManager; - public ValidateScopes() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateScopes() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateScopes([NotNull] IOpenIddictScopeManager scopeManager) => _scopeManager = scopeManager; @@ -465,7 +451,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidScope, - description: "The specified 'scope' parameter is not valid."); + description: context.Localizer[SR.ID3052, Parameters.Scope]); return; } @@ -480,13 +466,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientId() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientId() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientId([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -527,7 +507,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The specified 'client_id' parameter is invalid."); + description: context.Localizer[SR.ID3052]); return; } @@ -543,13 +523,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientType() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientType() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientType([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -583,7 +557,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) @@ -596,7 +570,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The 'client_secret' parameter is not valid for this client application."); + description: context.Localizer[SR.ID3053, Parameters.ClientSecret]); return; } @@ -612,7 +586,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The 'client_secret' parameter required for this client application is missing."); + description: context.Localizer[SR.ID3054, Parameters.ClientSecret]); return; } @@ -627,13 +601,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientSecret() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientSecret() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientSecret([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -667,7 +635,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // If the application is not a public client, validate the client secret. @@ -679,7 +647,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The specified client credentials are invalid."); + description: context.Localizer[SR.ID3055]); return; } @@ -695,13 +663,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateEndpointPermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateEndpointPermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -736,7 +698,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // Reject the request if the application is not allowed to use the device endpoint. @@ -747,7 +709,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "This client application is not allowed to use the device endpoint."); + description: context.Localizer[SR.ID3056]); return; } @@ -763,13 +725,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateScopePermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateScopePermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -804,7 +760,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } foreach (var scope in context.Request.GetScopes()) @@ -824,7 +780,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "This client application is not allowed to use the specified scope."); + description: context.Localizer[SR.ID3051]); return; } @@ -893,11 +849,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The verification request was not correctly extracted. To extract verification requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1033)); } context.Logger.LogInformation("The verification request was successfully extracted: {Request}.", notification.Request); @@ -1058,14 +1010,7 @@ namespace OpenIddict.Server } } - throw new InvalidOperationException(new StringBuilder() - .Append("The verification request was not handled. To handle verification requests in a controller, ") - .Append("create a custom controller action with the same route as the verification endpoint ") - .Append("and enable the pass-through mode in the server ASP.NET Core or OWIN options using ") - .AppendLine("'services.AddOpenIddict().AddServer().UseAspNetCore().EnableVerificationEndpointPassthrough()'.") - .Append("Alternatively, create a class implementing 'IOpenIddictServerHandler' ") - .Append("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1034)); } } @@ -1119,11 +1064,7 @@ namespace OpenIddict.Server return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The verification response was not correctly applied. To apply verification responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1035)); } } diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs index 9cb8bc3a..1430de45 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs @@ -21,6 +21,7 @@ using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -128,11 +129,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The configuration request was not correctly extracted. To extract configuration requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1036)); } context.Logger.LogInformation("The configuration request was successfully extracted: {Request}.", notification.Request); @@ -427,7 +424,7 @@ namespace OpenIddict.Server // At this stage, throw an exception if the issuer cannot be retrieved. if (issuer == null || !issuer.IsAbsoluteUri) { - throw new InvalidOperationException("The issuer must be a non-null, non-empty absolute URL."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1022)); } // Ensure the issuer ends with a trailing slash, as it is necessary @@ -919,11 +916,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The cryptography request was not correctly extracted. To extract configuration requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1037)); } context.Logger.LogInformation("The cryptography request was successfully extracted: {Request}.", notification.Request); @@ -1178,11 +1171,7 @@ namespace OpenIddict.Server return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The cryptography response was not correctly applied. To apply cryptography responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1038)); } } @@ -1399,7 +1388,7 @@ namespace OpenIddict.Server using var hash = CryptoConfig.CreateFromName(algorithm.Name) as HashAlgorithm; if (hash == null || hash is KeyedHashAlgorithm) { - throw new InvalidOperationException("The specified hash algorithm is not valid."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1216)); } return hash.ComputeHash(certificate.RawData); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs index da7949a8..a42df2be 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs @@ -17,6 +17,7 @@ using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; #if !SUPPORTS_TIME_CONSTANT_COMPARISONS using Org.BouncyCastle.Utilities; @@ -130,11 +131,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The token request was not correctly extracted. To extract token requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1039)); } context.Logger.LogInformation("The token request was successfully extracted: {Request}.", notification.Request); @@ -299,14 +296,7 @@ namespace OpenIddict.Server } } - throw new InvalidOperationException(new StringBuilder() - .Append("The token request was not handled. To handle token requests in a controller, ") - .Append("create a custom controller action with the same route as the token endpoint ") - .Append("and enable the pass-through mode in the server ASP.NET Core or OWIN options using ") - .AppendLine("'services.AddOpenIddict().AddServer().UseAspNetCore().EnableTokenEndpointPassthrough()'.") - .Append("Alternatively, create a class implementing 'IOpenIddictServerHandler' ") - .Append("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1040)); } } @@ -360,11 +350,7 @@ namespace OpenIddict.Server return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The token response was not correctly applied. To apply token responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1041)); } } @@ -404,7 +390,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'grant_type' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.GrantType]); return default; } @@ -417,7 +403,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnsupportedGrantType, - description: "The specified 'grant_type' parameter is not supported."); + description: context.Localizer[SR.ID3032, Parameters.GrantType]); return default; } @@ -428,7 +414,7 @@ namespace OpenIddict.Server { context.Reject( error: Errors.InvalidRequest, - description: "The 'offline_access' scope is not allowed."); + description: context.Localizer[SR.ID3035, Scopes.OfflineAccess]); return default; } @@ -482,7 +468,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The mandatory 'client_id' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.ClientId]); return default; } @@ -529,7 +515,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'code' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.Code]); return default; } @@ -575,8 +561,7 @@ namespace OpenIddict.Server { context.Reject( error: Errors.InvalidRequest, - description: "The 'client_id' and 'client_secret' parameters are " + - "required when using the client credentials grant."); + description: context.Localizer[SR.ID3057, Parameters.ClientId, Parameters.ClientSecret]); return default; } @@ -621,7 +606,7 @@ namespace OpenIddict.Server { context.Reject( error: Errors.InvalidRequest, - description: "The 'device_code' parameter is required when using the device code grant."); + description: context.Localizer[SR.ID3058, Parameters.DeviceCode]); return default; } @@ -668,7 +653,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'refresh_token' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.RefreshToken]); return default; } @@ -716,7 +701,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'username' and/or 'password' parameters are missing."); + description: context.Localizer[SR.ID3059, Parameters.Username, Parameters.Password]); return default; } @@ -733,13 +718,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictScopeManager _scopeManager; - public ValidateScopes() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateScopes() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateScopes([NotNull] IOpenIddictScopeManager scopeManager) => _scopeManager = scopeManager; @@ -790,7 +769,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidScope, - description: "The specified 'scope' parameter is not valid."); + description: context.Localizer[SR.ID3052, Parameters.Scope]); return; } @@ -805,13 +784,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientId() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientId() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientId([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -852,7 +825,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The specified 'client_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.ClientId]); return; } @@ -868,13 +841,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientType() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientType() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientType([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -908,7 +875,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) @@ -921,7 +888,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "The specified 'grant_type' parameter is not valid for this client application."); + description: context.Localizer[SR.ID3043, Parameters.GrantType]); return; } @@ -934,7 +901,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The 'client_secret' parameter is not valid for this client application."); + description: context.Localizer[SR.ID3061, Parameters.ClientSecret]); return; } @@ -950,7 +917,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The 'client_secret' parameter required for this client application is missing."); + description: context.Localizer[SR.ID3062, Parameters.ClientSecret]); return; } @@ -965,13 +932,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientSecret() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientSecret() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientSecret([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1005,7 +966,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // If the application is not a public client, validate the client secret. @@ -1017,7 +978,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The specified client credentials are invalid."); + description: context.Localizer[SR.ID3055]); return; } @@ -1033,13 +994,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateEndpointPermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateEndpointPermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1074,7 +1029,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // Reject the request if the application is not allowed to use the token endpoint. @@ -1085,7 +1040,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "This client application is not allowed to use the token endpoint."); + description: context.Localizer[SR.ID3063]); return; } @@ -1101,13 +1056,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateGrantTypePermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateGrantTypePermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1142,7 +1091,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // Reject the request if the application is not allowed to use the specified grant type. @@ -1153,7 +1102,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "This client application is not allowed to use the specified grant type."); + description: context.Localizer[SR.ID3064]); return; } @@ -1168,7 +1117,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The client application is not allowed to use the 'offline_access' scope."); + description: context.Localizer[SR.ID3065, Scopes.OfflineAccess]); return; } @@ -1184,13 +1133,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateScopePermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateScopePermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1225,7 +1168,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } foreach (var scope in context.Request.GetScopes()) @@ -1245,7 +1188,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "This client application is not allowed to use the specified scope."); + description: context.Localizer[SR.ID3051]); return; } @@ -1262,13 +1205,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateProofKeyForCodeExchangeRequirement([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1314,7 +1251,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange)) @@ -1324,7 +1261,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'code_verifier' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.CodeVerifier]); return; } @@ -1450,12 +1387,12 @@ namespace OpenIddict.Server // was issued to a public client but cannot be null for an authorization or device code grant request. if (context.Request.IsAuthorizationCodeGrantType()) { - throw new InvalidOperationException("The presenters list cannot be extracted from the authorization code."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1042)); } if (context.Request.IsDeviceCodeGrantType()) { - throw new InvalidOperationException("The presenters list cannot be extracted from the device code."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1043)); } return default; @@ -1471,12 +1408,9 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidGrant, - description: - context.Request.IsAuthorizationCodeGrantType() ? - "The specified authorization code cannot be used without specifying a client identifier." : - context.Request.IsDeviceCodeGrantType() ? - "The specified device code cannot be used without specifying a client identifier." : - "The specified refresh token cannot be used without specifying a client identifier."); + description: context.Request.IsAuthorizationCodeGrantType() ? context.Localizer[SR.ID3066] : + context.Request.IsDeviceCodeGrantType() ? context.Localizer[SR.ID3067] : + context.Localizer[SR.ID3068]); return default; } @@ -1492,12 +1426,9 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidGrant, - description: - context.Request.IsAuthorizationCodeGrantType() ? - "The specified authorization code cannot be used by this client application." : - context.Request.IsDeviceCodeGrantType() ? - "The specified device code cannot be used by this client application." : - "The specified refresh token cannot be used by this client application."); + description: context.Request.IsAuthorizationCodeGrantType() ? context.Localizer[SR.ID3069] : + context.Request.IsDeviceCodeGrantType() ? context.Localizer[SR.ID3070] : + context.Localizer[SR.ID3071]); return default; } @@ -1560,7 +1491,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'redirect_uri' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.RedirectUri]); return default; } @@ -1572,8 +1503,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidGrant, - description: "The specified 'redirect_uri' parameter doesn't match the client " + - "redirection endpoint the authorization code was initially sent to."); + description: context.Localizer[SR.ID3072, Parameters.RedirectUri]); return default; } @@ -1635,7 +1565,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The 'code_verifier' parameter is uncalled for in this request."); + description: context.Localizer[SR.ID3073, Parameters.CodeVerifier]); return default; } @@ -1651,7 +1581,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'code_verifier' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.CodeVerifier]); return default; } @@ -1660,7 +1590,7 @@ namespace OpenIddict.Server var method = context.Principal.GetClaim(Claims.Private.CodeChallengeMethod); if (string.IsNullOrEmpty(method)) { - throw new InvalidOperationException("The code challenge method cannot be retrieved from the authorization code."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1267)); } // Note: when using the "plain" code challenge method, no hashing is actually performed. @@ -1680,7 +1610,7 @@ namespace OpenIddict.Server else { - throw new InvalidOperationException("The specified code challenge method is not supported."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1044)); } // Compare the verifier and the code challenge: if the two don't match, return an error. @@ -1695,7 +1625,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidGrant, - description: "The specified 'code_verifier' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.CodeVerifier]); return default; } @@ -1747,7 +1677,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidGrant, - description: "The 'scope' parameter is not valid in this context."); + description: context.Localizer[SR.ID3074, Parameters.Scope]); return default; } @@ -1762,7 +1692,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidGrant, - description: "The specified 'scope' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.Scope]); return default; } @@ -1808,7 +1738,7 @@ namespace OpenIddict.Server var notification = context.Transaction.GetProperty( typeof(ValidateTokenRequestContext).FullName) ?? - throw new InvalidOperationException("The authentication context cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1006)); context.Principal ??= notification.Principal; diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs index 22258403..a84cee02 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs @@ -9,7 +9,6 @@ using System.Collections.Immutable; using System.Globalization; using System.Linq; using System.Security.Claims; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading.Tasks; @@ -21,6 +20,7 @@ using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -124,11 +124,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The introspection request was not correctly extracted. To extract introspection requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1045)); } context.Logger.LogInformation("The introspection request was successfully extracted: {Request}.", notification.Request); @@ -361,11 +357,7 @@ namespace OpenIddict.Server return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The introspection response was not correctly applied. To apply introspection responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1046)); } } @@ -405,7 +397,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'token' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.Token]); return default; } @@ -450,7 +442,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The mandatory 'client_id' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.ClientId]); return default; } @@ -467,13 +459,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientId() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientId() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientId([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -514,7 +500,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The specified 'client_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.ClientId]); return; } @@ -530,13 +516,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientType() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientType() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientType([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -570,7 +550,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) @@ -583,7 +563,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The 'client_secret' parameter is not valid for this client application."); + description: context.Localizer[SR.ID3061, Parameters.ClientSecret]); return; } @@ -599,7 +579,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The 'client_secret' parameter required for this client application is missing."); + description: context.Localizer[SR.ID3062, Parameters.ClientSecret]); return; } @@ -614,13 +594,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientSecret() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientSecret() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientSecret([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -654,7 +628,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // If the application is not a public client, validate the client secret. @@ -666,7 +640,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The specified client credentials are invalid."); + description: context.Localizer[SR.ID3055]); return; } @@ -682,13 +656,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateEndpointPermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateEndpointPermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -723,7 +691,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // Reject the request if the application is not allowed to use the introspection endpoint. @@ -734,7 +702,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "This client application is not allowed to use the introspection endpoint."); + description: context.Localizer[SR.ID3075]); return; } @@ -843,7 +811,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnsupportedTokenType, - description: "The specified token cannot be introspected."); + description: context.Localizer[SR.ID3076]); return default; } @@ -892,7 +860,7 @@ namespace OpenIddict.Server { if (!context.Principal.HasPresenter()) { - throw new InvalidOperationException("The presenters list cannot be extracted from the authorization code."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1042)); } if (!context.Principal.HasPresenter(context.ClientId)) @@ -902,7 +870,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidToken, - description: "The client application is not allowed to introspect the specified token."); + description: context.Localizer[SR.ID3077]); return default; } @@ -923,7 +891,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidToken, - description: "The client application is not allowed to introspect the specified token."); + description: context.Localizer[SR.ID3077]); return default; } @@ -940,7 +908,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidToken, - description: "The client application is not allowed to introspect the specified token."); + description: context.Localizer[SR.ID3077]); return default; } @@ -957,7 +925,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidToken, - description: "The client application is not allowed to introspect the specified token."); + description: context.Localizer[SR.ID3077]); return default; } @@ -998,7 +966,7 @@ namespace OpenIddict.Server var notification = context.Transaction.GetProperty( typeof(ValidateIntrospectionRequestContext).FullName) ?? - throw new InvalidOperationException("The authentication context cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1006)); context.Principal ??= notification.Principal; @@ -1068,13 +1036,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public AttachApplicationClaims() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public AttachApplicationClaims() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public AttachApplicationClaims([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -1122,7 +1084,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // Public clients are not allowed to access sensitive claims as authentication cannot be enforced. diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs index 24efc497..82c564ef 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Immutable; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Logging; @@ -14,6 +13,7 @@ using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -116,11 +116,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The revocation request was not correctly extracted. To extract revocation requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1047)); } context.Logger.LogInformation("The revocation request was successfully extracted: {Request}.", notification.Request); @@ -307,11 +303,7 @@ namespace OpenIddict.Server return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The revocation response was not correctly applied. To apply revocation responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1048)); } } @@ -351,7 +343,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'token' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.Token]); return default; } @@ -396,7 +388,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The mandatory 'client_id' parameter is missing."); + description: context.Localizer[SR.ID3029, Parameters.ClientId]); return default; } @@ -413,13 +405,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientId() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientId() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientId([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -460,7 +446,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The specified 'client_id' parameter is invalid."); + description: context.Localizer[SR.ID3052, Parameters.ClientId]); return; } @@ -476,13 +462,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientType() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientType() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientType([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -516,7 +496,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) @@ -529,7 +509,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The 'client_secret' parameter is not valid for this client application."); + description: context.Localizer[SR.ID3061, Parameters.ClientSecret]); return; } @@ -545,7 +525,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The 'client_secret' parameter required for this client application is missing."); + description: context.Localizer[SR.ID3062, Parameters.ClientSecret]); return; } @@ -560,13 +540,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientSecret() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientSecret() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientSecret([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -600,7 +574,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // If the application is not a public client, validate the client secret. @@ -612,7 +586,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidClient, - description: "The specified client credentials are invalid."); + description: context.Localizer[SR.ID3055]); return; } @@ -628,13 +602,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateEndpointPermissions() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateEndpointPermissions([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -669,7 +637,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - throw new InvalidOperationException("The client application details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1031)); } // Reject the request if the application is not allowed to use the revocation endpoint. @@ -680,7 +648,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnauthorizedClient, - description: "This client application is not allowed to use the revocation endpoint."); + description: context.Localizer[SR.ID3078]); return; } @@ -788,7 +756,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnsupportedTokenType, - description: "This token cannot be revoked."); + description: context.Localizer[SR.ID3079]); return default; } @@ -837,7 +805,7 @@ namespace OpenIddict.Server { if (!context.Principal.HasPresenter()) { - throw new InvalidOperationException("The presenters list cannot be extracted from the authorization code."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1042)); } if (!context.Principal.HasPresenter(context.ClientId)) @@ -847,7 +815,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidToken, - description: "The client application is not allowed to revoke the specified token."); + description: context.Localizer[SR.ID3080]); return default; } @@ -868,7 +836,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidToken, - description: "The client application is not allowed to revoke the specified token."); + description: context.Localizer[SR.ID3080]); return default; } @@ -885,7 +853,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidToken, - description: "The client application is not allowed to revoke the specified token."); + description: context.Localizer[SR.ID3080]); return default; } @@ -902,7 +870,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidToken, - description: "The client application is not allowed to revoke the specified token."); + description: context.Localizer[SR.ID3080]); return default; } @@ -943,7 +911,7 @@ namespace OpenIddict.Server var notification = context.Transaction.GetProperty( typeof(ValidateRevocationRequestContext).FullName) ?? - throw new InvalidOperationException("The authentication context cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1006)); context.Principal ??= notification.Principal; @@ -959,13 +927,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public RevokeToken() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public RevokeToken() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public RevokeToken([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -1003,7 +965,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.UnsupportedTokenType, - description: "The specified token cannot be revoked."); + description: context.Localizer[SR.ID3079]); return; } @@ -1015,7 +977,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidToken, - description: "The specified token is invalid."); + description: context.Localizer[SR.ID3004]); return; } @@ -1025,7 +987,7 @@ namespace OpenIddict.Server { context.Reject( error: Errors.UnsupportedTokenType, - description: "The specified token cannot be revoked."); + description: context.Localizer[SR.ID3079]); return; } diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs index 68e52857..b4482582 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Immutable; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Logging; @@ -14,6 +13,7 @@ using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -105,11 +105,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The logout request was not correctly extracted. To extract logout requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1049)); } context.Logger.LogInformation("The logout request was successfully extracted: {Request}.", notification.Request); @@ -273,14 +269,7 @@ namespace OpenIddict.Server } } - throw new InvalidOperationException(new StringBuilder() - .Append("The logout request was not handled. To handle logout requests in a controller, ") - .Append("create a custom controller action with the same route as the logout endpoint ") - .Append("and enable the pass-through mode in the server ASP.NET Core or OWIN options using ") - .AppendLine("'services.AddOpenIddict().AddServer().UseAspNetCore().EnableLogoutEndpointPassthrough()'.") - .Append("Alternatively, create a class implementing 'IOpenIddictServerHandler' ") - .Append("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1050)); } } @@ -334,11 +323,7 @@ namespace OpenIddict.Server return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The revocation response was not correctly applied. To apply revocation responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1051)); } } @@ -384,7 +369,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The 'post_logout_redirect_uri' parameter must be a valid absolute URL."); + description: context.Localizer[SR.ID3030, Parameters.PostLogoutRedirectUri]); return default; } @@ -396,7 +381,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The 'post_logout_redirect_uri' parameter must not include a fragment."); + description: context.Localizer[SR.ID3031, Parameters.PostLogoutRedirectUri]); return default; } @@ -413,13 +398,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictApplicationManager _applicationManager; - public ValidateClientPostLogoutRedirectUri() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateClientPostLogoutRedirectUri() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateClientPostLogoutRedirectUri([NotNull] IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; @@ -457,7 +436,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.InvalidRequest, - description: "The specified 'post_logout_redirect_uri' parameter is not valid."); + description: context.Localizer[SR.ID3052, Parameters.PostLogoutRedirectUri]); return; } diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs index 694a04f5..468d328d 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Immutable; using System.Linq; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Logging; @@ -15,6 +14,7 @@ using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -107,11 +107,7 @@ namespace OpenIddict.Server if (notification.Request == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("The userinfo request was not correctly extracted. To extract userinfo requests, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1052)); } context.Logger.LogInformation("The userinfo request was successfully extracted: {Request}.", notification.Request); @@ -333,11 +329,7 @@ namespace OpenIddict.Server return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The userinfo response was not correctly applied. To apply userinfo responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1053)); } } @@ -376,7 +368,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.MissingToken, - description: "The mandatory access token is missing."); + description: context.Localizer[SR.ID3029, Parameters.AccessToken]); return default; } @@ -480,7 +472,7 @@ namespace OpenIddict.Server var notification = context.Transaction.GetProperty( typeof(ValidateUserinfoRequestContext).FullName) ?? - throw new InvalidOperationException("The authentication context cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1006)); context.Principal ??= notification.Principal; diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.cs index 9c402e24..abb54510 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.cs @@ -23,6 +23,7 @@ using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlerFilters; using Properties = OpenIddict.Server.OpenIddictServerConstants.Properties; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -162,19 +163,10 @@ namespace OpenIddict.Server case OpenIddictServerEndpointType.Verification: return default; - case OpenIddictServerEndpointType.Token: throw new InvalidOperationException(new StringBuilder() - .AppendLine("An identity cannot be extracted from this token request.") - .Append("This generally indicates that the OpenIddict server stack was asked ") - .AppendLine("to validate a token for an invalid grant type (e.g password).") - .ToString()); + case OpenIddictServerEndpointType.Token: + throw new InvalidOperationException(SR.GetResourceString(SR.ID1000)); - default: throw new InvalidOperationException(new StringBuilder() - .AppendLine("An identity cannot be extracted from this request.") - .Append("This generally indicates that the OpenIddict server stack was asked ") - .AppendLine("to validate a token for an endpoint it doesn't manage.") - .Append("To validate tokens received by custom API endpoints, ") - .Append("the OpenIddict validation services must be used instead.") - .ToString()); + default: throw new InvalidOperationException(SR.GetResourceString(SR.ID1001)); } } } @@ -236,7 +228,7 @@ namespace OpenIddict.Server { context.Reject( error: Errors.InvalidRequest, - description: "The security token is missing."); + description: context.Localizer[SR.ID3000]); return default; } @@ -316,13 +308,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateReferenceTokenIdentifier([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -373,13 +359,13 @@ namespace OpenIddict.Server description: context.EndpointType switch { OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType() - => "The specified authorization code is invalid.", + => context.Localizer[SR.ID3001], OpenIddictServerEndpointType.Token when context.Request.IsDeviceCodeGrantType() - => "The specified device code is invalid.", + => context.Localizer[SR.ID3002], OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType() - => "The specified refresh token is invalid.", + => context.Localizer[SR.ID3003], - _ => "The specified token is invalid." + _ => context.Localizer[SR.ID3004] }); return; @@ -388,10 +374,7 @@ namespace OpenIddict.Server var payload = await _tokenManager.GetPayloadAsync(token); if (string.IsNullOrEmpty(payload)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The payload associated with a reference token cannot be retrieved.") - .Append("This may indicate that the token entry was corrupted.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1025)); } // Replace the token parameter by the payload resolved from the token entry. @@ -479,7 +462,7 @@ namespace OpenIddict.Server // For user codes, only the short "oi_usrc+jwt" form is valid. TokenTypeHints.UserCode => new[] { JsonWebTokenTypes.Private.UserCode }, - _ => throw new InvalidOperationException("The token type is not supported.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1002)) }; var result = context.Options.JsonWebTokenHandler.ValidateToken(context.Token, parameters); @@ -496,21 +479,17 @@ namespace OpenIddict.Server description: (result.Exception, context.EndpointType) switch { (SecurityTokenInvalidTypeException _, OpenIddictServerEndpointType.Token) - when context.Request.IsAuthorizationCodeGrantType() - => "The specified token is not an authorization code.", + when context.Request.IsAuthorizationCodeGrantType() => context.Localizer[SR.ID3005], (SecurityTokenInvalidTypeException _, OpenIddictServerEndpointType.Token) - when context.Request.IsDeviceCodeGrantType() - => "The specified token is not an device code.", + when context.Request.IsDeviceCodeGrantType() => context.Localizer[SR.ID3006], (SecurityTokenInvalidTypeException _, OpenIddictServerEndpointType.Token) - when context.Request.IsRefreshTokenGrantType() - => "The specified token is not a refresh token.", + when context.Request.IsRefreshTokenGrantType() => context.Localizer[SR.ID3007], - (SecurityTokenInvalidTypeException _, OpenIddictServerEndpointType.Userinfo) - => "The specified token is not an access token.", + (SecurityTokenInvalidTypeException _, OpenIddictServerEndpointType.Userinfo) => context.Localizer[SR.ID3008], - _ => "The specified token is not valid." + _ => context.Localizer[SR.ID3027] }); return default; @@ -529,7 +508,7 @@ namespace OpenIddict.Server // Store the token type (resolved from "typ" or "token_usage") as a special private claim. context.Principal.SetTokenType(result.TokenType switch { - var type when string.IsNullOrEmpty(type) => throw new InvalidOperationException("The token type cannot be resolved"), + var type when string.IsNullOrEmpty(type) => throw new InvalidOperationException(SR.GetResourceString(SR.ID1024)), JsonWebTokenTypes.AccessToken => TokenTypeHints.AccessToken, JsonWebTokenTypes.Prefixes.Application + JsonWebTokenTypes.AccessToken => TokenTypeHints.AccessToken, @@ -542,7 +521,7 @@ namespace OpenIddict.Server JsonWebTokenTypes.Private.RefreshToken => TokenTypeHints.RefreshToken, JsonWebTokenTypes.Private.UserCode => TokenTypeHints.UserCode, - _ => throw new InvalidOperationException("The token type is not supported.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1002)) }); // Restore the claim destinations from the special oi_cl_dstn claim (represented as a dictionary/JSON object). @@ -726,13 +705,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public RestoreReferenceTokenProperties() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public RestoreReferenceTokenProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public RestoreReferenceTokenProperties([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -770,7 +743,7 @@ namespace OpenIddict.Server var token = await _tokenManager.FindByIdAsync(identifier); if (token == null) { - throw new InvalidOperationException("The token entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1020)); } // Restore the creation/expiration dates/identifiers from the token entry metadata. @@ -822,17 +795,17 @@ namespace OpenIddict.Server }, description: context.EndpointType switch { - OpenIddictServerEndpointType.Authorization => "The specified identity token hint is invalid.", - OpenIddictServerEndpointType.Logout => "The specified identity token hint is invalid.", + OpenIddictServerEndpointType.Authorization => context.Localizer[SR.ID3009], + OpenIddictServerEndpointType.Logout => context.Localizer[SR.ID3009], OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType() - => "The specified authorization code is invalid.", + => context.Localizer[SR.ID3001], OpenIddictServerEndpointType.Token when context.Request.IsDeviceCodeGrantType() - => "The specified device code is invalid.", + => context.Localizer[SR.ID3002], OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType() - => "The specified refresh token is invalid.", + => context.Localizer[SR.ID3003], - _ => "The specified token is invalid." + _ => context.Localizer[SR.ID3004] }); @@ -848,19 +821,12 @@ namespace OpenIddict.Server var type = context.Principal.GetTokenType(); if (string.IsNullOrEmpty(type)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The deserialized principal doesn't contain the mandatory 'oi_tkn_typ' claim.") - .Append("When implementing custom token deserialization, a 'oi_tkn_typ' claim containing ") - .Append("the type of the token being processed must be added to the security principal.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1003)); } if (!string.Equals(type, context.TokenType, StringComparison.OrdinalIgnoreCase)) { - throw new InvalidOperationException(new StringBuilder() - .AppendFormat("The type of token associated with the deserialized principal ({0}) ", type) - .AppendFormat("doesn't match the expected token type ({0}).", context.TokenType) - .ToString()); + throw new InvalidOperationException(SR.FormatID1004(type, context.TokenType)); } } @@ -878,13 +844,7 @@ namespace OpenIddict.Server private readonly IOpenIddictAuthorizationManager _authorizationManager; private readonly IOpenIddictTokenManager _tokenManager; - public ValidateTokenEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateTokenEntry( [NotNull] IOpenIddictAuthorizationManager authorizationManager, @@ -935,13 +895,13 @@ namespace OpenIddict.Server description: context.EndpointType switch { OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType() - => "The specified authorization code is invalid.", + => context.Localizer[SR.ID3001], OpenIddictServerEndpointType.Token when context.Request.IsDeviceCodeGrantType() - => "The specified device code is invalid.", + => context.Localizer[SR.ID3002], OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType() - => "The specified refresh token is invalid.", + => context.Localizer[SR.ID3003], - _ => "The specified token is invalid." + _ => context.Localizer[SR.ID3004] }); return; @@ -974,13 +934,13 @@ namespace OpenIddict.Server description: context.EndpointType switch { OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType() - => "The specified authorization code has already been redeemed.", + => context.Localizer[SR.ID3010], OpenIddictServerEndpointType.Token when context.Request.IsDeviceCodeGrantType() - => "The specified device code has already been redeemed.", + => context.Localizer[SR.ID3011], OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType() - => "The specified refresh token has already been redeemed.", + => context.Localizer[SR.ID3012], - _ => "The specified token has already been redeemed." + _ => context.Localizer[SR.ID3013] }); return; @@ -995,7 +955,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.AuthorizationPending, - description: "The authorization has not been granted yet by the end user."); + description: context.Localizer[SR.ID3014]); return; } @@ -1007,7 +967,7 @@ namespace OpenIddict.Server context.Reject( error: Errors.AccessDenied, - description: "The authorization demand has been rejected by the end user."); + description: context.Localizer[SR.ID3015]); return; } @@ -1027,13 +987,13 @@ namespace OpenIddict.Server description: context.EndpointType switch { OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType() - => "The specified authorization code is no longer valid.", + => context.Localizer[SR.ID3016], OpenIddictServerEndpointType.Token when context.Request.IsDeviceCodeGrantType() - => "The specified device code is no longer valid.", + => context.Localizer[SR.ID3017], OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType() - => "The specified refresh token is no longer valid.", + => context.Localizer[SR.ID3018], - _ => "The specified token is no longer valid." + _ => context.Localizer[SR.ID3019] }); return; @@ -1085,13 +1045,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictAuthorizationManager _authorizationManager; - public ValidateAuthorizationEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ValidateAuthorizationEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ValidateAuthorizationEntry([NotNull] IOpenIddictAuthorizationManager authorizationManager) => _authorizationManager = authorizationManager; @@ -1135,13 +1089,13 @@ namespace OpenIddict.Server description: context.EndpointType switch { OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType() - => "The authorization associated with the authorization code is no longer valid.", + => context.Localizer[SR.ID3020], OpenIddictServerEndpointType.Token when context.Request.IsDeviceCodeGrantType() - => "The authorization associated with the device code is no longer valid.", + => context.Localizer[SR.ID3021], OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType() - => "The authorization associated with the refresh token is no longer valid.", + => context.Localizer[SR.ID3022], - _ => "The authorization associated with the token is no longer valid." + _ => context.Localizer[SR.ID3023] }); return; @@ -1202,13 +1156,13 @@ namespace OpenIddict.Server description: context.EndpointType switch { OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType() - => "The specified authorization code is no longer valid.", + => context.Localizer[SR.ID3016], OpenIddictServerEndpointType.Token when context.Request.IsDeviceCodeGrantType() - => "The specified device code is no longer valid.", + => context.Localizer[SR.ID3017], OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType() - => "The specified refresh token is no longer valid.", + => context.Localizer[SR.ID3018], - _ => "The specified token is no longer valid." + _ => context.Localizer[SR.ID3019] }); return default; @@ -1255,7 +1209,7 @@ namespace OpenIddict.Server case OpenIddictServerEndpointType.Verification: return default; - default: throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint."); + default: throw new InvalidOperationException(SR.GetResourceString(SR.ID1005)); } } } @@ -1296,17 +1250,17 @@ namespace OpenIddict.Server OpenIddictServerEndpointType.Userinfo => Errors.InsufficientAccess, OpenIddictServerEndpointType.Verification => Errors.AccessDenied, - _ => throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1005)) }; context.Response.ErrorDescription ??= context.EndpointType switch { - OpenIddictServerEndpointType.Authorization => "The authorization was denied by the resource owner.", - OpenIddictServerEndpointType.Token => "The token request was rejected by the authorization server.", - OpenIddictServerEndpointType.Userinfo => "The user information access demand was rejected by the authorization server.", - OpenIddictServerEndpointType.Verification => "The authorization was denied by the resource owner.", + OpenIddictServerEndpointType.Authorization => context.Localizer[SR.ID3015], + OpenIddictServerEndpointType.Verification => context.Localizer[SR.ID3015], + OpenIddictServerEndpointType.Token => context.Localizer[SR.ID3024], + OpenIddictServerEndpointType.Userinfo => context.Localizer[SR.ID3025], - _ => throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1005)) }; return default; @@ -1321,13 +1275,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public RejectDeviceCodeEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public RejectDeviceCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public RejectDeviceCodeEntry([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -1365,13 +1313,13 @@ namespace OpenIddict.Server var notification = context.Transaction.GetProperty( typeof(ProcessAuthenticationContext).FullName) ?? - throw new InvalidOperationException("The authentication context cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1006)); // Extract the device code identifier from the user code principal. var identifier = notification.Principal.GetClaim(Claims.Private.DeviceCodeId); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The device code identifier cannot be extracted from the principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1007)); } var token = await _tokenManager.FindByIdAsync(identifier); @@ -1390,13 +1338,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public RejectUserCodeEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public RejectUserCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public RejectUserCodeEntry([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -1434,13 +1376,13 @@ namespace OpenIddict.Server var notification = context.Transaction.GetProperty( typeof(ProcessAuthenticationContext).FullName) ?? - throw new InvalidOperationException("The authentication context cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1006)); // Extract the device code identifier from the authentication principal. var identifier = notification.Principal.GetTokenId(); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1008)); } var token = await _tokenManager.FindByIdAsync(identifier); @@ -1489,15 +1431,12 @@ namespace OpenIddict.Server case OpenIddictServerEndpointType.Verification: break; - default: throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint."); + default: throw new InvalidOperationException(SR.GetResourceString(SR.ID1009)); } if (context.Principal.Identity == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified principal doesn't contain any claims-based identity.") - .Append("Make sure that 'ClaimsPrincipal.Identity' is not null.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1010)); } // Note: sign-in operations triggered from the device endpoint can't be associated to specific users @@ -1507,20 +1446,12 @@ namespace OpenIddict.Server { if (context.Principal.Identity.IsAuthenticated) { - throw new InvalidOperationException(new StringBuilder() - .Append("The specified principal contains an authenticated identity, which is not valid ") - .AppendLine("when the sign-in operation is triggered from the device authorization endpoint.") - .Append("Make sure that 'ClaimsPrincipal.Identity.AuthenticationType' is null ") - .Append("and that 'ClaimsPrincipal.Identity.IsAuthenticated' returns 'false'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1011)); } if (!string.IsNullOrEmpty(context.Principal.GetClaim(Claims.Subject))) { - throw new InvalidOperationException(new StringBuilder() - .Append("The specified principal contains a subject claim, which is not valid ") - .Append("when the sign-in operation is triggered from the device authorization endpoint.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1012)); } return default; @@ -1528,18 +1459,12 @@ namespace OpenIddict.Server if (!context.Principal.Identity.IsAuthenticated) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The specified principal doesn't contain a valid/authenticated identity.") - .Append("Make sure that 'ClaimsPrincipal.Identity.AuthenticationType' is not null ") - .Append("and that 'ClaimsPrincipal.Identity.IsAuthenticated' returns 'true'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1013)); } if (string.IsNullOrEmpty(context.Principal.GetClaim(Claims.Subject))) { - throw new InvalidOperationException(new StringBuilder() - .Append("The specified principal was rejected because the mandatory subject claim was missing.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1014)); } return default; @@ -1590,7 +1515,7 @@ namespace OpenIddict.Server var notification = context.Transaction.GetProperty( typeof(ProcessAuthenticationContext).FullName) ?? - throw new InvalidOperationException("The authentication context cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1006)); // Restore the internal claims resolved from the authorization code/refresh token. foreach (var claims in notification.Principal.Claims @@ -1603,7 +1528,7 @@ namespace OpenIddict.Server continue; } - // When the request is a verification request, don't flow the copy from the user code. + // When the request is a verification request, don't flow the scopes from the user code. if (context.EndpointType == OpenIddictServerEndpointType.Verification && string.Equals(claims.Key, Claims.Private.Scope, StringComparison.OrdinalIgnoreCase)) { @@ -1851,13 +1776,7 @@ namespace OpenIddict.Server private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictAuthorizationManager _authorizationManager; - public AttachAuthorization() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public AttachAuthorization() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public AttachAuthorization( [NotNull] IOpenIddictApplicationManager applicationManager, @@ -1921,7 +1840,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId); if (application == null) { - throw new InvalidOperationException("The application entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1016)); } descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); @@ -1930,7 +1849,7 @@ namespace OpenIddict.Server var authorization = await _authorizationManager.CreateAsync(descriptor); if (authorization == null) { - throw new InvalidOperationException("An unknown error occurred while creating an authorization entry."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1017)); } var identifier = await _authorizationManager.GetIdAsync(authorization); @@ -2319,7 +2238,7 @@ namespace OpenIddict.Server { var notification = context.Transaction.GetProperty( typeof(ProcessAuthenticationContext).FullName) ?? - throw new InvalidOperationException("The authentication context cannot be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1006)); principal.SetExpirationDate(notification.Principal.GetExpirationDate()); } @@ -2540,13 +2459,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public RedeemTokenEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public RedeemTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public RedeemTokenEntry([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -2618,15 +2531,16 @@ namespace OpenIddict.Server description: context.EndpointType switch { OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType() - => "The specified authorization code is no longer valid.", + => context.Localizer[SR.ID3016], OpenIddictServerEndpointType.Token when context.Request.IsDeviceCodeGrantType() - => "The specified device code is no longer valid.", + => context.Localizer[SR.ID3017], OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType() - => "The specified refresh token is no longer valid.", + => context.Localizer[SR.ID3018], - OpenIddictServerEndpointType.Verification => "The specified user code is no longer valid.", + OpenIddictServerEndpointType.Verification + => context.Localizer[SR.ID3026], - _ => "The specified token is no longer valid." + _ => context.Localizer["The specified token is no longer valid."] }); return; @@ -2642,13 +2556,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public RevokeExistingTokenEntries() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public RevokeExistingTokenEntries() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public RevokeExistingTokenEntries([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -2718,13 +2626,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public ExtendRefreshTokenEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ExtendRefreshTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ExtendRefreshTokenEntry([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -2773,7 +2675,7 @@ namespace OpenIddict.Server var token = await _tokenManager.FindByIdAsync(identifier); if (token == null) { - throw new InvalidOperationException("The token details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1264)); } // Compute the new expiration date of the refresh token and update the token entry. @@ -2799,13 +2701,7 @@ namespace OpenIddict.Server private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; - public CreateAccessTokenEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public CreateAccessTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public CreateAccessTokenEntry( [NotNull] IOpenIddictApplicationManager applicationManager, @@ -2845,7 +2741,7 @@ namespace OpenIddict.Server var principal = context.AccessTokenPrincipal; if (principal == null) { - throw new InvalidOperationException("A token cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1021)); } var descriptor = new OpenIddictTokenDescriptor @@ -2865,7 +2761,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId); if (application == null) { - throw new InvalidOperationException("The application entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1016)); } descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); @@ -2874,7 +2770,7 @@ namespace OpenIddict.Server var token = await _tokenManager.CreateAsync(descriptor); if (token == null) { - throw new InvalidOperationException("An unknown error occurred while creating a token entry."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1018)); } var identifier = await _tokenManager.GetIdAsync(token); @@ -2936,7 +2832,7 @@ namespace OpenIddict.Server if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var claims = new Dictionary(StringComparer.Ordinal); @@ -3004,13 +2900,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public ConvertReferenceAccessToken() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ConvertReferenceAccessToken() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ConvertReferenceAccessToken([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -3051,19 +2941,19 @@ namespace OpenIddict.Server var principal = context.AccessTokenPrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var identifier = principal.GetTokenId(); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1008)); } var token = await _tokenManager.FindByIdAsync(identifier); if (token == null) { - throw new InvalidOperationException("The token entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1020)); } // Generate a new crypto-secure random identifier that will be substituted to the token. @@ -3101,13 +2991,7 @@ namespace OpenIddict.Server private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; - public CreateAuthorizationCodeEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public CreateAuthorizationCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public CreateAuthorizationCodeEntry( [NotNull] IOpenIddictApplicationManager applicationManager, @@ -3147,7 +3031,7 @@ namespace OpenIddict.Server var principal = context.AuthorizationCodePrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var descriptor = new OpenIddictTokenDescriptor @@ -3167,7 +3051,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId); if (application == null) { - throw new InvalidOperationException("The application entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1016)); } descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); @@ -3176,7 +3060,7 @@ namespace OpenIddict.Server var token = await _tokenManager.CreateAsync(descriptor); if (token == null) { - throw new InvalidOperationException("An unknown error occurred while creating a token entry."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1018)); } var identifier = await _tokenManager.GetIdAsync(token); @@ -3236,7 +3120,7 @@ namespace OpenIddict.Server if (principal == null) { - throw new InvalidOperationException("A token cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1021)); } var descriptor = new SecurityTokenDescriptor @@ -3287,13 +3171,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public ConvertReferenceAuthorizationCode() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ConvertReferenceAuthorizationCode() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ConvertReferenceAuthorizationCode([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -3333,19 +3211,19 @@ namespace OpenIddict.Server var principal = context.AuthorizationCodePrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var identifier = principal.GetTokenId(); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1008)); } var token = await _tokenManager.FindByIdAsync(identifier); if (token == null) { - throw new InvalidOperationException("The token entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1020)); } // Generate a new crypto-secure random identifier that will be substituted to the token. @@ -3383,13 +3261,7 @@ namespace OpenIddict.Server private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; - public CreateDeviceCodeEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public CreateDeviceCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public CreateDeviceCodeEntry( [NotNull] IOpenIddictApplicationManager applicationManager, @@ -3434,7 +3306,7 @@ namespace OpenIddict.Server var principal = context.DeviceCodePrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var descriptor = new OpenIddictTokenDescriptor @@ -3454,7 +3326,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId); if (application == null) { - throw new InvalidOperationException("The application entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1016)); } descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); @@ -3463,7 +3335,7 @@ namespace OpenIddict.Server var token = await _tokenManager.CreateAsync(descriptor); if (token == null) { - throw new InvalidOperationException("An unknown error occurred while creating a token entry."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1018)); } var identifier = await _tokenManager.GetIdAsync(token); @@ -3523,7 +3395,7 @@ namespace OpenIddict.Server if (principal == null) { - throw new InvalidOperationException("A token cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1021)); } var descriptor = new SecurityTokenDescriptor @@ -3574,13 +3446,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public ConvertReferenceDeviceCode() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ConvertReferenceDeviceCode() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ConvertReferenceDeviceCode([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -3626,19 +3492,19 @@ namespace OpenIddict.Server var principal = context.DeviceCodePrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var identifier = principal.GetTokenId(); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1008)); } var token = await _tokenManager.FindByIdAsync(identifier); if (token == null) { - throw new InvalidOperationException("The token entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1020)); } // Generate a new crypto-secure random identifier that will be substituted to the token. @@ -3675,13 +3541,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public UpdateReferenceDeviceCodeEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public UpdateReferenceDeviceCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public UpdateReferenceDeviceCodeEntry([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -3726,20 +3586,20 @@ namespace OpenIddict.Server var principal = context.DeviceCodePrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } // Extract the token identifier from the authentication principal. var identifier = context.Principal.GetClaim(Claims.Private.DeviceCodeId); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The device code identifier cannot be extracted from the principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1007)); } var token = await _tokenManager.FindByIdAsync(identifier); if (token == null) { - throw new InvalidOperationException("The token details cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1264)); } // Replace the device code details by the payload derived from the new device code principal, @@ -3773,13 +3633,7 @@ namespace OpenIddict.Server private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; - public CreateRefreshTokenEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public CreateRefreshTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public CreateRefreshTokenEntry( [NotNull] IOpenIddictApplicationManager applicationManager, @@ -3819,7 +3673,7 @@ namespace OpenIddict.Server var principal = context.RefreshTokenPrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var descriptor = new OpenIddictTokenDescriptor @@ -3839,7 +3693,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId); if (application == null) { - throw new InvalidOperationException("The application entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1016)); } descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); @@ -3848,7 +3702,7 @@ namespace OpenIddict.Server var token = await _tokenManager.CreateAsync(descriptor); if (token == null) { - throw new InvalidOperationException("An unknown error occurred while creating a token entry."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1018)); } var identifier = await _tokenManager.GetIdAsync(token); @@ -3908,7 +3762,7 @@ namespace OpenIddict.Server if (principal == null) { - throw new InvalidOperationException("A token cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1021)); } var descriptor = new SecurityTokenDescriptor @@ -3959,13 +3813,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public ConvertReferenceRefreshToken() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ConvertReferenceRefreshToken() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ConvertReferenceRefreshToken([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -4006,19 +3854,19 @@ namespace OpenIddict.Server var principal = context.RefreshTokenPrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var identifier = principal.GetTokenId(); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1008)); } var token = await _tokenManager.FindByIdAsync(identifier); if (token == null) { - throw new InvalidOperationException("The token entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1020)); } // Generate a new crypto-secure random identifier that will be substituted to the token. @@ -4081,7 +3929,7 @@ namespace OpenIddict.Server var principal = context.UserCodePrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var identifier = context.DeviceCodePrincipal.GetTokenId(); @@ -4103,13 +3951,7 @@ namespace OpenIddict.Server private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; - public CreateUserCodeEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public CreateUserCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public CreateUserCodeEntry( [NotNull] IOpenIddictApplicationManager applicationManager, @@ -4149,7 +3991,7 @@ namespace OpenIddict.Server var principal = context.UserCodePrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var descriptor = new OpenIddictTokenDescriptor @@ -4169,7 +4011,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId); if (application == null) { - throw new InvalidOperationException("The application entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1016)); } descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); @@ -4178,7 +4020,7 @@ namespace OpenIddict.Server var token = await _tokenManager.CreateAsync(descriptor); if (token == null) { - throw new InvalidOperationException("An unknown error occurred while creating a token entry."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1018)); } var identifier = await _tokenManager.GetIdAsync(token); @@ -4238,7 +4080,7 @@ namespace OpenIddict.Server if (principal == null) { - throw new InvalidOperationException("A token cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1021)); } var descriptor = new SecurityTokenDescriptor @@ -4279,13 +4121,7 @@ namespace OpenIddict.Server { private readonly IOpenIddictTokenManager _tokenManager; - public ConvertReferenceUserCode() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public ConvertReferenceUserCode() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public ConvertReferenceUserCode([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -4326,19 +4162,19 @@ namespace OpenIddict.Server var principal = context.UserCodePrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var identifier = principal.GetTokenId(); if (string.IsNullOrEmpty(identifier)) { - throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1008)); } var token = await _tokenManager.FindByIdAsync(identifier); if (token == null) { - throw new InvalidOperationException("The token entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1020)); } // Note: unlike other reference tokens, user codes are meant to be used by humans, @@ -4420,13 +4256,13 @@ namespace OpenIddict.Server credentials => credentials.Key is AsymmetricSecurityKey); if (credentials == null) { - throw new InvalidOperationException("No suitable signing credentials could be found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1265)); } using var hash = GetHashAlgorithm(credentials); if (hash == null || hash is KeyedHashAlgorithm) { - throw new InvalidOperationException("The signing credentials algorithm is not valid."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1266)); } if (!string.IsNullOrEmpty(context.Response.AccessToken)) @@ -4500,7 +4336,7 @@ namespace OpenIddict.Server SecurityAlgorithms.RsaSsaPssSha384Signature => HashAlgorithmName.SHA384, SecurityAlgorithms.RsaSsaPssSha512Signature => HashAlgorithmName.SHA512, - _ => throw new InvalidOperationException("The signing credentials algorithm is not supported.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1266)) } }; @@ -4521,13 +4357,7 @@ namespace OpenIddict.Server private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; - public CreateIdentityTokenEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling the OpenIddict server feature.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .Append("Alternatively, you can disable the built-in database-based server features by enabling ") - .Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.") - .ToString()); + public CreateIdentityTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1015)); public CreateIdentityTokenEntry( [NotNull] IOpenIddictApplicationManager applicationManager, @@ -4567,7 +4397,7 @@ namespace OpenIddict.Server var principal = context.IdentityTokenPrincipal; if (principal == null) { - throw new InvalidOperationException("A token entry cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1019)); } var descriptor = new OpenIddictTokenDescriptor @@ -4587,7 +4417,7 @@ namespace OpenIddict.Server var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId); if (application == null) { - throw new InvalidOperationException("The application entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1016)); } descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); @@ -4596,7 +4426,7 @@ namespace OpenIddict.Server var token = await _tokenManager.CreateAsync(descriptor); if (token == null) { - throw new InvalidOperationException("An unknown error occurred while creating a token entry."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1018)); } var identifier = await _tokenManager.GetIdAsync(token); @@ -4657,7 +4487,7 @@ namespace OpenIddict.Server if (principal == null) { - throw new InvalidOperationException("A token cannot be created from a null principal."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1021)); } var claims = new Dictionary(StringComparer.Ordinal); @@ -4883,7 +4713,7 @@ namespace OpenIddict.Server // At this stage, throw an exception if the issuer cannot be retrieved. if (issuer == null || !issuer.IsAbsoluteUri) { - throw new InvalidOperationException("The issuer must be a non-null, non-empty absolute URL."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1022)); } // Ensure the issuer ends with a trailing slash, as it is necessary @@ -4937,7 +4767,7 @@ namespace OpenIddict.Server if (context.EndpointType != OpenIddictServerEndpointType.Logout) { - throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1023)); } return default; diff --git a/src/OpenIddict.Server/OpenIddictServerHelpers.cs b/src/OpenIddict.Server/OpenIddictServerHelpers.cs index 357e9251..1ad27c06 100644 --- a/src/OpenIddict.Server/OpenIddictServerHelpers.cs +++ b/src/OpenIddict.Server/OpenIddictServerHelpers.cs @@ -6,6 +6,7 @@ using System; using JetBrains.Annotations; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -31,7 +32,7 @@ namespace OpenIddict.Server if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The property name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1105), nameof(name)); } if (transaction.Properties.TryGetValue(name, out var property) && property is TProperty result) @@ -61,7 +62,7 @@ namespace OpenIddict.Server if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The property name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1105), nameof(name)); } if (value == null) diff --git a/src/OpenIddict.Server/OpenIddictServerOptions.cs b/src/OpenIddict.Server/OpenIddictServerOptions.cs index ca501f28..45d841e3 100644 --- a/src/OpenIddict.Server/OpenIddictServerOptions.cs +++ b/src/OpenIddict.Server/OpenIddictServerOptions.cs @@ -12,6 +12,7 @@ using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server { @@ -146,7 +147,7 @@ namespace OpenIddict.Server TokenTypeHints.AccessToken => JsonWebTokenTypes.AccessToken, TokenTypeHints.IdToken => JsonWebTokenTypes.IdentityToken, - _ => throw new NotSupportedException("The token usage of the JWT token is not supported.") + _ => throw new NotSupportedException(SR.GetResourceString(SR.ID1268)) }; } @@ -154,14 +155,14 @@ namespace OpenIddict.Server // (provided via the type delegate parameter) or inferred from the token_usage claim. if (string.IsNullOrEmpty(type)) { - throw new SecurityTokenInvalidTypeException("The type of the JWT token cannot be resolved or inferred."); + throw new SecurityTokenInvalidTypeException(SR.GetResourceString(SR.ID1269)); } // Note: unlike IdentityModel, this custom validator deliberately uses case-insensitive comparisons. if (parameters.ValidTypes != null && parameters.ValidTypes.Any() && !parameters.ValidTypes.Contains(type, StringComparer.OrdinalIgnoreCase)) { - throw new SecurityTokenInvalidTypeException("The type of the JWT token doesn't match the expected type.") + throw new SecurityTokenInvalidTypeException(SR.GetResourceString(SR.ID1270)) { InvalidType = type }; diff --git a/src/OpenIddict.Server/OpenIddictServerTransaction.cs b/src/OpenIddict.Server/OpenIddictServerTransaction.cs index 681910ba..0fc3916b 100644 --- a/src/OpenIddict.Server/OpenIddictServerTransaction.cs +++ b/src/OpenIddict.Server/OpenIddictServerTransaction.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using OpenIddict.Abstractions; @@ -26,6 +27,11 @@ namespace OpenIddict.Server /// public Uri Issuer { get; set; } + /// + /// Gets or sets the localizer associated with the current request. + /// + public IStringLocalizer Localizer { get; set; } + /// /// Gets or sets the logger associated with the current request. /// diff --git a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreBuilder.cs b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreBuilder.cs index 15392b03..909d73f0 100644 --- a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreBuilder.cs +++ b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreBuilder.cs @@ -8,6 +8,7 @@ using System; using System.ComponentModel; using JetBrains.Annotations; using OpenIddict.Validation.AspNetCore; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace Microsoft.Extensions.DependencyInjection { @@ -57,7 +58,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(realm)) { - throw new ArgumentException("The realm cannot be null or empty.", nameof(realm)); + throw new ArgumentException(SR.GetResourceString(SR.ID1106), nameof(realm)); } return Configure(options => options.Realm = realm); diff --git a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreConfiguration.cs b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreConfiguration.cs index 4249da6c..4c00c25a 100644 --- a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreConfiguration.cs +++ b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreConfiguration.cs @@ -5,10 +5,10 @@ */ using System; -using System.Text; using JetBrains.Annotations; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.AspNetCore { @@ -34,10 +34,7 @@ namespace OpenIddict.Validation.AspNetCore if (options.SchemeMap.TryGetValue(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme, out var builder) && builder.HandlerType != typeof(OpenIddictValidationAspNetCoreHandler)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The OpenIddict ASP.NET Core validation handler cannot be registered as an authentication scheme.") - .Append("This may indicate that an instance of another handler was registered with the same scheme.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1163)); } options.AddScheme( @@ -80,11 +77,7 @@ namespace OpenIddict.Validation.AspNetCore if (!TryValidate(options.DefaultSignInScheme) || !TryValidate(options.DefaultSignOutScheme)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The OpenIddict ASP.NET Core validation cannot be used as the default sign-in/sign-out handler.") - .Append("Make sure that neither DefaultSignInScheme nor DefaultSignOutScheme ") - .Append("point to an instance of the OpenIddict ASP.NET Core validation handler.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1164)); } } } diff --git a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs index b7a94e46..3685443d 100644 --- a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs +++ b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; -using System.Text; using System.Text.Encodings.Web; using System.Threading.Tasks; using JetBrains.Annotations; @@ -17,6 +16,7 @@ using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Validation.OpenIddictValidationEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.AspNetCore { @@ -98,11 +98,7 @@ namespace OpenIddict.Validation.AspNetCore return false; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } return false; @@ -111,7 +107,7 @@ namespace OpenIddict.Validation.AspNetCore protected override async Task HandleAuthenticateAsync() { var transaction = Context.Features.Get()?.Transaction ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict validation context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); // Note: in many cases, the authentication token was already validated by the time this action is called // (generally later in the pipeline, when using the pass-through mode). To avoid having to re-validate it, @@ -149,7 +145,7 @@ namespace OpenIddict.Validation.AspNetCore [OpenIddictValidationAspNetCoreConstants.Properties.ErrorUri] = context.ErrorUri }); - return AuthenticateResult.Fail("An error occurred while authenticating the current request.", properties); + return AuthenticateResult.Fail(SR.GetResourceString(SR.ID1112), properties); } else @@ -175,7 +171,7 @@ namespace OpenIddict.Validation.AspNetCore protected override async Task HandleChallengeAsync([CanBeNull] AuthenticationProperties properties) { var transaction = Context.Features.Get()?.Transaction ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict validation context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); transaction.Properties[typeof(AuthenticationProperties).FullName] = properties ?? new AuthenticationProperties(); @@ -210,11 +206,7 @@ namespace OpenIddict.Validation.AspNetCore return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } } diff --git a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs index f265b568..655c8319 100644 --- a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs +++ b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs @@ -25,6 +25,7 @@ using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Validation.AspNetCore.OpenIddictValidationAspNetCoreHandlerFilters; using static OpenIddict.Validation.OpenIddictValidationEvents; using Properties = OpenIddict.Validation.AspNetCore.OpenIddictValidationAspNetCoreConstants.Properties; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.AspNetCore { @@ -100,7 +101,7 @@ namespace OpenIddict.Validation.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // Only use the current host as the issuer if the @@ -114,7 +115,7 @@ namespace OpenIddict.Validation.AspNetCore { context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'Host' header is missing."); + description: context.Localizer[SR.ID3081]); return default; } @@ -124,7 +125,7 @@ namespace OpenIddict.Validation.AspNetCore { context.Reject( error: Errors.InvalidRequest, - description: "The specified 'Host' header is invalid."); + description: context.Localizer[SR.ID3082]); return default; } @@ -177,7 +178,7 @@ namespace OpenIddict.Validation.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // Resolve the access token from the standard Authorization header. @@ -237,7 +238,7 @@ namespace OpenIddict.Validation.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } if (string.IsNullOrEmpty(request.ContentType) || @@ -301,7 +302,7 @@ namespace OpenIddict.Validation.AspNetCore var request = context.Transaction.GetHttpRequest(); if (request == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // Resolve the access token from the standard access_token query parameter. @@ -398,7 +399,7 @@ namespace OpenIddict.Validation.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } response.StatusCode = context.Response.Error switch @@ -454,7 +455,7 @@ namespace OpenIddict.Validation.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // Prevent the response from being cached. @@ -507,7 +508,7 @@ namespace OpenIddict.Validation.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } var scheme = context.Response.Error switch @@ -616,7 +617,7 @@ namespace OpenIddict.Validation.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } // If the response doesn't contain a WWW-Authenticate header, don't return an empty response. @@ -668,7 +669,7 @@ namespace OpenIddict.Validation.AspNetCore var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; if (response == null) { - throw new InvalidOperationException("The ASP.NET Core HTTP request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); } context.Logger.LogInformation("The response was successfully returned as a JSON document: {Response}.", context.Response); diff --git a/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionConfiguration.cs b/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionConfiguration.cs index 7e4d2e2d..43d98a00 100644 --- a/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionConfiguration.cs +++ b/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionConfiguration.cs @@ -8,7 +8,6 @@ using System; using JetBrains.Annotations; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Options; -using Microsoft.IdentityModel.Tokens; namespace OpenIddict.Validation.DataProtection { diff --git a/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionHandlers.cs b/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionHandlers.cs index c97a550b..4a0b5eb7 100644 --- a/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionHandlers.cs +++ b/src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionHandlers.cs @@ -21,6 +21,7 @@ using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationHandlers; using Properties = OpenIddict.Validation.OpenIddictValidationConstants.Properties; using Schemes = OpenIddict.Validation.DataProtection.OpenIddictValidationDataProtectionConstants.Purposes.Schemes; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.DataProtection { @@ -83,14 +84,14 @@ namespace OpenIddict.Validation.DataProtection // Create a Data Protection protector using the provider registered in the options. var protector = _options.CurrentValue.DataProtectionProvider.CreateProtector(context.TokenType switch { - null => throw new InvalidOperationException("Generic token validation is not supported by the validation handler."), + null => throw new InvalidOperationException(SR.GetResourceString(SR.ID1166)), TokenTypeHints.AccessToken when context.Transaction.Properties.ContainsKey(Properties.ReferenceTokenIdentifier) => new[] { Handlers.Server, Formats.AccessToken, Features.ReferenceTokens, Schemes.Server }, TokenTypeHints.AccessToken => new[] { Handlers.Server, Formats.AccessToken, Schemes.Server }, - _ => throw new InvalidOperationException("The specified token type is not supported.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1002)) }); try @@ -112,7 +113,7 @@ namespace OpenIddict.Validation.DataProtection { context.Reject( error: Errors.InvalidToken, - description: "The specified token is not valid."); + description: context.Localizer[SR.ID3027]); return default; } diff --git a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinBuilder.cs b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinBuilder.cs index 1a78afe0..f108a2bf 100644 --- a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinBuilder.cs +++ b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinBuilder.cs @@ -9,6 +9,7 @@ using System.ComponentModel; using JetBrains.Annotations; using Microsoft.Owin.Security; using OpenIddict.Validation.Owin; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace Microsoft.Extensions.DependencyInjection { @@ -73,7 +74,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(realm)) { - throw new ArgumentException("The realm cannot be null or empty.", nameof(realm)); + throw new ArgumentException(SR.GetResourceString(SR.ID1106), nameof(realm)); } return Configure(options => options.Realm = realm); diff --git a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs index 137a931d..0a9f31db 100644 --- a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs +++ b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; using System.Security.Claims; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Owin; @@ -16,6 +15,7 @@ using Microsoft.Owin.Security.Infrastructure; using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Validation.OpenIddictValidationEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.Owin { @@ -70,10 +70,10 @@ namespace OpenIddict.Validation.Owin // active authentication is used, as AuthenticateCoreAsync() is always called before InvokeAsync() in this case. var transaction = Context.Get(typeof(OpenIddictValidationTransaction).FullName) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict validation context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); var context = transaction.GetProperty(typeof(ProcessRequestContext).FullName) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict validation context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); if (context.IsRequestHandled) { @@ -109,11 +109,7 @@ namespace OpenIddict.Validation.Owin return false; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } return false; @@ -122,7 +118,7 @@ namespace OpenIddict.Validation.Owin protected override async Task AuthenticateCoreAsync() { var transaction = Context.Get(typeof(OpenIddictValidationTransaction).FullName) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict validation context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); // Note: in many cases, the authentication token was already validated by the time this action is called // (generally later in the pipeline, when using the pass-through mode). To avoid having to re-validate it, @@ -197,7 +193,7 @@ namespace OpenIddict.Validation.Owin if (challenge != null && (Response.StatusCode == 401 || Response.StatusCode == 403)) { var transaction = Context.Get(typeof(OpenIddictValidationTransaction).FullName) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict validation context."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); transaction.Properties[typeof(AuthenticationProperties).FullName] = challenge.Properties ?? new AuthenticationProperties(); @@ -232,11 +228,7 @@ namespace OpenIddict.Validation.Owin return; } - throw new InvalidOperationException(new StringBuilder() - .Append("The OpenID Connect response was not correctly processed. This may indicate ") - .Append("that the event handler responsible of processing OpenID Connect responses ") - .Append("was not registered or was explicitly removed from the handlers list.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1110)); } } } diff --git a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs index d237f9fe..ff739931 100644 --- a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs +++ b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs @@ -22,6 +22,7 @@ using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.Owin.OpenIddictValidationOwinHandlerFilters; using Properties = OpenIddict.Validation.Owin.OpenIddictValidationOwinConstants.Properties; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.Owin { @@ -97,7 +98,7 @@ namespace OpenIddict.Validation.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // Only use the current host as the issuer if the @@ -111,7 +112,7 @@ namespace OpenIddict.Validation.Owin { context.Reject( error: Errors.InvalidRequest, - description: "The mandatory 'Host' header is missing."); + description: context.Localizer[SR.ID3081]); return default; } @@ -121,7 +122,7 @@ namespace OpenIddict.Validation.Owin { context.Reject( error: Errors.InvalidRequest, - description: "The specified 'Host' header is invalid."); + description: context.Localizer[SR.ID3082]); return default; } @@ -174,7 +175,7 @@ namespace OpenIddict.Validation.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // Resolve the access token from the standard Authorization header. @@ -234,7 +235,7 @@ namespace OpenIddict.Validation.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.IsNullOrEmpty(request.ContentType) || @@ -299,7 +300,7 @@ namespace OpenIddict.Validation.Owin var request = context.Transaction.GetOwinRequest(); if (request == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // Resolve the access token from the standard access_token query parameter. @@ -400,7 +401,7 @@ namespace OpenIddict.Validation.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } response.StatusCode = context.Response.Error switch @@ -456,7 +457,7 @@ namespace OpenIddict.Validation.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // Prevent the response from being cached. @@ -509,7 +510,7 @@ namespace OpenIddict.Validation.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } if (string.IsNullOrEmpty(context.Response.Error)) @@ -623,7 +624,7 @@ namespace OpenIddict.Validation.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } // If the response doesn't contain a WWW-Authenticate header, don't return an empty response. @@ -675,7 +676,7 @@ namespace OpenIddict.Validation.Owin var response = context.Transaction.GetOwinRequest()?.Context.Response; if (response == null) { - throw new InvalidOperationException("The OWIN request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); } context.Logger.LogInformation("The response was successfully returned as a JSON document: {Response}.", context.Response); diff --git a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinMiddlewareFactory.cs b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinMiddlewareFactory.cs index b3a12a36..d2d892e6 100644 --- a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinMiddlewareFactory.cs +++ b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinMiddlewareFactory.cs @@ -5,12 +5,12 @@ */ using System; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Microsoft.Owin; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.Owin { @@ -48,13 +48,7 @@ namespace OpenIddict.Validation.Owin var provider = context.Get(typeof(IServiceProvider).FullName); if (provider == null) { - throw new InvalidOperationException(new StringBuilder() - .Append("No service provider was found in the OWIN context. For the OpenIddict validation ") - .Append("services to work correctly, a per-request 'IServiceProvider' must be attached ") - .AppendLine("to the OWIN environment with the dictionary key 'System.IServiceProvider'.") - .Append("Note: when using a dependency injection container supporting middleware resolution ") - .Append("(like Autofac), the 'app.UseOpenIddictValidation()' extension MUST NOT be called.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1167)); } // Note: the Microsoft.Extensions.DependencyInjection container doesn't support resolving services @@ -69,11 +63,8 @@ namespace OpenIddict.Validation.Owin return middleware.Invoke(context); - static T GetRequiredService(IServiceProvider provider) - => provider.GetService() ?? throw new InvalidOperationException(new StringBuilder() - .AppendLine("The OpenIddict validation services cannot be resolved from the DI container.") - .Append("To register the OWIN services, use 'services.AddOpenIddict().AddValidation().UseOwin()'.") - .ToString()); + static T GetRequiredService(IServiceProvider provider) => provider.GetService() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID1168)); } } } diff --git a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs index 3a2f9bbd..100d3f7d 100644 --- a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs +++ b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs @@ -5,11 +5,11 @@ */ using System; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using OpenIddict.Server; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.ServerIntegration { @@ -75,7 +75,7 @@ namespace OpenIddict.Validation.ServerIntegration if (options.ValidationType != OpenIddictValidationType.Direct) { - throw new InvalidOperationException("The local server integration can only be used with direct validation."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1169)); } // Note: authorization validation requires that authorizations have an entry @@ -83,10 +83,7 @@ namespace OpenIddict.Validation.ServerIntegration // not created if the authorization storage is disabled in the server options. if (options.EnableAuthorizationEntryValidation && _options.CurrentValue.DisableAuthorizationStorage) { - throw new InvalidOperationException(new StringBuilder() - .Append("Authorization entry validation cannot be enabled when authorization ") - .Append("storage is disabled in the OpenIddict server options.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1170)); } // Note: token validation requires that tokens have an entry in the database @@ -94,10 +91,7 @@ namespace OpenIddict.Validation.ServerIntegration // token storage is disabled in the OpenIddict server options. if (options.EnableTokenEntryValidation && _options.CurrentValue.DisableTokenStorage) { - throw new InvalidOperationException(new StringBuilder() - .Append("Token entry validation cannot be enabled when token storage ") - .Append("is disabled in the OpenIddict server options.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1171)); } } } diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs index 0a33d81c..30f1b392 100644 --- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs +++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs @@ -14,6 +14,7 @@ using JetBrains.Annotations; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.SystemNetHttp.OpenIddictValidationSystemNetHttpHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.SystemNetHttp { @@ -63,11 +64,11 @@ namespace OpenIddict.Validation.SystemNetHttp var request = context.Transaction.GetHttpRequestMessage(); if (request == null) { - throw new InvalidOperationException("The System.Net.Http request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1172)); } var configuration = await context.Options.ConfigurationManager.GetConfigurationAsync(default) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the server configuration."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1139)); // The OAuth 2.0 specification recommends sending the client credentials using basic authentication. // However, this authentication method is known to have compatibility issues with how the diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs index 7bd0d9f0..6a5f08dc 100644 --- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs +++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs @@ -17,6 +17,7 @@ using JetBrains.Annotations; using OpenIddict.Abstractions; using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.SystemNetHttp.OpenIddictValidationSystemNetHttpHandlerFilters; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation.SystemNetHttp { @@ -124,7 +125,7 @@ namespace OpenIddict.Validation.SystemNetHttp var request = context.Transaction.GetHttpRequestMessage(); if (request == null) { - throw new InvalidOperationException("The System.Net.Http request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1172)); } // Note: System.Net.Http doesn't expose convenient methods allowing to create @@ -174,7 +175,7 @@ namespace OpenIddict.Validation.SystemNetHttp var request = context.Transaction.GetHttpRequestMessage(); if (request == null) { - throw new InvalidOperationException("The System.Net.Http request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1172)); } request.Content = new FormUrlEncodedContent( @@ -221,20 +222,20 @@ namespace OpenIddict.Validation.SystemNetHttp var request = context.Transaction.GetHttpRequestMessage(); if (request == null) { - throw new InvalidOperationException("The System.Net.Http request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1172)); } var assembly = typeof(OpenIddictValidationSystemNetHttpOptions).Assembly.GetName(); using var client = _factory.CreateClient(assembly.Name); if (client == null) { - throw new InvalidOperationException("An unknown error occurred while creating a System.Net.Http client."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1173)); } var response = await client.SendAsync(request, HttpCompletionOption.ResponseContentRead); if (response == null) { - throw new InvalidOperationException("An unknown error occurred while sending a System.Net.Http request."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1174)); } // Store the HttpResponseMessage in the transaction properties. @@ -270,7 +271,7 @@ namespace OpenIddict.Validation.SystemNetHttp var response = context.Transaction.GetHttpResponseMessage(); if (response == null) { - throw new InvalidOperationException("The System.Net.Http request cannot be resolved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1172)); } // The status code is deliberately not validated to ensure even errored responses diff --git a/src/OpenIddict.Validation/OpenIddict.Validation.csproj b/src/OpenIddict.Validation/OpenIddict.Validation.csproj index 1ba4dc2c..a4a2a411 100644 --- a/src/OpenIddict.Validation/OpenIddict.Validation.csproj +++ b/src/OpenIddict.Validation/OpenIddict.Validation.csproj @@ -17,6 +17,7 @@ To use the validation feature on ASP.NET Core or OWIN/Katana, reference the Open + diff --git a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs index 73bad25c..018710e0 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs @@ -11,12 +11,12 @@ using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; using OpenIddict.Validation; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute; namespace Microsoft.Extensions.DependencyInjection @@ -161,7 +161,7 @@ namespace Microsoft.Extensions.DependencyInjection if (key is AsymmetricSecurityKey asymmetricSecurityKey && asymmetricSecurityKey.PrivateKeyStatus == PrivateKeyStatus.DoesNotExist) { - throw new InvalidOperationException("The asymmetric encryption key doesn't contain the required private key."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1054)); } if (key.IsSupportedAlgorithm(SecurityAlgorithms.Aes256KW)) @@ -176,10 +176,7 @@ namespace Microsoft.Extensions.DependencyInjection SecurityAlgorithms.RsaOAEP, SecurityAlgorithms.Aes256CbcHmacSha512)); } - throw new InvalidOperationException(new StringBuilder() - .AppendLine("An encryption algorithm cannot be automatically inferred from the encrypting key.") - .Append("Consider using 'options.AddEncryptionCredentials(EncryptingCredentials)' instead.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1055)); } /// @@ -201,13 +198,13 @@ namespace Microsoft.Extensions.DependencyInjection var extensions = certificate.Extensions.OfType().ToList(); if (extensions.Count != 0 && !extensions.Any(extension => extension.KeyUsages.HasFlag(X509KeyUsageFlags.KeyEncipherment))) { - throw new InvalidOperationException("The specified certificate is not a key encryption certificate."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1059)); } } if (!certificate.HasPrivateKey) { - throw new InvalidOperationException("The specified certificate doesn't contain the required private key."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1060)); } return AddEncryptionKey(new X509SecurityKey(certificate)); @@ -250,18 +247,18 @@ namespace Microsoft.Extensions.DependencyInjection if (string.IsNullOrEmpty(resource)) { - throw new ArgumentException("The resource cannot be null or empty.", nameof(resource)); + throw new ArgumentException(SR.GetResourceString(SR.ID1061), nameof(resource)); } if (string.IsNullOrEmpty(password)) { - throw new ArgumentException("The password cannot be null or empty.", nameof(password)); + throw new ArgumentException(SR.GetResourceString(SR.ID1062), nameof(password)); } using var stream = assembly.GetManifestResourceStream(resource); if (stream == null) { - throw new InvalidOperationException("The certificate was not found in the specified assembly."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1063)); } return AddEncryptionCertificate(stream, password, flags); @@ -305,7 +302,7 @@ namespace Microsoft.Extensions.DependencyInjection if (string.IsNullOrEmpty(password)) { - throw new ArgumentException("The password cannot be null or empty.", nameof(password)); + throw new ArgumentException(SR.GetResourceString(SR.ID1062), nameof(password)); } using var buffer = new MemoryStream(); @@ -323,13 +320,13 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(thumbprint)) { - throw new ArgumentException("The thumbprint cannot be null or empty.", nameof(thumbprint)); + throw new ArgumentException(SR.GetResourceString(SR.ID1064), nameof(thumbprint)); } var certificate = GetCertificate(StoreLocation.CurrentUser, thumbprint) ?? GetCertificate(StoreLocation.LocalMachine, thumbprint); if (certificate == null) { - throw new InvalidOperationException("The certificate corresponding to the specified thumbprint was not found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1065)); } return AddEncryptionCertificate(certificate); @@ -357,7 +354,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(thumbprint)) { - throw new ArgumentException("The thumbprint cannot be null or empty.", nameof(thumbprint)); + throw new ArgumentException(SR.GetResourceString(SR.ID1064), nameof(thumbprint)); } using var store = new X509Store(name, location); @@ -369,7 +366,7 @@ namespace Microsoft.Extensions.DependencyInjection if (certificate == null) { - throw new InvalidOperationException("The certificate corresponding to the specified thumbprint was not found."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1065)); } return AddEncryptionCertificate(certificate); @@ -390,7 +387,7 @@ namespace Microsoft.Extensions.DependencyInjection if (audiences.Any(audience => string.IsNullOrEmpty(audience))) { - throw new ArgumentException("Audiences cannot be null or empty.", nameof(audiences)); + throw new ArgumentException(SR.GetResourceString(SR.ID1122), nameof(audiences)); } return Configure(options => options.Audiences.UnionWith(audiences)); @@ -442,7 +439,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(identifier)) { - throw new ArgumentException("The client identifier cannot be null or empty.", nameof(identifier)); + throw new ArgumentException(SR.GetResourceString(SR.ID1123), nameof(identifier)); } return Configure(options => options.ClientId = identifier); @@ -458,7 +455,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(secret)) { - throw new ArgumentException("The client secret cannot be null or empty.", nameof(secret)); + throw new ArgumentException(SR.GetResourceString(SR.ID1124), nameof(secret)); } return Configure(options => options.ClientSecret = secret); @@ -490,12 +487,12 @@ namespace Microsoft.Extensions.DependencyInjection { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The issuer cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1125), nameof(address)); } - + if (!Uri.TryCreate(address, UriKind.Absolute, out Uri uri) || !uri.IsWellFormedOriginalString()) { - throw new ArgumentException("The issuer must be a valid absolute URL.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1126), nameof(address)); } return SetIssuer(uri); diff --git a/src/OpenIddict.Validation/OpenIddictValidationConfiguration.cs b/src/OpenIddict.Validation/OpenIddictValidationConfiguration.cs index 5708d0e3..05b6e1c2 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationConfiguration.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationConfiguration.cs @@ -6,13 +6,13 @@ using System; using System.Linq; -using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; using static OpenIddict.Validation.OpenIddictValidationEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -41,59 +41,45 @@ namespace OpenIddict.Validation if (options.JsonWebTokenHandler == null) { - throw new InvalidOperationException("The security token handler cannot be null."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1074)); } if (options.Configuration == null && options.ConfigurationManager == null && options.Issuer == null && options.MetadataAddress == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("An OAuth 2.0/OpenID Connect server configuration or an issuer address must be registered.") - .Append("To use a local OpenIddict server, reference the 'OpenIddict.Validation.ServerIntegration' package ") - .AppendLine("and call 'services.AddOpenIddict().AddValidation().UseLocalServer()' to import the server settings.") - .Append("To use a remote server, reference the 'OpenIddict.Validation.SystemNetHttp' package and call ") - .Append("'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' ") - .AppendLine("and 'services.AddOpenIddict().AddValidation().SetIssuer()' to use server discovery.") - .Append("Alternatively, you can register a static server configuration by calling ") - .Append("'services.AddOpenIddict().AddValidation().SetConfiguration()'.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1127)); } if (options.ValidationType == OpenIddictValidationType.Introspection) { if (!options.Handlers.Any(descriptor => descriptor.ContextType == typeof(ApplyIntrospectionRequestContext))) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("An introspection client must be registered when using introspection.") - .Append("Reference the 'OpenIddict.Validation.SystemNetHttp' package and call ") - .Append("'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' ") - .Append("to register the default System.Net.Http-based integration.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1128)); } if (options.Issuer == null && options.MetadataAddress == null) { - throw new InvalidOperationException("The issuer or the metadata address must be set when using introspection."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1129)); } if (string.IsNullOrEmpty(options.ClientId)) { - throw new InvalidOperationException("The client identifier cannot be null or empty when using introspection."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1130)); } if (string.IsNullOrEmpty(options.ClientSecret)) { - throw new InvalidOperationException("The client secret cannot be null or empty when using introspection."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1131)); } if (options.EnableAuthorizationEntryValidation) { - throw new InvalidOperationException("Authorization validation cannot be enabled when using introspection."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1132)); } if (options.EnableTokenEntryValidation) { - throw new InvalidOperationException("Token validation cannot be enabled when using introspection."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1133)); } } @@ -102,10 +88,7 @@ namespace OpenIddict.Validation options.EncryptionCredentials.All(credentials => credentials.Key is X509SecurityKey x509SecurityKey && (x509SecurityKey.Certificate.NotBefore > DateTime.Now || x509SecurityKey.Certificate.NotAfter < DateTime.Now))) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("When using X.509 encryption credentials, at least one of the registered certificates must be valid.") - .Append("To use key rollover, register both the new certificate and the old one in the credentials collection.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1086)); } if (options.Configuration == null && options.ConfigurationManager == null) @@ -113,12 +96,7 @@ namespace OpenIddict.Validation if (!options.Handlers.Any(descriptor => descriptor.ContextType == typeof(ApplyConfigurationRequestContext)) || !options.Handlers.Any(descriptor => descriptor.ContextType == typeof(ApplyCryptographyRequestContext))) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("A discovery client must be registered when using server discovery.") - .Append("Reference the 'OpenIddict.Validation.SystemNetHttp' package and call ") - .Append("'services.AddOpenIddict().AddValidation().UseSystemNetHttp()' ") - .Append("to register the default System.Net.Http-based integration.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1134)); } if (options.MetadataAddress == null) @@ -130,12 +108,12 @@ namespace OpenIddict.Validation { if (options.Issuer == null || !options.Issuer.IsAbsoluteUri) { - throw new InvalidOperationException("The authority must be provided and must be an absolute URL."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1135)); } if (!string.IsNullOrEmpty(options.Issuer.Fragment) || !string.IsNullOrEmpty(options.Issuer.Query)) { - throw new InvalidOperationException("The authority cannot contain a fragment or a query string."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1136)); } if (!options.Issuer.OriginalString.EndsWith("/")) diff --git a/src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs b/src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs index 9caf23cc..688cd576 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs @@ -6,12 +6,12 @@ using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using static OpenIddict.Validation.OpenIddictValidationEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -115,11 +115,7 @@ namespace OpenIddict.Validation if (handler == null) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine($"The event handler of type '{descriptor.ServiceDescriptor.ServiceType}' couldn't be resolved.") - .AppendLine("This may indicate that it was not properly registered in the dependency injection container.") - .Append("To register an event handler, use 'services.AddOpenIddict().AddValidation().AddEventHandler()'.") - .ToString()); + throw new InvalidOperationException(SR.FormatID1137(descriptor.ServiceDescriptor.ServiceType)); } yield return handler; @@ -132,10 +128,7 @@ namespace OpenIddict.Validation { if (!(_provider.GetService(descriptor.FilterTypes[index]) is IOpenIddictValidationHandlerFilter filter)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine($"The event handler filter of type '{descriptor.FilterTypes[index]}' couldn't be resolved.") - .AppendLine("This may indicate that it was not properly registered in the dependency injection container.") - .ToString()); + throw new InvalidOperationException(SR.FormatID1098(descriptor.FilterTypes[index])); } if (!await filter.IsActiveAsync(context)) diff --git a/src/OpenIddict.Validation/OpenIddictValidationEvents.cs b/src/OpenIddict.Validation/OpenIddictValidationEvents.cs index 6557a007..a4982784 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationEvents.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationEvents.cs @@ -8,6 +8,7 @@ using System; using System.ComponentModel; using System.Security.Claims; using JetBrains.Annotations; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using OpenIddict.Abstractions; @@ -50,6 +51,11 @@ namespace OpenIddict.Validation set => Transaction.Issuer = value; } + /// + /// Gets the localizer used to localize the messages generated by OpenIddict. + /// + public IStringLocalizer Localizer => Transaction.Localizer; + /// /// Gets the logger responsible of logging processed operations. /// diff --git a/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs b/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs index ab7f38f6..3ebc4e26 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs @@ -8,13 +8,17 @@ using System; using System.Linq; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging.Abstractions; +using OpenIddict.Abstractions.Resources; using OpenIddict.Validation; using static OpenIddict.Validation.OpenIddictValidationHandlerFilters; using static OpenIddict.Validation.OpenIddictValidationHandlers; namespace Microsoft.Extensions.DependencyInjection { + using Microsoft.Extensions.Options; + /// /// Exposes extensions allowing to register the OpenIddict validation services. /// @@ -50,6 +54,18 @@ namespace Microsoft.Extensions.DependencyInjection builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); + builder.Services.TryAddSingleton>(provider => + { + // Note: the string localizer factory is deliberately not resolved from + // the DI container to ensure the built-in .resx files are always used + // even if the factory was replaced by a different implementation in DI. + var factory = new ResourceManagerStringLocalizerFactory( + localizationOptions: Options.Create(new LocalizationOptions()), + loggerFactory: NullLoggerFactory.Instance); + + return new StringLocalizer(factory); + }); + // Note: TryAddEnumerable() is used here to ensure the initializer is registered only once. builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< IPostConfigureOptions, OpenIddictValidationConfiguration>()); diff --git a/src/OpenIddict.Validation/OpenIddictValidationFactory.cs b/src/OpenIddict.Validation/OpenIddictValidationFactory.cs index 170b5b47..999382d2 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationFactory.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationFactory.cs @@ -6,13 +6,16 @@ using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using OpenIddict.Abstractions.Resources; namespace OpenIddict.Validation { public class OpenIddictValidationFactory : IOpenIddictValidationFactory { + private readonly IStringLocalizer _localizer; private readonly ILogger _logger; private readonly IOptionsMonitor _options; @@ -20,9 +23,11 @@ namespace OpenIddict.Validation /// Creates a new instance of the class. /// public OpenIddictValidationFactory( + [NotNull] IStringLocalizer localizer, [NotNull] ILogger logger, [NotNull] IOptionsMonitor options) { + _localizer = localizer; _logger = logger; _options = options; } @@ -31,6 +36,7 @@ namespace OpenIddict.Validation => new ValueTask(new OpenIddictValidationTransaction { Issuer = _options.CurrentValue.Issuer, + Localizer = _localizer, Logger = _logger, Options = _options.CurrentValue }); diff --git a/src/OpenIddict.Validation/OpenIddictValidationHandlerDescriptor.cs b/src/OpenIddict.Validation/OpenIddictValidationHandlerDescriptor.cs index e8d8f97b..bb44743f 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationHandlerDescriptor.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationHandlerDescriptor.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using static OpenIddict.Validation.OpenIddictValidationEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -86,7 +87,7 @@ namespace OpenIddict.Validation if (!typeof(IOpenIddictValidationHandlerFilter<>).MakeGenericType(typeof(TContext)).IsAssignableFrom(type)) { - throw new InvalidOperationException("The specified service type is not valid."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1103)); } _filterTypes.Add(type); @@ -118,7 +119,7 @@ namespace OpenIddict.Validation var type = descriptor.ServiceType; if (!typeof(IOpenIddictValidationHandler<>).MakeGenericType(typeof(TContext)).IsAssignableFrom(type)) { - throw new InvalidOperationException("The specified service type is not valid."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1103)); } _descriptor = descriptor; @@ -216,7 +217,7 @@ namespace OpenIddict.Validation ContextType = typeof(TContext), FilterTypes = _filterTypes.ToImmutableArray(), Order = _order, - ServiceDescriptor = _descriptor ?? throw new InvalidOperationException("No service descriptor was set."), + ServiceDescriptor = _descriptor ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID1104)), Type = _type }; } diff --git a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Discovery.cs b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Discovery.cs index 340ec509..46a7eec7 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Discovery.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Discovery.cs @@ -11,6 +11,7 @@ using JetBrains.Annotations; using Microsoft.IdentityModel.Tokens; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Validation.OpenIddictValidationEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -69,7 +70,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "No issuer could be found in the discovery document."); + description: context.Localizer[SR.ID3096]); return default; } @@ -78,7 +79,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "A discovery response containing an invalid issuer was returned."); + description: context.Localizer[SR.ID3097]); return default; } @@ -87,7 +88,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "The issuer returned by the discovery endpoint is not valid."); + description: context.Localizer[SR.ID3098]); return default; } @@ -134,7 +135,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "No JWKS endpoint could be found in the discovery document."); + description: context.Localizer[SR.ID3099]); return default; } @@ -143,7 +144,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "A discovery response containing an invalid JWKS endpoint URL was returned."); + description: context.Localizer[SR.ID3100]); return default; } @@ -188,7 +189,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "A discovery response containing an invalid introspection endpoint URL was returned."); + description: context.Localizer[SR.ID3101]); return default; } @@ -248,7 +249,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "The JWKS document didn't contain a valid 'jwks' node with at least one key."); + description: context.Localizer[SR.ID3102, JsonWebKeySetParameterNames.Keys]); return default; } @@ -294,7 +295,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "A JWKS response containing an unsupported key was returned."); + description: context.Localizer[SR.ID3103]); return default; } @@ -312,7 +313,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "A JWKS response containing an invalid key was returned."); + description: context.Localizer[SR.ID3104]); return default; } diff --git a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs index 24df8100..34db3e89 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs @@ -15,6 +15,7 @@ using Microsoft.IdentityModel.JsonWebTokens; using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Validation.OpenIddictValidationEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -149,7 +150,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "The mandatory 'active' parameter couldn't be found in the introspection response."); + description: context.Localizer[SR.ID3105, Parameters.Active]); return default; } @@ -160,7 +161,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.InvalidToken, - description: "The token was rejected by the remote authorization server."); + description: context.Localizer[SR.ID3106]); return default; } @@ -207,7 +208,7 @@ namespace OpenIddict.Validation context.Reject( error: Errors.ServerError, - description: $"The {parameter.Key} claim is malformed or isn't of the expected type."); + description: context.Localizer[SR.ID3107, parameter.Key]); return default; } @@ -328,7 +329,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "An introspection response containing an invalid issuer was returned."); + description: context.Localizer[SR.ID3108]); return default; } @@ -337,7 +338,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "The issuer returned in the introspection response is not valid."); + description: context.Localizer[SR.ID3109]); return default; } @@ -387,7 +388,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.InvalidToken, - description: "The type of the introspection token doesn't match the expected type."); + description: context.Localizer[SR.ID3110]); return default; } diff --git a/src/OpenIddict.Validation/OpenIddictValidationHandlers.cs b/src/OpenIddict.Validation/OpenIddictValidationHandlers.cs index 8f598a87..4fec24d0 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationHandlers.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationHandlers.cs @@ -10,7 +10,6 @@ using System.ComponentModel; using System.Globalization; using System.Linq; using System.Security.Claims; -using System.Text; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Logging; @@ -20,6 +19,7 @@ using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationHandlerFilters; using Properties = OpenIddict.Validation.OpenIddictValidationConstants.Properties; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -91,7 +91,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.MissingToken, - description: "The security token is missing."); + description: context.Localizer[SR.ID3000]); return default; } @@ -108,11 +108,7 @@ namespace OpenIddict.Validation { private readonly IOpenIddictTokenManager _tokenManager; - public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling token entry validation.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .ToString()); + public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1138)); public ValidateReferenceTokenIdentifier([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -155,7 +151,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.InvalidToken, - description: "The specified token is not valid."); + description: context.Localizer[SR.ID3027]); return; } @@ -163,10 +159,7 @@ namespace OpenIddict.Validation var payload = await _tokenManager.GetPayloadAsync(token); if (string.IsNullOrEmpty(payload)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The payload associated with a reference token cannot be retrieved.") - .Append("This may indicate that the token entry was corrupted.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1025)); } // Replace the token parameter by the payload resolved from the token entry. @@ -221,7 +214,7 @@ namespace OpenIddict.Validation } var configuration = await context.Options.ConfigurationManager.GetConfigurationAsync(default) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the server configuration."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1139)); // Clone the token validation parameters and set the issuer using the value found in the // OpenID Connect server configuration (that can be static or retrieved using discovery). @@ -247,7 +240,7 @@ namespace OpenIddict.Validation JsonWebTokenTypes.Prefixes.Application + JsonWebTokenTypes.AccessToken }, - _ => throw new InvalidOperationException("The token type is not supported.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1002)) }; var result = context.Options.JsonWebTokenHandler.ValidateToken(context.Token, parameters); @@ -266,16 +259,12 @@ namespace OpenIddict.Validation error: Errors.InvalidToken, description: result.Exception switch { - SecurityTokenInvalidIssuerException _ - => "The issuer associated to the specified token is not valid.", - SecurityTokenInvalidTypeException _ - => "The specified token is not of the expected type.", - SecurityTokenSignatureKeyNotFoundException _ - => "The signing key associated to the specified token was not found.", - SecurityTokenInvalidSignatureException _ - => "The signature associated to the specified token is not valid.", - - _ => "The specified token is not valid." + SecurityTokenInvalidIssuerException _ => context.Localizer[SR.ID3088], + SecurityTokenInvalidTypeException _ => context.Localizer[SR.ID3089], + SecurityTokenSignatureKeyNotFoundException _ => context.Localizer[SR.ID3090], + SecurityTokenInvalidSignatureException _ => context.Localizer[SR.ID3091], + + _ => context.Localizer[SR.ID3027] }); return; @@ -287,12 +276,12 @@ namespace OpenIddict.Validation // Store the token type (resolved from "typ" or "token_usage") as a special private claim. context.Principal.SetTokenType(result.TokenType switch { - var type when string.IsNullOrEmpty(type) => throw new InvalidOperationException("The token type cannot be resolved"), + var type when string.IsNullOrEmpty(type) => throw new InvalidOperationException(SR.GetResourceString(SR.ID1024)), JsonWebTokenTypes.AccessToken => TokenTypeHints.AccessToken, JsonWebTokenTypes.Prefixes.Application + JsonWebTokenTypes.AccessToken => TokenTypeHints.AccessToken, - _ => throw new InvalidOperationException("The token type is not supported.") + _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID1002)) }); context.Logger.LogTrace("The self-contained JWT token '{Token}' was successfully validated and the following " + @@ -342,7 +331,7 @@ namespace OpenIddict.Validation } var configuration = await context.Options.ConfigurationManager.GetConfigurationAsync(default) ?? - throw new InvalidOperationException("An unknown error occurred while retrieving the server configuration."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1139)); if (string.IsNullOrEmpty(configuration.IntrospectionEndpoint) || !Uri.TryCreate(configuration.IntrospectionEndpoint, UriKind.Absolute, out Uri address) || @@ -350,7 +339,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.ServerError, - description: "This resource server is currently unavailable. Try again later."); + description: context.Localizer[SR.ID3092]); return; } @@ -358,7 +347,7 @@ namespace OpenIddict.Validation try { var principal = await _service.IntrospectTokenAsync(address, context.Token, context.TokenType) ?? - throw new InvalidOperationException("An unknown error occurred while introspecting the access token."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1140)); // Note: tokens that are considered valid at this point are assumed to be of the given type, // as the introspection handlers ensure the introspected token type matches the expected @@ -376,7 +365,7 @@ namespace OpenIddict.Validation context.Reject( error: Errors.InvalidToken, - description: "The specified token is not valid."); + description: context.Localizer[SR.ID3027]); return; } @@ -551,11 +540,7 @@ namespace OpenIddict.Validation { private readonly IOpenIddictTokenManager _tokenManager; - public RestoreReferenceTokenProperties() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling token entry validation.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .ToString()); + public RestoreReferenceTokenProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1138)); public RestoreReferenceTokenProperties([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -592,7 +577,7 @@ namespace OpenIddict.Validation var token = await _tokenManager.FindByIdAsync((string) identifier); if (token == null) { - throw new InvalidOperationException("The token entry cannot be found in the database."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1020)); } // Restore the creation/expiration dates/identifiers from the token entry metadata. @@ -638,7 +623,7 @@ namespace OpenIddict.Validation { context.Reject( error: Errors.InvalidToken, - description: "The specified token is not valid."); + description: context.Localizer[SR.ID3027]); return default; } @@ -652,19 +637,12 @@ namespace OpenIddict.Validation var type = context.Principal.GetTokenType(); if (string.IsNullOrEmpty(type)) { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The deserialized principal doesn't contain the mandatory 'oi_tkn_typ' claim.") - .Append("When implementing custom token deserialization, a 'oi_tkn_typ' claim containing ") - .Append("the type of the token being processed must be added to the security principal.") - .ToString()); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1003)); } if (!string.Equals(type, context.TokenType, StringComparison.OrdinalIgnoreCase)) { - throw new InvalidOperationException(new StringBuilder() - .AppendFormat("The type of token associated with the deserialized principal ({0}) ", type) - .AppendFormat("doesn't match the expected token type ({0}).", context.TokenType) - .ToString()); + throw new InvalidOperationException(SR.FormatID1004(type, context.TokenType)); } } @@ -708,7 +686,7 @@ namespace OpenIddict.Validation context.Reject( error: Errors.InvalidToken, - description: "The specified access token is no longer valid."); + description: context.Localizer[SR.ID3019]); return default; } @@ -762,7 +740,7 @@ namespace OpenIddict.Validation context.Reject( error: Errors.InvalidToken, - description: "The specified access token doesn't contain any audience."); + description: context.Localizer[SR.ID3093]); return default; } @@ -774,7 +752,7 @@ namespace OpenIddict.Validation context.Reject( error: Errors.InvalidToken, - description: "The specified access token cannot be used with this resource server."); + description: context.Localizer[SR.ID3094]); return default; } @@ -792,11 +770,7 @@ namespace OpenIddict.Validation { private readonly IOpenIddictTokenManager _tokenManager; - public ValidateTokenEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling token entry validation.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .ToString()); + public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1138)); public ValidateTokenEntry([NotNull] IOpenIddictTokenManager tokenManager) => _tokenManager = tokenManager; @@ -833,7 +807,7 @@ namespace OpenIddict.Validation context.Reject( error: Errors.InvalidToken, - description: "The token is no longer valid."); + description: context.Localizer[SR.ID3019]); return; } @@ -856,11 +830,7 @@ namespace OpenIddict.Validation { private readonly IOpenIddictAuthorizationManager _authorizationManager; - public ValidateAuthorizationEntry() => throw new InvalidOperationException(new StringBuilder() - .AppendLine("The core services must be registered when enabling authorization entry validation.") - .Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ") - .AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.") - .ToString()); + public ValidateAuthorizationEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1141)); public ValidateAuthorizationEntry([NotNull] IOpenIddictAuthorizationManager authorizationManager) => _authorizationManager = authorizationManager; @@ -897,7 +867,7 @@ namespace OpenIddict.Validation context.Reject( error: Errors.InvalidToken, - description: "The authorization associated with the token is no longer valid."); + description: context.Localizer[SR.ID3023]); return; } @@ -961,7 +931,7 @@ namespace OpenIddict.Validation else { context.Response.Error = Errors.InsufficientAccess; - context.Response.ErrorDescription = "The user represented by the token is not allowed to perform the requested action."; + context.Response.ErrorDescription = context.Localizer[SR.ID3095]; } return default; diff --git a/src/OpenIddict.Validation/OpenIddictValidationHelpers.cs b/src/OpenIddict.Validation/OpenIddictValidationHelpers.cs index 98fe2c43..8ac2c95e 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationHelpers.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationHelpers.cs @@ -6,6 +6,7 @@ using System; using JetBrains.Annotations; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -31,7 +32,7 @@ namespace OpenIddict.Validation if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The property name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1105), nameof(name)); } if (transaction.Properties.TryGetValue(name, out var property) && property is TProperty result) @@ -61,7 +62,7 @@ namespace OpenIddict.Validation if (string.IsNullOrEmpty(name)) { - throw new ArgumentException("The property name cannot be null or empty.", nameof(name)); + throw new ArgumentException(SR.GetResourceString(SR.ID1105), nameof(name)); } if (value == null) diff --git a/src/OpenIddict.Validation/OpenIddictValidationOptions.cs b/src/OpenIddict.Validation/OpenIddictValidationOptions.cs index ea330b26..5e5a817e 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationOptions.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationOptions.cs @@ -12,6 +12,7 @@ using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -134,7 +135,7 @@ namespace OpenIddict.Validation TokenTypeHints.AccessToken => JsonWebTokenTypes.AccessToken, TokenTypeHints.IdToken => JsonWebTokenTypes.IdentityToken, - _ => throw new NotSupportedException("The token usage of the JWT token is not supported.") + _ => throw new NotSupportedException(SR.GetResourceString(SR.ID1268)) }; } @@ -142,14 +143,14 @@ namespace OpenIddict.Validation // (provided via the type delegate parameter) or inferred from the token_usage claim. if (string.IsNullOrEmpty(type)) { - throw new SecurityTokenInvalidTypeException("The type of the JWT token cannot be resolved or inferred."); + throw new SecurityTokenInvalidTypeException(SR.GetResourceString(SR.ID1269)); } // Note: unlike IdentityModel, this custom validator deliberately uses case-insensitive comparisons. if (parameters.ValidTypes != null && parameters.ValidTypes.Any() && !parameters.ValidTypes.Contains(type, StringComparer.OrdinalIgnoreCase)) { - throw new SecurityTokenInvalidTypeException("The type of the JWT token doesn't match the expected type.") + throw new SecurityTokenInvalidTypeException(SR.GetResourceString(SR.ID1270)) { InvalidType = type }; diff --git a/src/OpenIddict.Validation/OpenIddictValidationRetriever.cs b/src/OpenIddict.Validation/OpenIddictValidationRetriever.cs index 218eb439..2d2e7d45 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationRetriever.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationRetriever.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -35,26 +36,26 @@ namespace OpenIddict.Validation { if (string.IsNullOrEmpty(address)) { - throw new ArgumentException("The address cannot be null or empty.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); } if (!Uri.TryCreate(address, UriKind.Absolute, out Uri uri) || !uri.IsWellFormedOriginalString()) { - throw new ArgumentException("The address must be a valid absolute URI.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1143), nameof(address)); } cancel.ThrowIfCancellationRequested(); var configuration = await _service.GetConfigurationAsync(uri, cancel) ?? - throw new InvalidOperationException("The server configuration couldn't be retrieved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1144)); if (!Uri.TryCreate(configuration.JwksUri, UriKind.Absolute, out uri) || !uri.IsWellFormedOriginalString()) { - throw new InvalidOperationException("The JWKS URI couldn't be resolved from the provider metadata."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1145)); } configuration.JsonWebKeySet = await _service.GetSecurityKeysAsync(uri, cancel) ?? - throw new InvalidOperationException("The server JSON Web Key set couldn't be retrieved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1146)); // Copy the signing keys found in the JSON Web Key Set to the SigningKeys collection. foreach (var key in configuration.JsonWebKeySet.GetSigningKeys()) diff --git a/src/OpenIddict.Validation/OpenIddictValidationService.cs b/src/OpenIddict.Validation/OpenIddictValidationService.cs index b75cff1b..504219e7 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationService.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationService.cs @@ -6,7 +6,6 @@ using System; using System.Security.Claims; -using System.Text; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; @@ -16,6 +15,7 @@ using Microsoft.IdentityModel.Tokens; using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Validation.OpenIddictValidationEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Validation { @@ -46,7 +46,7 @@ namespace OpenIddict.Validation if (!address.IsAbsoluteUri) { - throw new ArgumentException("The address must be an absolute URI.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1143), nameof(address)); } cancellationToken.ThrowIfCancellationRequested(); @@ -72,7 +72,7 @@ namespace OpenIddict.Validation var configuration = await HandleConfigurationResponseAsync(); if (configuration == null) { - throw new InvalidOperationException("The OpenID Connect server configuration couldn't be retrieved."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1144)); } return configuration; @@ -89,16 +89,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while preparing the configuration request.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1147(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -116,16 +108,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while sending the configuration request.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1148(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -143,16 +127,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while extracting the configuration response.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1149(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -171,16 +147,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while handling the configuration response.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1150(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -218,7 +186,7 @@ namespace OpenIddict.Validation if (!address.IsAbsoluteUri) { - throw new ArgumentException("The address must be an absolute URI.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1143), nameof(address)); } cancellationToken.ThrowIfCancellationRequested(); @@ -245,7 +213,7 @@ namespace OpenIddict.Validation var keys = await HandleCryptographyResponseAsync(); if (keys == null) { - throw new InvalidOperationException("An unknown error occurred while retrieving the JWK set."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1146)); } return keys; @@ -262,16 +230,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while preparing the cryptography request.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1151(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -289,16 +249,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while sending the cryptography request.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1152(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -316,16 +268,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while extracting the cryptography response.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1153(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -344,16 +288,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while handling the cryptography response.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1154(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -405,12 +341,12 @@ namespace OpenIddict.Validation if (!address.IsAbsoluteUri) { - throw new ArgumentException("The address must be an absolute URI.", nameof(address)); + throw new ArgumentException(SR.GetResourceString(SR.ID1143), nameof(address)); } if (string.IsNullOrEmpty(token)) { - throw new ArgumentException("The token cannot be null or empty.", nameof(token)); + throw new ArgumentException(SR.GetResourceString(SR.ID1155), nameof(token)); } cancellationToken.ThrowIfCancellationRequested(); @@ -436,7 +372,7 @@ namespace OpenIddict.Validation var principal = await HandleIntrospectionResponseAsync(); if (principal == null) { - throw new InvalidOperationException("An unknown error occurred while introspecting the token."); + throw new InvalidOperationException(SR.GetResourceString(SR.ID1156)); } return principal; @@ -455,16 +391,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while preparing the introspection request.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1157(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -482,16 +410,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while sending the introspection request.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1158(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -509,16 +429,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while extracting the introspection response.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1159(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -539,16 +451,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while handling the introspection response.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1160(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } @@ -581,7 +485,7 @@ namespace OpenIddict.Validation { if (string.IsNullOrEmpty(token)) { - throw new ArgumentException("The access token cannot be null or empty.", nameof(token)); + throw new ArgumentException(SR.GetResourceString(SR.ID1161), nameof(token)); } cancellationToken.ThrowIfCancellationRequested(); @@ -609,16 +513,8 @@ namespace OpenIddict.Validation if (context.IsRejected) { - var message = new StringBuilder() - .AppendLine("An error occurred while validating the access token.") - .AppendFormat("Error: {0}", context.Error ?? "(not available)") - .AppendLine() - .AppendFormat("Error description: {0}", context.ErrorDescription ?? "(not available)") - .AppendLine() - .AppendFormat("Error URI: {0}", context.ErrorUri ?? "(not available)") - .ToString(); - - throw new OpenIddictExceptions.GenericException(message, + throw new OpenIddictExceptions.GenericException( + SR.FormatID1162(context.Error, context.ErrorDescription, context.ErrorUri), context.Error, context.ErrorDescription, context.ErrorUri); } diff --git a/src/OpenIddict.Validation/OpenIddictValidationTransaction.cs b/src/OpenIddict.Validation/OpenIddictValidationTransaction.cs index 444242f5..9a289b62 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationTransaction.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationTransaction.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using OpenIddict.Abstractions; @@ -26,6 +27,11 @@ namespace OpenIddict.Validation /// public Uri Issuer { get; set; } + /// + /// Gets or sets the localizer associated with the current request. + /// + public IStringLocalizer Localizer { get; set; } + /// /// Gets or sets the logger associated with the current request. /// diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs index e9c404d7..598fc551 100644 --- a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs @@ -9,6 +9,7 @@ using System.IO; using System.Text; using System.Text.Json; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Abstractions.Tests.Primitives { @@ -86,7 +87,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives return converter.Read(ref reader, type, options: null); }); - Assert.StartsWith("The specified type is not supported.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1175), exception.Message); Assert.Equal("typeToConvert", exception.ParamName); } diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs index 63d2fda2..5fb0cc3a 100644 --- a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs @@ -12,6 +12,7 @@ using System.Linq; using System.Security.Claims; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Abstractions.Tests.Primitives { @@ -183,7 +184,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => request.HasAcrValue(value)); Assert.Equal("value", exception.ParamName); - Assert.StartsWith("The value cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1176), exception.Message); } [Theory] @@ -247,7 +248,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => request.HasPrompt(prompt)); Assert.Equal("prompt", exception.ParamName); - Assert.StartsWith("The prompt cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1177), exception.Message); } [Theory] @@ -311,7 +312,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => request.HasResponseType(type)); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The response type cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1178), exception.Message); } [Theory] @@ -375,7 +376,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => request.HasScope(scope)); Assert.Equal("scope", exception.ParamName); - Assert.StartsWith("The scope cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1179), exception.Message); } [Theory] @@ -985,7 +986,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => claim.HasDestination(null)); Assert.Equal("destination", exception.ParamName); - Assert.StartsWith("The destination cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1180), exception.Message); } [Fact] @@ -1055,7 +1056,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => claim.SetDestinations(destination)); Assert.Equal("destinations", exception.ParamName); - Assert.StartsWith("Destinations cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1181), exception.Message); } [Theory] @@ -1184,7 +1185,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var claim = new Claim(Claims.Name, "Bob le Bricoleur"); // Act - claim.SetDestinations((IEnumerable)destinations); + claim.SetDestinations((IEnumerable) destinations); // Assert Assert.Equal(destination, claim.Properties[Properties.Destinations]); @@ -1978,7 +1979,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => principal.HasAudience(audience)); Assert.Equal("audience", exception.ParamName); - Assert.StartsWith("The audience cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1185), exception.Message); } [Theory] @@ -2042,7 +2043,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => principal.HasPresenter(presenter)); Assert.Equal("presenter", exception.ParamName); - Assert.StartsWith("The presenter cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1186), exception.Message); } [Theory] @@ -2106,7 +2107,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => principal.HasResource(resource)); Assert.Equal("resource", exception.ParamName); - Assert.StartsWith("The resource cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1061), exception.Message); } [Theory] @@ -2170,7 +2171,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => principal.HasScope(scope)); Assert.Equal("scope", exception.ParamName); - Assert.StartsWith("The scope cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1179), exception.Message); } [Theory] @@ -2235,7 +2236,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => principal.HasTokenType(type)); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The token type cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1187), exception.Message); } [Fact] @@ -2264,7 +2265,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => identity.AddClaim(type, "value")); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The claim type cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1183), exception.Message); } [Fact] @@ -2304,7 +2305,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => principal.GetClaims(type)); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The claim type cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1183), exception.Message); } [Fact] @@ -2346,7 +2347,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => principal.HasClaim(type)); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The claim type cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1183), exception.Message); } [Fact] @@ -2390,7 +2391,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => principal.RemoveClaims(type)); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The claim type cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1183), exception.Message); } [Fact] @@ -2433,7 +2434,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => principal.SetClaim(type, "value")); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The claim type cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1183), exception.Message); } [Fact] @@ -2672,7 +2673,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var principal = new ClaimsPrincipal(identity); // Act - principal.SetScopes((IEnumerable)scopes); + principal.SetScopes((IEnumerable) scopes); // Assert Assert.Equal(scope, principal.GetClaims(Claims.Private.Scope)); @@ -2953,7 +2954,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives private TimeSpan? ParseLifeTime(string lifetime) { var lifeT = lifetime != null - ? (TimeSpan?)TimeSpan.FromSeconds(double.Parse(lifetime, NumberStyles.Number, CultureInfo.InvariantCulture)) + ? (TimeSpan?) TimeSpan.FromSeconds(double.Parse(lifetime, NumberStyles.Number, CultureInfo.InvariantCulture)) : null; return lifeT; diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs index 6c190ebc..57e0b376 100644 --- a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs @@ -11,6 +11,7 @@ using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Abstractions.Tests.Primitives { @@ -31,7 +32,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives }); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1189), exception.Message); } [Fact] @@ -44,7 +45,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives }); Assert.Equal("parameters", exception.ParamName); - Assert.StartsWith("The specified JSON element is not an object.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1188), exception.Message); } [Fact] @@ -61,7 +62,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives }); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("A parameter with the same name already exists.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1190), exception.Message); } [Fact] @@ -149,7 +150,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives }); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1189), exception.Message); } [Fact] @@ -210,7 +211,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => message.GetParameter(name)); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1189), exception.Message); } [Fact] @@ -276,7 +277,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => message.HasParameter(name)); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1189), exception.Message); } [Theory] @@ -306,7 +307,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => message.RemoveParameter(name)); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1189), exception.Message); } [Fact] @@ -335,7 +336,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives var exception = Assert.Throws(() => message.SetParameter(name, null)); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1189), exception.Message); } [Fact] @@ -407,7 +408,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives // Assert Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1189), exception.Message); } [Fact] diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs index a35e041b..7874aa60 100644 --- a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Text; using System.Text.Json; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Abstractions.Tests.Primitives { @@ -266,7 +267,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives // Assert Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The item name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1191), exception.Message); } [Fact] @@ -336,7 +337,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives // Assert Assert.Equal("index", exception.ParamName); - Assert.StartsWith("The item index cannot be negative.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1192), exception.Message); } [Fact] @@ -698,7 +699,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives // Assert Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1189), exception.Message); } [Fact] diff --git a/test/OpenIddict.Core.Tests/OpenIddictCoreBuilderTests.cs b/test/OpenIddict.Core.Tests/OpenIddictCoreBuilderTests.cs index 573528ad..6151e9e3 100644 --- a/test/OpenIddict.Core.Tests/OpenIddictCoreBuilderTests.cs +++ b/test/OpenIddict.Core.Tests/OpenIddictCoreBuilderTests.cs @@ -6,11 +6,14 @@ using System; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using OpenIddict.Abstractions; +using OpenIddict.Abstractions.Resources; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core.Tests { @@ -39,7 +42,7 @@ namespace OpenIddict.Core.Tests var exception = Assert.Throws(() => builder.ReplaceApplicationManager(typeof(object))); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -97,7 +100,7 @@ namespace OpenIddict.Core.Tests var exception = Assert.Throws(() => builder.ReplaceApplicationStoreResolver(typeof(object))); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -130,7 +133,7 @@ namespace OpenIddict.Core.Tests var exception = Assert.Throws(() => builder.ReplaceAuthorizationManager(typeof(object))); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -187,7 +190,7 @@ namespace OpenIddict.Core.Tests var exception = Assert.Throws(() => builder.ReplaceAuthorizationStoreResolver(typeof(object))); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -220,7 +223,7 @@ namespace OpenIddict.Core.Tests var exception = Assert.Throws(() => builder.ReplaceScopeManager(typeof(object))); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -278,7 +281,7 @@ namespace OpenIddict.Core.Tests var exception = Assert.Throws(() => builder.ReplaceScopeStoreResolver(typeof(object))); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -311,7 +314,7 @@ namespace OpenIddict.Core.Tests var exception = Assert.Throws(() => builder.ReplaceTokenManager(typeof(object))); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -369,7 +372,7 @@ namespace OpenIddict.Core.Tests var exception = Assert.Throws(() => builder.ReplaceTokenStoreResolver(typeof(object))); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -455,7 +458,7 @@ namespace OpenIddict.Core.Tests }); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -505,7 +508,7 @@ namespace OpenIddict.Core.Tests }); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -555,7 +558,7 @@ namespace OpenIddict.Core.Tests }); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -605,7 +608,7 @@ namespace OpenIddict.Core.Tests }); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] @@ -679,10 +682,11 @@ namespace OpenIddict.Core.Tests { public ClosedGenericApplicationManager( IOpenIddictApplicationCache cache, - IOpenIddictApplicationStoreResolver resolver, + IStringLocalizer localizer, ILogger> logger, - IOptionsMonitor options) - : base(cache, resolver, logger, options) + IOptionsMonitor options, + IOpenIddictApplicationStoreResolver resolver) + : base(cache, localizer, logger, options, resolver) { } } @@ -692,10 +696,11 @@ namespace OpenIddict.Core.Tests { public OpenGenericApplicationManager( IOpenIddictApplicationCache cache, - IOpenIddictApplicationStoreResolver resolver, + IStringLocalizer localizer, ILogger> logger, - IOptionsMonitor options) - : base(cache, resolver, logger, options) + IOptionsMonitor options, + IOpenIddictApplicationStoreResolver resolver) + : base(cache, localizer, logger, options, resolver) { } } @@ -704,10 +709,11 @@ namespace OpenIddict.Core.Tests { public ClosedGenericAuthorizationManager( IOpenIddictAuthorizationCache cache, - IOpenIddictAuthorizationStoreResolver resolver, + IStringLocalizer localizer, ILogger> logger, - IOptionsMonitor options) - : base(cache, resolver, logger, options) + IOptionsMonitor options, + IOpenIddictAuthorizationStoreResolver resolver) + : base(cache, localizer, logger, options, resolver) { } } @@ -717,10 +723,11 @@ namespace OpenIddict.Core.Tests { public OpenGenericAuthorizationManager( IOpenIddictAuthorizationCache cache, - IOpenIddictAuthorizationStoreResolver resolver, + IStringLocalizer localizer, ILogger> logger, - IOptionsMonitor options) - : base(cache, resolver, logger, options) + IOptionsMonitor options, + IOpenIddictAuthorizationStoreResolver resolver) + : base(cache, localizer, logger, options, resolver) { } } @@ -729,10 +736,11 @@ namespace OpenIddict.Core.Tests { public ClosedGenericScopeManager( IOpenIddictScopeCache cache, - IOpenIddictScopeStoreResolver resolver, + IStringLocalizer localizer, ILogger> logger, - IOptionsMonitor options) - : base(cache, resolver, logger, options) + IOptionsMonitor options, + IOpenIddictScopeStoreResolver resolver) + : base(cache, localizer, logger, options, resolver) { } } @@ -742,10 +750,11 @@ namespace OpenIddict.Core.Tests { public OpenGenericScopeManager( IOpenIddictScopeCache cache, - IOpenIddictScopeStoreResolver resolver, + IStringLocalizer localizer, ILogger> logger, - IOptionsMonitor options) - : base(cache, resolver, logger, options) + IOptionsMonitor options, + IOpenIddictScopeStoreResolver resolver) + : base(cache, localizer, logger, options, resolver) { } } @@ -754,10 +763,11 @@ namespace OpenIddict.Core.Tests { public ClosedGenericTokenManager( IOpenIddictTokenCache cache, - IOpenIddictTokenStoreResolver resolver, + IStringLocalizer localizer, ILogger> logger, - IOptionsMonitor options) - : base(cache, resolver, logger, options) + IOptionsMonitor options, + IOpenIddictTokenStoreResolver resolver) + : base(cache, localizer, logger, options, resolver) { } } @@ -767,10 +777,11 @@ namespace OpenIddict.Core.Tests { public OpenGenericTokenManager( IOpenIddictTokenCache cache, - IOpenIddictTokenStoreResolver resolver, + IStringLocalizer localizer, ILogger> logger, - IOptionsMonitor options) - : base(cache, resolver, logger, options) + IOptionsMonitor options, + IOpenIddictTokenStoreResolver resolver) + : base(cache, localizer, logger, options, resolver) { } } diff --git a/test/OpenIddict.Core.Tests/Resolvers/OpenIddictApplicationStoreResolverTests.cs b/test/OpenIddict.Core.Tests/Resolvers/OpenIddictApplicationStoreResolverTests.cs index a5182113..97c7b4f8 100644 --- a/test/OpenIddict.Core.Tests/Resolvers/OpenIddictApplicationStoreResolverTests.cs +++ b/test/OpenIddict.Core.Tests/Resolvers/OpenIddictApplicationStoreResolverTests.cs @@ -5,11 +5,11 @@ */ using System; -using System.Text; using Microsoft.Extensions.DependencyInjection; using Moq; using OpenIddict.Abstractions; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core.Tests { @@ -26,13 +26,7 @@ namespace OpenIddict.Core.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No application store has been registered in the dependency injection container.") - .Append("To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' ") - .AppendLine("package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'.") - .Append("To register a custom store, create an implementation of 'IOpenIddictApplicationStore' and ") - .Append("use 'services.AddOpenIddict().AddCore().AddApplicationStore()' to add it to the DI container.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1227), exception.Message); } [Fact] diff --git a/test/OpenIddict.Core.Tests/Resolvers/OpenIddictAuthorizationStoreResolverTests.cs b/test/OpenIddict.Core.Tests/Resolvers/OpenIddictAuthorizationStoreResolverTests.cs index 687665da..612145c3 100644 --- a/test/OpenIddict.Core.Tests/Resolvers/OpenIddictAuthorizationStoreResolverTests.cs +++ b/test/OpenIddict.Core.Tests/Resolvers/OpenIddictAuthorizationStoreResolverTests.cs @@ -5,11 +5,11 @@ */ using System; -using System.Text; using Microsoft.Extensions.DependencyInjection; using Moq; using OpenIddict.Abstractions; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core.Tests { @@ -26,13 +26,7 @@ namespace OpenIddict.Core.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No authorization store has been registered in the dependency injection container.") - .Append("To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' ") - .AppendLine("package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'.") - .Append("To register a custom store, create an implementation of 'IOpenIddictAuthorizationStore' and ") - .Append("use 'services.AddOpenIddict().AddCore().AddAuthorizationStore()' to add it to the DI container.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1228), exception.Message); } [Fact] diff --git a/test/OpenIddict.Core.Tests/Resolvers/OpenIddictScopeStoreResolverTests.cs b/test/OpenIddict.Core.Tests/Resolvers/OpenIddictScopeStoreResolverTests.cs index ab759c2b..218ee899 100644 --- a/test/OpenIddict.Core.Tests/Resolvers/OpenIddictScopeStoreResolverTests.cs +++ b/test/OpenIddict.Core.Tests/Resolvers/OpenIddictScopeStoreResolverTests.cs @@ -5,11 +5,11 @@ */ using System; -using System.Text; using Microsoft.Extensions.DependencyInjection; using Moq; using OpenIddict.Abstractions; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core.Tests { @@ -26,13 +26,7 @@ namespace OpenIddict.Core.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No scope store has been registered in the dependency injection container.") - .Append("To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' ") - .AppendLine("package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'.") - .Append("To register a custom store, create an implementation of 'IOpenIddictScopeStore' and ") - .Append("use 'services.AddOpenIddict().AddCore().AddScopeStore()' to add it to the DI container.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1229), exception.Message); } [Fact] diff --git a/test/OpenIddict.Core.Tests/Resolvers/OpenIddictTokenStoreResolverTests.cs b/test/OpenIddict.Core.Tests/Resolvers/OpenIddictTokenStoreResolverTests.cs index 77183483..2f6410c9 100644 --- a/test/OpenIddict.Core.Tests/Resolvers/OpenIddictTokenStoreResolverTests.cs +++ b/test/OpenIddict.Core.Tests/Resolvers/OpenIddictTokenStoreResolverTests.cs @@ -5,11 +5,11 @@ */ using System; -using System.Text; using Microsoft.Extensions.DependencyInjection; using Moq; using OpenIddict.Abstractions; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Core.Tests { @@ -26,13 +26,7 @@ namespace OpenIddict.Core.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No token store has been registered in the dependency injection container.") - .Append("To register the Entity Framework Core stores, reference the 'OpenIddict.EntityFrameworkCore' ") - .AppendLine("package and call 'services.AddOpenIddict().AddCore().UseEntityFrameworkCore()'.") - .Append("To register a custom store, create an implementation of 'IOpenIddictTokenStore' and ") - .Append("use 'services.AddOpenIddict().AddCore().AddTokenStore()' to add it to the DI container.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1230), exception.Message); } [Fact] diff --git a/test/OpenIddict.EntityFramework.Tests/OpenIddictEntityFrameworkBuilderTests.cs b/test/OpenIddict.EntityFramework.Tests/OpenIddictEntityFrameworkBuilderTests.cs index 85447019..03405c8a 100644 --- a/test/OpenIddict.EntityFramework.Tests/OpenIddictEntityFrameworkBuilderTests.cs +++ b/test/OpenIddict.EntityFramework.Tests/OpenIddictEntityFrameworkBuilderTests.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Options; using OpenIddict.Core; using OpenIddict.EntityFramework.Models; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework.Tests { @@ -78,7 +79,7 @@ namespace OpenIddict.EntityFramework.Tests }); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] diff --git a/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolverTests.cs b/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolverTests.cs index b748a960..2e567f02 100644 --- a/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolverTests.cs +++ b/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolverTests.cs @@ -6,7 +6,6 @@ using System; using System.Data.Entity; -using System.Text; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -15,6 +14,7 @@ using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; using Xunit; using static OpenIddict.EntityFramework.OpenIddictEntityFrameworkApplicationStoreResolver; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework.Tests { @@ -48,12 +48,7 @@ namespace OpenIddict.EntityFramework.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified application type is not compatible with the Entity Framework 6.x stores.") - .Append("When enabling the Entity Framework 6.x stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkApplication' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkApplication' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1233), exception.Message); } [Fact] @@ -74,11 +69,7 @@ namespace OpenIddict.EntityFramework.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No Entity Framework 6.x context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework 6.x stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFramework().UseDbContext()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1234), exception.Message); } [Fact] @@ -102,7 +93,7 @@ namespace OpenIddict.EntityFramework.Tests Assert.NotNull(resolver.Get()); } - private static OpenIddictEntityFrameworkApplicationStore CreateStore() + private static OpenIddictEntityFrameworkApplicationStore CreateStore() => new Mock>( Mock.Of(), Mock.Of(), diff --git a/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolverTests.cs b/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolverTests.cs index 0da4a977..62da0eee 100644 --- a/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolverTests.cs +++ b/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolverTests.cs @@ -6,7 +6,6 @@ using System; using System.Data.Entity; -using System.Text; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -15,6 +14,7 @@ using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; using Xunit; using static OpenIddict.EntityFramework.OpenIddictEntityFrameworkAuthorizationStoreResolver; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework.Tests { @@ -48,12 +48,7 @@ namespace OpenIddict.EntityFramework.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified authorization type is not compatible with the Entity Framework 6.x stores.") - .Append("When enabling the Entity Framework 6.x stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkAuthorization' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkAuthorization' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1235), exception.Message); } [Fact] @@ -74,11 +69,7 @@ namespace OpenIddict.EntityFramework.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No Entity Framework 6.x context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework 6.x stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFramework().UseDbContext()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1234), exception.Message); } [Fact] diff --git a/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkScopeStoreResolverTests.cs b/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkScopeStoreResolverTests.cs index 5edf1293..21c6c687 100644 --- a/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkScopeStoreResolverTests.cs +++ b/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkScopeStoreResolverTests.cs @@ -6,7 +6,6 @@ using System; using System.Data.Entity; -using System.Text; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -15,6 +14,7 @@ using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; using Xunit; using static OpenIddict.EntityFramework.OpenIddictEntityFrameworkScopeStoreResolver; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework.Tests { @@ -48,12 +48,7 @@ namespace OpenIddict.EntityFramework.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified scope type is not compatible with the Entity Framework 6.x stores.") - .Append("When enabling the Entity Framework 6.x stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkScope' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkScope' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1236), exception.Message); } [Fact] @@ -74,11 +69,7 @@ namespace OpenIddict.EntityFramework.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No Entity Framework 6.x context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework 6.x stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFramework().UseDbContext()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1234), exception.Message); } [Fact] diff --git a/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkTokenStoreResolverTests.cs b/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkTokenStoreResolverTests.cs index e1b3044f..887a554c 100644 --- a/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkTokenStoreResolverTests.cs +++ b/test/OpenIddict.EntityFramework.Tests/Resolvers/OpenIddictEntityFrameworkTokenStoreResolverTests.cs @@ -6,7 +6,6 @@ using System; using System.Data.Entity; -using System.Text; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -15,6 +14,7 @@ using OpenIddict.Abstractions; using OpenIddict.EntityFramework.Models; using Xunit; using static OpenIddict.EntityFramework.OpenIddictEntityFrameworkTokenStoreResolver; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFramework.Tests { @@ -48,12 +48,7 @@ namespace OpenIddict.EntityFramework.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified token type is not compatible with the Entity Framework 6.x stores.") - .Append("When enabling the Entity Framework 6.x stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkToken' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkToken' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1237), exception.Message); } [Fact] @@ -74,11 +69,7 @@ namespace OpenIddict.EntityFramework.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No Entity Framework 6.x context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework 6.x stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFramework().UseDbContext()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1234), exception.Message); } [Fact] diff --git a/test/OpenIddict.EntityFrameworkCore.Tests/OpenIddictEntityFrameworkCoreBuilderTests.cs b/test/OpenIddict.EntityFrameworkCore.Tests/OpenIddictEntityFrameworkCoreBuilderTests.cs index 5bf55021..d235a870 100644 --- a/test/OpenIddict.EntityFrameworkCore.Tests/OpenIddictEntityFrameworkCoreBuilderTests.cs +++ b/test/OpenIddict.EntityFrameworkCore.Tests/OpenIddictEntityFrameworkCoreBuilderTests.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Options; using OpenIddict.Core; using OpenIddict.EntityFrameworkCore.Models; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore.Tests { @@ -98,7 +99,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests }); Assert.Equal("type", exception.ParamName); - Assert.StartsWith("The specified type is invalid.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message); } [Fact] diff --git a/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolverTests.cs b/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolverTests.cs index 6015c205..c15aff74 100644 --- a/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolverTests.cs +++ b/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolverTests.cs @@ -5,7 +5,6 @@ */ using System; -using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; @@ -15,6 +14,7 @@ using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; using Xunit; using static OpenIddict.EntityFrameworkCore.OpenIddictEntityFrameworkCoreApplicationStoreResolver; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore.Tests { @@ -48,12 +48,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified application type is not compatible with the Entity Framework Core stores.") - .Append("When enabling the Entity Framework Core stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkCoreApplication' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkCoreApplication' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1251), exception.Message); } [Fact] @@ -74,11 +69,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No Entity Framework Core context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework Core stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFrameworkCore().UseDbContext()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1252), exception.Message); } [Fact] @@ -102,7 +93,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests Assert.NotNull(resolver.Get()); } - private static OpenIddictEntityFrameworkCoreApplicationStore CreateStore() + private static OpenIddictEntityFrameworkCoreApplicationStore CreateStore() => new Mock>( Mock.Of(), Mock.Of(), diff --git a/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolverTests.cs b/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolverTests.cs index ceaa108e..9d105fed 100644 --- a/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolverTests.cs +++ b/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolverTests.cs @@ -5,7 +5,6 @@ */ using System; -using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; @@ -15,6 +14,7 @@ using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; using Xunit; using static OpenIddict.EntityFrameworkCore.OpenIddictEntityFrameworkCoreAuthorizationStoreResolver; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore.Tests { @@ -48,12 +48,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified authorization type is not compatible with the Entity Framework Core stores.") - .Append("When enabling the Entity Framework Core stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkCoreAuthorization' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkCoreAuthorization' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1253), exception.Message); } [Fact] @@ -74,11 +69,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No Entity Framework Core context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework Core stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFrameworkCore().UseDbContext()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1252), exception.Message); } [Fact] diff --git a/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolverTests.cs b/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolverTests.cs index f4c0c8a7..d9e9f840 100644 --- a/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolverTests.cs +++ b/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolverTests.cs @@ -5,7 +5,6 @@ */ using System; -using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; @@ -15,6 +14,7 @@ using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; using Xunit; using static OpenIddict.EntityFrameworkCore.OpenIddictEntityFrameworkCoreScopeStoreResolver; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore.Tests { @@ -48,12 +48,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified scope type is not compatible with the Entity Framework Core stores.") - .Append("When enabling the Entity Framework Core stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkCoreScope' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkCoreScope' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1254), exception.Message); } [Fact] @@ -74,11 +69,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No Entity Framework Core context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework Core stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFrameworkCore().UseDbContext()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1252), exception.Message); } [Fact] diff --git a/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolverTests.cs b/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolverTests.cs index 809b795f..0e4b6bf1 100644 --- a/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolverTests.cs +++ b/test/OpenIddict.EntityFrameworkCore.Tests/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolverTests.cs @@ -5,7 +5,6 @@ */ using System; -using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; @@ -15,6 +14,7 @@ using OpenIddict.Abstractions; using OpenIddict.EntityFrameworkCore.Models; using Xunit; using static OpenIddict.EntityFrameworkCore.OpenIddictEntityFrameworkCoreTokenStoreResolver; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.EntityFrameworkCore.Tests { @@ -48,12 +48,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified token type is not compatible with the Entity Framework Core stores.") - .Append("When enabling the Entity Framework Core stores, make sure you use the built-in ") - .Append("'OpenIddictEntityFrameworkCoreToken' entity or a custom entity that inherits ") - .Append("from the generic 'OpenIddictEntityFrameworkCoreToken' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1255), exception.Message); } [Fact] @@ -74,11 +69,7 @@ namespace OpenIddict.EntityFrameworkCore.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("No Entity Framework Core context was specified in the OpenIddict options.") - .Append("To configure the OpenIddict Entity Framework Core stores to use a specific 'DbContext', ") - .Append("use 'options.UseEntityFrameworkCore().UseDbContext()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1252), exception.Message); } [Fact] diff --git a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbBuilderTests.cs b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbBuilderTests.cs index fe970838..7ab7b3fc 100644 --- a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbBuilderTests.cs +++ b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbBuilderTests.cs @@ -12,6 +12,7 @@ using Moq; using OpenIddict.Core; using OpenIddict.MongoDb.Models; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb.Tests { @@ -110,7 +111,7 @@ namespace OpenIddict.MongoDb.Tests var exception = Assert.Throws(() => builder.SetApplicationsCollectionName(name)); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The collection name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1260), exception.Message); } [Fact] @@ -143,7 +144,7 @@ namespace OpenIddict.MongoDb.Tests var exception = Assert.Throws(() => builder.SetAuthorizationsCollectionName(name)); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The collection name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1260), exception.Message); } [Fact] @@ -176,7 +177,7 @@ namespace OpenIddict.MongoDb.Tests var exception = Assert.Throws(() => builder.SetScopesCollectionName(name)); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The collection name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1260), exception.Message); } [Fact] @@ -209,7 +210,7 @@ namespace OpenIddict.MongoDb.Tests var exception = Assert.Throws(() => builder.SetTokensCollectionName(name)); Assert.Equal("name", exception.ParamName); - Assert.StartsWith("The collection name cannot be null or empty.", exception.Message); + Assert.StartsWith(SR.GetResourceString(SR.ID1260), exception.Message); } [Fact] diff --git a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs index 8e3d5d09..81bae138 100644 --- a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs +++ b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs @@ -5,7 +5,6 @@ */ using System; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; @@ -13,6 +12,7 @@ using Microsoft.Extensions.Options; using MongoDB.Driver; using Moq; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb.Tests { @@ -82,12 +82,7 @@ namespace OpenIddict.MongoDb.Tests await context.GetDatabaseAsync(CancellationToken.None); }); - Assert.Equal(new StringBuilder() - .AppendLine("No suitable MongoDB database service can be found.") - .Append("To configure the OpenIddict MongoDB stores to use a specific database, use ") - .Append("'services.AddOpenIddict().AddCore().UseMongoDb().UseDatabase()' or register an ") - .Append("'IMongoDatabase' in the dependency injection container in 'ConfigureServices()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1261), exception.Message); } [Fact] diff --git a/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbApplicationStoreResolverTests.cs b/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbApplicationStoreResolverTests.cs index 5a1d8091..2e3bcdbb 100644 --- a/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbApplicationStoreResolverTests.cs +++ b/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbApplicationStoreResolverTests.cs @@ -5,13 +5,13 @@ */ using System; -using System.Text; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Moq; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb.Tests { @@ -43,12 +43,7 @@ namespace OpenIddict.MongoDb.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified application type is not compatible with the MongoDB stores.") - .Append("When enabling the MongoDB stores, make sure you use the built-in ") - .Append("'OpenIddictMongoDbApplication' entity or a custom entity that inherits ") - .Append("from the 'OpenIddictMongoDbApplication' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1256), exception.Message); } [Fact] @@ -66,7 +61,7 @@ namespace OpenIddict.MongoDb.Tests Assert.NotNull(resolver.Get()); } - private static OpenIddictMongoDbApplicationStore CreateStore() + private static OpenIddictMongoDbApplicationStore CreateStore() => new Mock>( Mock.Of(), Mock.Of>()).Object; diff --git a/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbAuthorizationStoreResolverTests.cs b/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbAuthorizationStoreResolverTests.cs index 4d5d86e0..6b74de86 100644 --- a/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbAuthorizationStoreResolverTests.cs +++ b/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbAuthorizationStoreResolverTests.cs @@ -5,13 +5,13 @@ */ using System; -using System.Text; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Moq; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb.Tests { @@ -43,12 +43,7 @@ namespace OpenIddict.MongoDb.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified authorization type is not compatible with the MongoDB stores.") - .Append("When enabling the MongoDB stores, make sure you use the built-in ") - .Append("'OpenIddictMongoDbAuthorization' entity or a custom entity that inherits ") - .Append("from the 'OpenIddictMongoDbAuthorization' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1257), exception.Message); } [Fact] diff --git a/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbScopeStoreResolverTests.cs b/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbScopeStoreResolverTests.cs index bce4ed35..b6a5c85c 100644 --- a/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbScopeStoreResolverTests.cs +++ b/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbScopeStoreResolverTests.cs @@ -5,13 +5,13 @@ */ using System; -using System.Text; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Moq; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb.Tests { @@ -43,12 +43,7 @@ namespace OpenIddict.MongoDb.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified scope type is not compatible with the MongoDB stores.") - .Append("When enabling the MongoDB stores, make sure you use the built-in ") - .Append("'OpenIddictMongoDbScope' entity or a custom entity that inherits ") - .Append("from the 'OpenIddictMongoDbScope' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1258), exception.Message); } [Fact] diff --git a/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbTokenStoreResolverTests.cs b/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbTokenStoreResolverTests.cs index 4b3bf743..625baa8f 100644 --- a/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbTokenStoreResolverTests.cs +++ b/test/OpenIddict.MongoDb.Tests/Resolvers/OpenIddictMongoDbTokenStoreResolverTests.cs @@ -5,13 +5,13 @@ */ using System; -using System.Text; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Moq; using OpenIddict.Abstractions; using OpenIddict.MongoDb.Models; using Xunit; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.MongoDb.Tests { @@ -43,12 +43,7 @@ namespace OpenIddict.MongoDb.Tests // Act and assert var exception = Assert.Throws(() => resolver.Get()); - Assert.Equal(new StringBuilder() - .AppendLine("The specified token type is not compatible with the MongoDB stores.") - .Append("When enabling the MongoDB stores, make sure you use the built-in ") - .Append("'OpenIddictMongoDbToken' entity or a custom entity that inherits ") - .Append("from the 'OpenIddictMongoDbToken' entity.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1259), exception.Message); } [Fact] diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Authentication.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Authentication.cs index 6044eab1..fc1d7aa9 100644 --- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Authentication.cs +++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Authentication.cs @@ -10,6 +10,7 @@ using OpenIddict.Abstractions; using OpenIddict.Server.FunctionalTests; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore.FunctionalTests { @@ -30,7 +31,7 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'request_id' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3028(Parameters.RequestId), response.ErrorDescription); } [Fact] @@ -55,7 +56,7 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'request_id' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.RequestId), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Exchange.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Exchange.cs index ac39470a..9295cdd6 100644 --- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Exchange.cs +++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Exchange.cs @@ -12,6 +12,7 @@ using OpenIddict.Server.FunctionalTests; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore.FunctionalTests { @@ -53,7 +54,7 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("Multiple client credentials cannot be specified.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3087), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Introspection.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Introspection.cs index d0794cc6..3b73a759 100644 --- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Introspection.cs +++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Introspection.cs @@ -12,6 +12,7 @@ using OpenIddict.Server.FunctionalTests; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore.FunctionalTests { @@ -51,7 +52,7 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("Multiple client credentials cannot be specified.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3087), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Revocation.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Revocation.cs index a622a724..90676e61 100644 --- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Revocation.cs +++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Revocation.cs @@ -12,6 +12,7 @@ using OpenIddict.Server.FunctionalTests; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore.FunctionalTests { @@ -51,7 +52,7 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("Multiple client credentials cannot be specified.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3087), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Session.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Session.cs index 665f2768..8ee86512 100644 --- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Session.cs +++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.Session.cs @@ -10,6 +10,7 @@ using OpenIddict.Abstractions; using OpenIddict.Server.FunctionalTests; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore.FunctionalTests { @@ -30,7 +31,7 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'request_id' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3028(Parameters.RequestId), response.ErrorDescription); } [Fact] @@ -55,7 +56,7 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'request_id' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.RequestId), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs index 50e0a542..e85f8190 100644 --- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs +++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs @@ -26,6 +26,7 @@ using Xunit.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.AspNetCore.FunctionalTests { @@ -287,7 +288,7 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("This server only accepts HTTPS requests.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3083), response.ErrorDescription); } [Theory] diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs index 710cb12a..9f27df74 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs @@ -436,7 +436,7 @@ namespace OpenIddict.Server.FunctionalTests // returned by ReadAsStreamAsync() is always assumed to contain UTF-8 encoded payloads. using var stream = await message.Content.ReadAsStreamAsync(); using var document = await HtmlParser.ParseDocumentAsync(stream); - + // Note: a dictionary is deliberately not used here to allow multiple parameters with the // same name to be retrieved. While initially not allowed by the core OAuth2 specification, // this is required for derived drafts like the OAuth2 token exchange specification. diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs index 672be607..8557be98 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs @@ -9,7 +9,6 @@ using System.Collections.Immutable; using System.Linq; using System.Net.Http; using System.Security.Claims; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; @@ -18,6 +17,7 @@ using OpenIddict.Abstractions; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.FunctionalTests { @@ -40,7 +40,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified HTTP method is not valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3084), response.ErrorDescription); } [Fact] @@ -64,7 +64,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.RequestNotSupported, response.Error); - Assert.Equal("The 'request' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3028(Parameters.Request), response.ErrorDescription); } [Fact] @@ -86,7 +86,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.RequestUriNotSupported, response.Error); - Assert.Equal("The 'request_uri' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3028(Parameters.RequestUri), response.ErrorDescription); } [Theory] @@ -196,7 +196,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'client_id' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.ClientId), response.ErrorDescription); } [Fact] @@ -216,14 +216,14 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'redirect_uri' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.RedirectUri), response.ErrorDescription); } [Theory] - [InlineData("/path", "The 'redirect_uri' parameter must be a valid absolute URL.")] - [InlineData("/tmp/file.xml", "The 'redirect_uri' parameter must be a valid absolute URL.")] - [InlineData("C:\\tmp\\file.xml", "The 'redirect_uri' parameter must be a valid absolute URL.")] - [InlineData("http://www.fabrikam.com/path#param=value", "The 'redirect_uri' parameter must not include a fragment.")] + [InlineData("/path", SR.ID3030)] + [InlineData("/tmp/file.xml", SR.ID3030)] + [InlineData("C:\\tmp\\file.xml", SR.ID3030)] + [InlineData("http://www.fabrikam.com/path#param=value", SR.ID3031)] public async Task ValidateAuthorizationRequest_InvalidRedirectUriCausesAnError(string address, string message) { // Arrange @@ -240,7 +240,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal(message, response.ErrorDescription); + Assert.Equal(string.Format(SR.GetResourceString(message), Parameters.RedirectUri), response.ErrorDescription); } [Fact] @@ -261,7 +261,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'response_type' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.ResponseType), response.ErrorDescription); } [Theory] @@ -289,7 +289,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'response_type'/'response_mode' combination is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3033(Parameters.ResponseType, Parameters.ResponseMode), response.ErrorDescription); } [Theory] @@ -316,7 +316,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'nonce' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.Nonce), response.ErrorDescription); } [Theory] @@ -340,7 +340,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'openid' scope is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3034(Scopes.OpenId), response.ErrorDescription); } [Theory] @@ -366,7 +366,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'prompt' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.Prompt), response.ErrorDescription); } [Theory] @@ -440,8 +440,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'code_challenge' and 'code_challenge_method' parameters " + - "can only be used with a response type containing 'code'.", response.ErrorDescription); + Assert.Equal(SR.FormatID3040(Parameters.CodeChallenge, Parameters.CodeChallengeMethod, ResponseTypes.Code), response.ErrorDescription); } [Fact] @@ -463,7 +462,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'code_challenge_method' parameter cannot be used without 'code_challenge'.", response.ErrorDescription); + Assert.Equal(SR.FormatID3037(Parameters.CodeChallengeMethod, Parameters.CodeChallenge), response.ErrorDescription); } [Fact] @@ -486,7 +485,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'code_challenge_method' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3032(Parameters.CodeChallengeMethod), response.ErrorDescription); } [Fact] @@ -506,7 +505,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnsupportedResponseType, response.Error); - Assert.Equal("The specified 'response_type' parameter is not allowed.", response.ErrorDescription); + Assert.Equal(SR.FormatID3032(Parameters.ResponseType), response.ErrorDescription); } [Fact] @@ -526,7 +525,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnsupportedResponseType, response.Error); - Assert.Equal("The specified 'response_type' parameter is not allowed.", response.ErrorDescription); + Assert.Equal(SR.FormatID3032(Parameters.ResponseType), response.ErrorDescription); } [Theory] @@ -562,7 +561,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnsupportedResponseType, response.Error); - Assert.Equal("The specified 'response_type' parameter is not allowed.", response.ErrorDescription); + Assert.Equal(SR.FormatID3032(Parameters.ResponseType), response.ErrorDescription); } [Fact] @@ -607,7 +606,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidScope, response.Error); - Assert.Equal("The specified 'scope' parameter is not valid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.Scope), response.ErrorDescription); } [Fact] @@ -767,7 +766,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'offline_access' scope is not allowed.", response.ErrorDescription); + Assert.Equal(SR.FormatID3035(Scopes.OfflineAccess), response.ErrorDescription); } [Fact] @@ -788,7 +787,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'response_mode' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3032(Parameters.ResponseMode), response.ErrorDescription); } [Fact] @@ -810,7 +809,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'code_challenge_method' parameter must be specified.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.CodeChallengeMethod), response.ErrorDescription); } [Fact] @@ -838,7 +837,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'code_challenge_method' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3032(Parameters.CodeChallengeMethod), response.ErrorDescription); } [Fact] @@ -860,7 +859,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'code_challenge_method' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3032(Parameters.CodeChallengeMethod), response.ErrorDescription); } [Theory] @@ -928,7 +927,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'response_type' parameter is not allowed when using PKCE.", response.ErrorDescription); + Assert.Equal(SR.FormatID3041(Parameters.ResponseType), response.ErrorDescription); } [Fact] @@ -949,7 +948,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'redirect_uri' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.RedirectUri), response.ErrorDescription); } [Fact] @@ -971,7 +970,7 @@ namespace OpenIddict.Server.FunctionalTests }); // Assert - Assert.Equal("The request cannot be validated because no redirect_uri was specified.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1027), exception.Message); } [Fact] @@ -1005,8 +1004,7 @@ namespace OpenIddict.Server.FunctionalTests }); // Assert - Assert.Equal("The authorization request cannot be validated because a different " + - "redirect_uri was specified by the client application.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1100), exception.Message); } [Fact] @@ -1036,7 +1034,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'client_id' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.ClientId), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); } @@ -1079,7 +1077,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnauthorizedClient, response.Error); - Assert.Equal("The specified 'response_type' parameter is not valid for this client application.", response.ErrorDescription); + Assert.Equal(SR.FormatID3043(Parameters.ResponseType), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Confidential, It.IsAny()), Times.Once()); @@ -1123,7 +1121,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnauthorizedClient, response.Error); - Assert.Equal("This client application is not allowed to use the authorization endpoint.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3046), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, @@ -1134,31 +1132,31 @@ namespace OpenIddict.Server.FunctionalTests [InlineData( "code", new[] { Permissions.GrantTypes.AuthorizationCode }, - "The client application is not allowed to use the authorization code flow.")] + SR.ID3047)] [InlineData( "code id_token", new[] { Permissions.GrantTypes.AuthorizationCode, Permissions.GrantTypes.Implicit }, - "The client application is not allowed to use the hybrid flow.")] + SR.ID3049)] [InlineData( "code id_token token", new[] { Permissions.GrantTypes.AuthorizationCode, Permissions.GrantTypes.Implicit }, - "The client application is not allowed to use the hybrid flow.")] + SR.ID3049)] [InlineData( "code token", new[] { Permissions.GrantTypes.AuthorizationCode, Permissions.GrantTypes.Implicit }, - "The client application is not allowed to use the hybrid flow.")] + SR.ID3049)] [InlineData( "id_token", new[] { Permissions.GrantTypes.Implicit }, - "The client application is not allowed to use the implicit flow.")] + SR.ID3048)] [InlineData( "id_token token", new[] { Permissions.GrantTypes.Implicit }, - "The client application is not allowed to use the implicit flow.")] + SR.ID3048)] [InlineData( "token", new[] { Permissions.GrantTypes.Implicit }, - "The client application is not allowed to use the implicit flow.")] + SR.ID3048)] public async Task ValidateAuthorizationRequest_RequestIsRejectedWhenGrantTypePermissionIsNotGranted( string type, string[] permissions, string description) { @@ -1201,7 +1199,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnauthorizedClient, response.Error); - Assert.Equal(description, response.ErrorDescription); + Assert.Equal(SR.GetResourceString(description), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, permissions[0], It.IsAny()), Times.Once()); @@ -1250,7 +1248,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The client application is not allowed to use the 'offline_access' scope.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3050), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, It.IsAny()), Times.Once()); @@ -1288,7 +1286,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'redirect_uri' parameter is not valid for this client application.", response.ErrorDescription); + Assert.Equal(SR.FormatID3043(Parameters.RedirectUri), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.ValidateRedirectUriAsync(application, "http://www.fabrikam.com/path", It.IsAny()), Times.Once()); @@ -1337,7 +1335,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("This client application is not allowed to use the specified scope.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3051), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, Permissions.Prefixes.Scope + Scopes.OpenId, It.IsAny()), Times.Never()); @@ -1387,7 +1385,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'code_challenge' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.CodeChallenge), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasRequirementAsync(application, @@ -1901,11 +1899,7 @@ namespace OpenIddict.Server.FunctionalTests return client.SendAsync(HttpMethod.Put, "/connect/authorize", new OpenIddictRequest()); }); - Assert.Equal(new StringBuilder() - .Append("The authorization response was not correctly applied. To apply authorization responses, ") - .Append("create a class implementing 'IOpenIddictServerHandler' ") - .AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1029), exception.Message); } [Fact] @@ -2059,7 +2053,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'response_mode' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3032(Parameters.ResponseMode), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs index 6ba83632..87d82552 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs @@ -16,6 +16,7 @@ using OpenIddict.Abstractions; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.FunctionalTests { @@ -39,7 +40,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified HTTP method is not valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3084), response.ErrorDescription); } [Theory] diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Exchange.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Exchange.cs index 389ff5e2..8fbda00c 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Exchange.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Exchange.cs @@ -18,6 +18,7 @@ using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlers; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.FunctionalTests { @@ -41,7 +42,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified HTTP method is not valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3084), response.ErrorDescription); } [Theory] @@ -151,7 +152,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'grant_type' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.GrantType), response.ErrorDescription); } [Fact] @@ -171,7 +172,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The mandatory 'client_id' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.ClientId), response.ErrorDescription); } [Fact] @@ -191,7 +192,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'code' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.Code), response.ErrorDescription); } [Fact] @@ -210,7 +211,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'refresh_token' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.RefreshToken), response.ErrorDescription); } [Theory] @@ -233,8 +234,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'client_id' and 'client_secret' parameters are " + - "required when using the client credentials grant.", response.ErrorDescription); + Assert.Equal(SR.FormatID3057(Parameters.ClientId, Parameters.ClientSecret), response.ErrorDescription); } [Theory] @@ -257,7 +257,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'username' and/or 'password' parameters are missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3059(Parameters.Username, Parameters.Password), response.ErrorDescription); } [Fact] @@ -277,7 +277,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified authorization code is invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3001), response.ErrorDescription); } [Fact] @@ -296,7 +296,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified refresh token is invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3003), response.ErrorDescription); } [Fact] @@ -338,7 +338,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified authorization code is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3016), response.ErrorDescription); } [Fact] @@ -379,7 +379,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified refresh token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3018), response.ErrorDescription); } [Fact] @@ -422,7 +422,7 @@ namespace OpenIddict.Server.FunctionalTests }); }); - Assert.Equal("The presenters list cannot be extracted from the authorization code.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1042), exception.Message); } [Fact] @@ -464,7 +464,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified authorization code cannot be used by this client application.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3069), response.ErrorDescription); } [Fact] @@ -506,7 +506,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified refresh token cannot be used by this client application.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3071), response.ErrorDescription); } [Fact] @@ -550,7 +550,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'redirect_uri' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.RedirectUri), response.ErrorDescription); } [Fact] @@ -594,8 +594,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified 'redirect_uri' parameter doesn't match the client " + - "redirection endpoint the authorization code was initially sent to.", response.ErrorDescription); + Assert.Equal(SR.FormatID3072(Parameters.RedirectUri), response.ErrorDescription); } [Fact] @@ -638,7 +637,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'code_verifier' parameter is uncalled for in this request.", response.ErrorDescription); + Assert.Equal(SR.FormatID3073(Parameters.CodeVerifier), response.ErrorDescription); } [Fact] @@ -683,7 +682,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'code_verifier' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.CodeVerifier), response.ErrorDescription); } [Fact] @@ -729,7 +728,7 @@ namespace OpenIddict.Server.FunctionalTests }); }); - Assert.Equal("The code challenge method cannot be retrieved from the authorization code.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1267), exception.Message); } [Fact] @@ -775,7 +774,7 @@ namespace OpenIddict.Server.FunctionalTests }); }); - Assert.Equal("The specified code challenge method is not supported.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1044), exception.Message); } [Theory] @@ -822,7 +821,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified 'code_verifier' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.CodeVerifier), response.ErrorDescription); } [Theory] @@ -921,7 +920,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The 'scope' parameter is not valid in this context.", response.ErrorDescription); + Assert.Equal(SR.FormatID3074(Parameters.Scope), response.ErrorDescription); } [Fact] @@ -965,7 +964,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified 'scope' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.Scope), response.ErrorDescription); } [Fact] @@ -1007,7 +1006,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The 'scope' parameter is not valid in this context.", response.ErrorDescription); + Assert.Equal(SR.FormatID3074(Parameters.Scope), response.ErrorDescription); } [Fact] @@ -1049,7 +1048,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified 'scope' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.Scope), response.ErrorDescription); } [Theory] @@ -1081,7 +1080,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnsupportedGrantType, response.Error); - Assert.Equal("The specified 'grant_type' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3032(Parameters.GrantType), response.ErrorDescription); } [Fact] @@ -1108,7 +1107,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'offline_access' scope is not allowed.", response.ErrorDescription); + Assert.Equal(SR.FormatID3035(Scopes.OfflineAccess), response.ErrorDescription); } [Fact] @@ -1139,7 +1138,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidScope, response.Error); - Assert.Equal("The specified 'scope' parameter is not valid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.Scope), response.ErrorDescription); } [Fact] @@ -1252,8 +1251,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'client_id' and 'client_secret' parameters are " + - "required when using the client credentials grant.", response.ErrorDescription); + Assert.Equal(SR.FormatID3057(Parameters.ClientId, Parameters.ClientSecret), response.ErrorDescription); } [Fact] @@ -1279,7 +1277,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The mandatory 'client_id' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.ClientId), response.ErrorDescription); } [Fact] @@ -1310,7 +1308,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The specified 'client_id' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.ClientId), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); } @@ -1347,7 +1345,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnauthorizedClient, response.Error); - Assert.Equal("The specified 'grant_type' parameter is not valid for this client application.", response.ErrorDescription); + Assert.Equal(SR.FormatID3043(Parameters.GrantType), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny()), Times.Once()); @@ -1387,7 +1385,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The 'client_secret' parameter is not valid for this client application.", response.ErrorDescription); + Assert.Equal(SR.FormatID3061(Parameters.ClientSecret), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny()), Times.Once()); @@ -1427,7 +1425,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The 'client_secret' parameter required for this client application is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3062(Parameters.ClientSecret), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny()), Times.Once()); @@ -1470,7 +1468,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The specified client credentials are invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3055), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny()), Times.AtLeastOnce()); @@ -1516,7 +1514,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnauthorizedClient, response.Error); - Assert.Equal("This client application is not allowed to use the token endpoint.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3063), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, @@ -1562,7 +1560,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnauthorizedClient, response.Error); - Assert.Equal("This client application is not allowed to use the specified grant type.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3064), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, @@ -1613,7 +1611,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The client application is not allowed to use the 'offline_access' scope.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3050), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, It.IsAny()), Times.Once()); @@ -1664,7 +1662,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("This client application is not allowed to use the specified scope.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3051), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, Permissions.Prefixes.Scope + Scopes.OpenId, It.IsAny()), Times.Never()); @@ -1714,7 +1712,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'code_verifier' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.CodeVerifier), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, It.IsAny()), Times.Once()); @@ -2143,7 +2141,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified authorization code is invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3001), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.AtLeastOnce()); } @@ -2202,7 +2200,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified refresh token is invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3003), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny()), Times.AtLeastOnce()); } @@ -2282,7 +2280,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified authorization code has already been redeemed.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3010), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(token, Statuses.Redeemed, It.IsAny()), Times.Once()); @@ -2349,7 +2347,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified refresh token has already been redeemed.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3012), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(token, Statuses.Redeemed, It.IsAny()), Times.Once()); @@ -2445,7 +2443,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified authorization code has already been redeemed.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3010), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(manager => manager.TryRevokeAsync(authorization, It.IsAny()), Times.Once()); @@ -2527,7 +2525,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified refresh token has already been redeemed.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3012), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(manager => manager.TryRevokeAsync(authorization, It.IsAny()), Times.Once()); @@ -2624,7 +2622,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified authorization code has already been redeemed.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3010), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(tokens[0], Statuses.Redeemed, It.IsAny()), Times.Once()); @@ -2711,7 +2709,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified refresh token has already been redeemed.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3012), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(tokens[0], Statuses.Redeemed, It.IsAny()), Times.Once()); @@ -2799,7 +2797,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified authorization code is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3016), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(token, Statuses.Redeemed, It.IsAny()), Times.Once()); @@ -2872,7 +2870,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified refresh token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3018), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(token, Statuses.Valid, It.IsAny()), Times.Once()); @@ -3151,7 +3149,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The authorization associated with the authorization code is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3020), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny()), Times.Once()); } @@ -3249,7 +3247,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The authorization associated with the authorization code is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3020), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(authorization, Statuses.Valid, It.IsAny()), Times.Once()); @@ -3329,7 +3327,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The authorization associated with the refresh token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3022), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny()), Times.Once()); } @@ -3413,7 +3411,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The authorization associated with the refresh token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3022), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(authorization, Statuses.Valid, It.IsAny()), Times.Once()); diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Introspection.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Introspection.cs index 795c7515..e23755d3 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Introspection.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Introspection.cs @@ -20,6 +20,7 @@ using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlers; using static OpenIddict.Server.OpenIddictServerHandlers.Introspection; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.FunctionalTests { @@ -42,7 +43,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified HTTP method is not valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3084), response.ErrorDescription); } [Theory] @@ -152,7 +153,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'token' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.Token), response.ErrorDescription); } [Fact] @@ -176,7 +177,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The specified token is invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3004), response.ErrorDescription); } [Fact] @@ -217,7 +218,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The specified token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3019), response.ErrorDescription); } [Fact] @@ -258,7 +259,7 @@ namespace OpenIddict.Server.FunctionalTests }); }); - Assert.Equal("The presenters list cannot be extracted from the authorization code.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1042), exception.Message); } [Fact] @@ -300,7 +301,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The client application is not allowed to introspect the specified token.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3077), response.ErrorDescription); } [Fact] @@ -343,7 +344,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The client application is not allowed to introspect the specified token.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3077), response.ErrorDescription); } [Fact] @@ -385,7 +386,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The client application is not allowed to introspect the specified token.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3077), response.ErrorDescription); } [Fact] @@ -427,7 +428,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The client application is not allowed to introspect the specified token.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3077), response.ErrorDescription); } [Fact] @@ -449,7 +450,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The mandatory 'client_id' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.ClientId), response.ErrorDescription); } [Fact] @@ -479,7 +480,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The specified 'client_id' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.ClientId), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.Once()); } @@ -521,7 +522,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnauthorizedClient, response.Error); - Assert.Equal("This client application is not allowed to use the introspection endpoint.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3075), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, @@ -560,7 +561,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The 'client_secret' parameter is not valid for this client application.", response.ErrorDescription); + Assert.Equal(SR.FormatID3061(Parameters.ClientSecret), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny()), Times.Once()); @@ -598,7 +599,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The 'client_secret' parameter required for this client application is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3062(Parameters.ClientSecret), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny()), Times.Once()); @@ -1248,7 +1249,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The specified token is invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3004), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByReferenceIdAsync("QaTk2f6UPe9trKismGBJr0OIs0KqpvNrqRsJqGuJAAI", It.IsAny()), Times.AtLeastOnce()); } @@ -1433,7 +1434,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The authorization associated with the token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3023), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny()), Times.Once()); } @@ -1531,7 +1532,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The authorization associated with the token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3023), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("18D15F73-BE2B-6867-DC01-B3C1E8AFDED0", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(authorization, Statuses.Valid, It.IsAny()), Times.Once()); @@ -1616,7 +1617,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The specified token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3019), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByReferenceIdAsync("QaTk2f6UPe9trKismGBJr0OIs0KqpvNrqRsJqGuJAAI", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(manager => manager.HasStatusAsync(token, Statuses.Valid, It.IsAny()), Times.Once()); diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Revocation.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Revocation.cs index 9ecfca6f..57b3f8fa 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Revocation.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Revocation.cs @@ -16,6 +16,7 @@ using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlers; using static OpenIddict.Server.OpenIddictServerHandlers.Revocation; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.FunctionalTests { @@ -39,7 +40,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified HTTP method is not valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3084), response.ErrorDescription); } [Theory] @@ -149,7 +150,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The mandatory 'token' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.Token), response.ErrorDescription); } [Fact] @@ -191,7 +192,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnsupportedTokenType, response.Error); - Assert.Equal("This token cannot be revoked.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3079), response.ErrorDescription); } [Fact] @@ -233,7 +234,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The client application is not allowed to revoke the specified token.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3080), response.ErrorDescription); } [Fact] @@ -276,7 +277,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The client application is not allowed to revoke the specified token.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3080), response.ErrorDescription); } [Fact] @@ -318,7 +319,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The client application is not allowed to revoke the specified token.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3080), response.ErrorDescription); } [Fact] @@ -341,7 +342,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The mandatory 'client_id' parameter is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3029(Parameters.ClientId), response.ErrorDescription); } [Fact] @@ -371,7 +372,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The specified 'client_id' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.ClientId), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); } @@ -414,7 +415,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.UnauthorizedClient, response.Error); - Assert.Equal("This client application is not allowed to use the revocation endpoint.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3078), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(application, @@ -454,7 +455,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The 'client_secret' parameter is not valid for this client application.", response.ErrorDescription); + Assert.Equal(SR.FormatID3061(Parameters.ClientSecret), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny()), Times.Once()); @@ -493,7 +494,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The 'client_secret' parameter required for this client application is missing.", response.ErrorDescription); + Assert.Equal(SR.FormatID3062(Parameters.ClientSecret), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny()), Times.Once()); @@ -535,7 +536,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidClient, response.Error); - Assert.Equal("The specified client credentials are invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3055), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByClientIdAsync("Fabrikam", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.HasClientTypeAsync(application, ClientTypes.Public, It.IsAny()), Times.AtLeastOnce()); @@ -731,7 +732,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The specified token is invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3004), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.TryRevokeAsync(It.IsAny(), It.IsAny()), Times.Never()); @@ -791,7 +792,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The specified token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3019), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.TryRevokeAsync(It.IsAny(), It.IsAny()), Times.Never()); diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Session.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Session.cs index 1d59d716..369a5029 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Session.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Session.cs @@ -14,6 +14,7 @@ using OpenIddict.Abstractions; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.FunctionalTests { @@ -36,7 +37,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified HTTP method is not valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3084), response.ErrorDescription); } [Theory] @@ -132,11 +133,11 @@ namespace OpenIddict.Server.FunctionalTests } [Theory] - [InlineData("/path", "The 'post_logout_redirect_uri' parameter must be a valid absolute URL.")] - [InlineData("/tmp/file.xml", "The 'post_logout_redirect_uri' parameter must be a valid absolute URL.")] - [InlineData("C:\\tmp\\file.xml", "The 'post_logout_redirect_uri' parameter must be a valid absolute URL.")] - [InlineData("http://www.fabrikam.com/path#param=value", "The 'post_logout_redirect_uri' parameter must not include a fragment.")] - public async Task ValidateLogoutRequest_RequestIsRejectedWhenRedirectUriIsInvalid(string address, string message) + [InlineData("/path", SR.ID3030)] + [InlineData("/tmp/file.xml", SR.ID3030)] + [InlineData("C:\\tmp\\file.xml", SR.ID3030)] + [InlineData("http://www.fabrikam.com/path#param=value", SR.ID3031)] + public async Task ValidateLogoutRequest_InvalidRedirectUriCausesAnError(string address, string message) { // Arrange await using var server = await CreateServerAsync(); @@ -150,7 +151,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal(message, response.ErrorDescription); + Assert.Equal(string.Format(SR.GetResourceString(message), Parameters.PostLogoutRedirectUri), response.ErrorDescription); } [Fact] @@ -178,7 +179,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'post_logout_redirect_uri' parameter is not valid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.PostLogoutRedirectUri), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByPostLogoutRedirectUriAsync("http://www.fabrikam.com/path", It.IsAny()), Times.Once()); } @@ -222,7 +223,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'post_logout_redirect_uri' parameter is not valid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.PostLogoutRedirectUri), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByPostLogoutRedirectUriAsync("http://www.fabrikam.com/path", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(manager => manager.HasPermissionAsync(applications[0], Permissions.Endpoints.Logout, It.IsAny()), Times.Once()); diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Userinfo.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Userinfo.cs index 2b1ab0d7..d2a516bf 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Userinfo.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Userinfo.cs @@ -14,6 +14,7 @@ using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlers; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.FunctionalTests { @@ -36,7 +37,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified HTTP method is not valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3084), response.ErrorDescription); } [Theory] @@ -163,7 +164,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The specified token is invalid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3004), response.ErrorDescription); } [Fact] @@ -201,7 +202,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidToken, response.Error); - Assert.Equal("The specified token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3019), response.ErrorDescription); } [Theory] diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs index bd9fa152..d45c3f45 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs @@ -8,19 +8,21 @@ using System; using System.Collections.Immutable; using System.Linq; using System.Security.Claims; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; using Moq; using OpenIddict.Abstractions; +using OpenIddict.Abstractions.Resources; using OpenIddict.Core; using Xunit; using Xunit.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.OpenIddictServerHandlers; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.FunctionalTests { @@ -46,13 +48,7 @@ namespace OpenIddict.Server.FunctionalTests return client.PostAsync("/authenticate", new OpenIddictRequest()); }); - Assert.Equal(new StringBuilder() - .AppendLine("An identity cannot be extracted from this request.") - .Append("This generally indicates that the OpenIddict server stack was asked ") - .AppendLine("to validate a token for an endpoint it doesn't manage.") - .Append("To validate tokens received by custom API endpoints, ") - .Append("the OpenIddict validation services must be used instead.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1001), exception.Message); } [Fact] @@ -81,13 +77,7 @@ namespace OpenIddict.Server.FunctionalTests return client.GetAsync("/authenticate"); }); - Assert.Equal(new StringBuilder() - .AppendLine("An identity cannot be extracted from this request.") - .Append("This generally indicates that the OpenIddict server stack was asked ") - .AppendLine("to validate a token for an endpoint it doesn't manage.") - .Append("To validate tokens received by custom API endpoints, ") - .Append("the OpenIddict validation services must be used instead.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1001), exception.Message); } [Fact] @@ -121,11 +111,7 @@ namespace OpenIddict.Server.FunctionalTests }); }); - Assert.Equal(new StringBuilder() - .AppendLine("An identity cannot be extracted from this token request.") - .Append("This generally indicates that the OpenIddict server stack was asked ") - .AppendLine("to validate a token for an invalid grant type (e.g password).") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1000), exception.Message); } [Fact] @@ -733,11 +719,7 @@ namespace OpenIddict.Server.FunctionalTests }); // Assert - Assert.Equal(new StringBuilder() - .AppendLine("The deserialized principal doesn't contain the mandatory 'oi_tkn_typ' claim.") - .Append("When implementing custom token deserialization, a 'oi_tkn_typ' claim containing ") - .Append("the type of the token being processed must be added to the security principal.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1003), exception.Message); } [Fact] @@ -787,10 +769,7 @@ namespace OpenIddict.Server.FunctionalTests }); // Assert - Assert.Equal(new StringBuilder() - .AppendFormat("The type of token associated with the deserialized principal ({0}) ", TokenTypeHints.AuthorizationCode) - .AppendFormat("doesn't match the expected token type ({0}).", TokenTypeHints.AccessToken) - .ToString(), exception.Message); + Assert.Equal(SR.FormatID1004(TokenTypeHints.AuthorizationCode, TokenTypeHints.AccessToken), exception.Message); } [Fact] @@ -1137,7 +1116,7 @@ namespace OpenIddict.Server.FunctionalTests return client.PostAsync("/challenge", new OpenIddictRequest()); }); - Assert.Equal("An OpenID Connect response cannot be returned from this endpoint.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1005), exception.Message); } [Fact] @@ -1166,7 +1145,7 @@ namespace OpenIddict.Server.FunctionalTests return client.GetAsync("/challenge"); }); - Assert.Equal("An OpenID Connect response cannot be returned from this endpoint.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1005), exception.Message); } [Fact] @@ -1201,7 +1180,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.AccessDenied, response.Error); - Assert.Equal("The authorization was denied by the resource owner.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3015), response.ErrorDescription); Assert.Null(response.ErrorUri); } @@ -1235,7 +1214,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The token request was rejected by the authorization server.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3024), response.ErrorDescription); Assert.Null(response.ErrorUri); } @@ -1283,7 +1262,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InsufficientAccess, response.Error); - Assert.Equal("The user information access demand was rejected by the authorization server.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3025), response.ErrorDescription); Assert.Null(response.ErrorUri); } @@ -1394,7 +1373,7 @@ namespace OpenIddict.Server.FunctionalTests return client.PostAsync("/signin", new OpenIddictRequest()); }); - Assert.Equal("An OpenID Connect response cannot be returned from this endpoint.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1009), exception.Message); } [Fact] @@ -1423,7 +1402,7 @@ namespace OpenIddict.Server.FunctionalTests return client.GetAsync("/signin"); }); - Assert.Equal("An OpenID Connect response cannot be returned from this endpoint.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1009), exception.Message); } [Fact] @@ -1456,10 +1435,7 @@ namespace OpenIddict.Server.FunctionalTests }); }); - Assert.Equal(new StringBuilder() - .AppendLine("The specified principal doesn't contain any claims-based identity.") - .Append("Make sure that 'ClaimsPrincipal.Identity' is not null.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1010), exception.Message); } [Fact] @@ -1492,11 +1468,7 @@ namespace OpenIddict.Server.FunctionalTests }); }); - Assert.Equal(new StringBuilder() - .AppendLine("The specified principal doesn't contain a valid/authenticated identity.") - .Append("Make sure that 'ClaimsPrincipal.Identity.AuthenticationType' is not null ") - .Append("and that 'ClaimsPrincipal.Identity.IsAuthenticated' returns 'true'.") - .ToString(), exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1013), exception.Message); } [Fact] @@ -1529,7 +1501,7 @@ namespace OpenIddict.Server.FunctionalTests }); }); - Assert.Equal("The specified principal was rejected because the mandatory subject claim was missing.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1014), exception.Message); } [Fact] @@ -3212,7 +3184,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified authorization code is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3016), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.TryRedeemAsync(token, It.IsAny()), Times.Once()); @@ -3350,7 +3322,7 @@ namespace OpenIddict.Server.FunctionalTests // Assert Assert.Equal(Errors.InvalidGrant, response.Error); - Assert.Equal("The specified refresh token is no longer valid.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3018), response.ErrorDescription); Mock.Get(manager).Verify(manager => manager.FindByIdAsync("60FFF7EA-F98E-437B-937E-5073CC313103", It.IsAny()), Times.AtLeastOnce()); Mock.Get(manager).Verify(manager => manager.TryRedeemAsync(token, It.IsAny()), Times.Once()); @@ -4100,7 +4072,7 @@ namespace OpenIddict.Server.FunctionalTests return client.PostAsync("/signout", new OpenIddictRequest()); }); - Assert.Equal("An OpenID Connect response cannot be returned from this endpoint.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1023), exception.Message); } [Fact] @@ -4129,7 +4101,7 @@ namespace OpenIddict.Server.FunctionalTests return client.GetAsync("/signout"); }); - Assert.Equal("An OpenID Connect response cannot be returned from this endpoint.", exception.Message); + Assert.Equal(SR.GetResourceString(SR.ID1023), exception.Message); } [Theory] @@ -4290,9 +4262,10 @@ namespace OpenIddict.Server.FunctionalTests { var manager = new Mock>( Mock.Of>(), - Mock.Of(), + Mock.Of>(), OutputHelper.ToLogger>(), - Mock.Of>()); + Mock.Of>(), + Mock.Of()); configuration?.Invoke(manager); @@ -4304,9 +4277,10 @@ namespace OpenIddict.Server.FunctionalTests { var manager = new Mock>( Mock.Of>(), - Mock.Of(), + Mock.Of>(), OutputHelper.ToLogger>(), - Mock.Of>()); + Mock.Of>(), + Mock.Of()); configuration?.Invoke(manager); @@ -4318,9 +4292,10 @@ namespace OpenIddict.Server.FunctionalTests { var manager = new Mock>( Mock.Of>(), - Mock.Of(), + Mock.Of>(), OutputHelper.ToLogger>(), - Mock.Of>()); + Mock.Of>(), + Mock.Of()); configuration?.Invoke(manager); @@ -4332,9 +4307,10 @@ namespace OpenIddict.Server.FunctionalTests { var manager = new Mock>( Mock.Of>(), - Mock.Of(), + Mock.Of>(), OutputHelper.ToLogger>(), - Mock.Of>()); + Mock.Of>(), + Mock.Of()); configuration?.Invoke(manager); diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Authentication.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Authentication.cs index 357338cd..7e62615f 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Authentication.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Authentication.cs @@ -10,6 +10,7 @@ using OpenIddict.Abstractions; using OpenIddict.Server.FunctionalTests; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin.FunctionalTests { @@ -30,7 +31,7 @@ namespace OpenIddict.Server.Owin.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'request_id' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3028(Parameters.RequestId), response.ErrorDescription); } [Fact] @@ -55,7 +56,7 @@ namespace OpenIddict.Server.Owin.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'request_id' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.RequestId), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Exchange.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Exchange.cs index 0d594973..f82bcc2c 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Exchange.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Exchange.cs @@ -11,6 +11,7 @@ using Owin; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin.FunctionalTests { @@ -52,7 +53,7 @@ namespace OpenIddict.Server.Owin.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("Multiple client credentials cannot be specified.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3087), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Introspection.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Introspection.cs index 557d9ee5..0b6b027f 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Introspection.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Introspection.cs @@ -11,6 +11,7 @@ using Owin; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin.FunctionalTests { @@ -50,7 +51,7 @@ namespace OpenIddict.Server.Owin.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("Multiple client credentials cannot be specified.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3087), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Revocation.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Revocation.cs index 3fda38a0..0ea67a2c 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Revocation.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Revocation.cs @@ -11,6 +11,7 @@ using Owin; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin.FunctionalTests { @@ -50,7 +51,7 @@ namespace OpenIddict.Server.Owin.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("Multiple client credentials cannot be specified.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3087), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Session.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Session.cs index 92ec017e..9c59971a 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Session.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.Session.cs @@ -10,6 +10,7 @@ using OpenIddict.Abstractions; using OpenIddict.Server.FunctionalTests; using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin.FunctionalTests { @@ -30,7 +31,7 @@ namespace OpenIddict.Server.Owin.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The 'request_id' parameter is not supported.", response.ErrorDescription); + Assert.Equal(SR.FormatID3028(Parameters.RequestId), response.ErrorDescription); } [Fact] @@ -55,7 +56,7 @@ namespace OpenIddict.Server.Owin.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("The specified 'request_id' parameter is invalid.", response.ErrorDescription); + Assert.Equal(SR.FormatID3052(Parameters.RequestId), response.ErrorDescription); } } } diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs index e8134ad8..b6db3fb9 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs @@ -24,6 +24,7 @@ using Xunit.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlers; +using SR = OpenIddict.Abstractions.Resources.OpenIddictResources; namespace OpenIddict.Server.Owin.FunctionalTests { @@ -244,7 +245,7 @@ namespace OpenIddict.Server.Owin.FunctionalTests // Assert Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal("This server only accepts HTTPS requests.", response.ErrorDescription); + Assert.Equal(SR.GetResourceString(SR.ID3083), response.ErrorDescription); } [Theory] diff --git a/test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs b/test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs index b0964b96..c64d2b7e 100644 --- a/test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs +++ b/test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs @@ -1,7 +1,5 @@ using System; -using System.Linq; using System.Reflection; -using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -19,7 +17,7 @@ namespace OpenIddict.Server.Tests public void Constructor_ThrowsAnExceptionForNullServices() { // Arrange - var services = (IServiceCollection)null; + var services = (IServiceCollection) null; // Act and assert var exception = Assert.Throws(() => new OpenIddictServerBuilder(services)); @@ -831,7 +829,7 @@ namespace OpenIddict.Server.Tests // Assert Assert.True(options.DisableAccessTokenEncryption); } - + [Fact] public void SetAuthorizationEndpointUris_ThrowsExceptionWhenAddressesIsNull() { @@ -901,7 +899,7 @@ namespace OpenIddict.Server.Tests // Assert Assert.Contains(new Uri("http://localhost/endpoint-path"), options.AuthorizationEndpointUris); } - + [Fact] public void SetIntrospectionEndpointUris_ThrowsExceptionWhenAddressesIsNull() {