Browse Source

Update the entire codebase to use IStringLocalizer/ResourceManager

pull/1030/head
Kévin Chalet 6 years ago
parent
commit
8feeb8698d
  1. 1
      Directory.Build.props
  2. 16
      Directory.Build.targets
  3. 2
      Directory.Packages.props
  4. 2
      samples/Mvc.Server/ViewModels/Authorization/VerifyViewModel.cs
  5. 3
      shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs
  6. 4
      shared/OpenIddict.Extensions/OpenIddict.Extensions.csproj
  7. 1
      src/OpenIddict.Abstractions/Caches/IOpenIddictApplicationCache.cs
  8. 1
      src/OpenIddict.Abstractions/Caches/IOpenIddictTokenCache.cs
  9. 5
      src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj
  10. 3
      src/OpenIddict.Abstractions/Primitives/OpenIddictConverter.cs
  11. 57
      src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
  12. 17
      src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs
  13. 11
      src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs
  14. 1432
      src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx
  15. 4
      src/OpenIddict.Abstractions/Stores/IOpenIddictApplicationStore.cs
  16. 2
      src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs
  17. 4
      src/OpenIddict.Abstractions/Stores/IOpenIddictScopeStore.cs
  18. 2
      src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs
  19. 17
      src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs
  20. 41
      src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs
  21. 17
      src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs
  22. 37
      src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs
  23. 83
      src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
  24. 74
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  25. 36
      src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
  26. 69
      src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
  27. 1
      src/OpenIddict.Core/OpenIddict.Core.csproj
  28. 51
      src/OpenIddict.Core/OpenIddictCoreBuilder.cs
  29. 19
      src/OpenIddict.Core/OpenIddictCoreExtensions.cs
  30. 19
      src/OpenIddict.Core/Resolvers/OpenIddictApplicationStoreResolver.cs
  31. 19
      src/OpenIddict.Core/Resolvers/OpenIddictAuthorizationStoreResolver.cs
  32. 19
      src/OpenIddict.Core/Resolvers/OpenIddictScopeStoreResolver.cs
  33. 19
      src/OpenIddict.Core/Resolvers/OpenIddictTokenStoreResolver.cs
  34. 3
      src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs
  35. 15
      src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolver.cs
  36. 15
      src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolver.cs
  37. 15
      src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkScopeStoreResolver.cs
  38. 15
      src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkTokenStoreResolver.cs
  39. 25
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
  40. 54
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
  41. 25
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs
  42. 52
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs
  43. 3
      src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs
  44. 15
      src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolver.cs
  45. 15
      src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolver.cs
  46. 15
      src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolver.cs
  47. 15
      src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolver.cs
  48. 25
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs
  49. 54
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs
  50. 25
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs
  51. 52
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs
  52. 9
      src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs
  53. 9
      src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs
  54. 1
      src/OpenIddict.MongoDb/OpenIddictMongoDbOptions.cs
  55. 9
      src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbApplicationStoreResolver.cs
  56. 9
      src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbAuthorizationStoreResolver.cs
  57. 9
      src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbScopeStoreResolver.cs
  58. 9
      src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbTokenStoreResolver.cs
  59. 26
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs
  60. 50
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs
  61. 26
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs
  62. 46
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs
  63. 3
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs
  64. 18
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreConfiguration.cs
  65. 36
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs
  66. 36
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs
  67. 33
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs
  68. 66
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs
  69. 7
      src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs
  70. 3
      src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs
  71. 7
      src/OpenIddict.Server.Owin/OpenIddictServerOwinConfiguration.cs
  72. 38
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs
  73. 36
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs
  74. 2
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Device.cs
  75. 33
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs
  76. 61
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs
  77. 17
      src/OpenIddict.Server.Owin/OpenIddictServerOwinMiddlewareFactory.cs
  78. 1
      src/OpenIddict.Server/OpenIddict.Server.csproj
  79. 102
      src/OpenIddict.Server/OpenIddictServerBuilder.cs
  80. 109
      src/OpenIddict.Server/OpenIddictServerConfiguration.cs
  81. 13
      src/OpenIddict.Server/OpenIddictServerDispatcher.cs
  82. 7
      src/OpenIddict.Server/OpenIddictServerEvents.Authentication.cs
  83. 7
      src/OpenIddict.Server/OpenIddictServerEvents.Session.cs
  84. 2
      src/OpenIddict.Server/OpenIddictServerEvents.Userinfo.cs
  85. 7
      src/OpenIddict.Server/OpenIddictServerEvents.cs
  86. 19
      src/OpenIddict.Server/OpenIddictServerExtensions.cs
  87. 8
      src/OpenIddict.Server/OpenIddictServerFactory.cs
  88. 7
      src/OpenIddict.Server/OpenIddictServerHandlerDescriptor.cs
  89. 169
      src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
  90. 109
      src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs
  91. 23
      src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs
  92. 182
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  93. 90
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  94. 94
      src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
  95. 37
      src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs
  96. 18
      src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs
  97. 466
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  98. 5
      src/OpenIddict.Server/OpenIddictServerHelpers.cs
  99. 7
      src/OpenIddict.Server/OpenIddictServerOptions.cs
  100. 6
      src/OpenIddict.Server/OpenIddictServerTransaction.cs

1
Directory.Build.props

@ -9,6 +9,7 @@
<DebugSymbols>true</DebugSymbols>
<CodeAnalysisRuleset>$(MSBuildThisFileDirectory)eng\CodeAnalysis.ruleset</CodeAnalysisRuleset>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<EnableXlfLocalization>false</EnableXlfLocalization>
</PropertyGroup>
<PropertyGroup>

16
Directory.Build.targets

@ -73,5 +73,21 @@
</ReferencePath>
</ItemGroup>
</Target>
<!--
Note: Arcade always generates .resx backing files with internal static methods/constants.
To ensure the OpenIddict resources are public, the default visibility is manually overriden.
-->
<Target Name="OverrideResourcesVisibility" Condition=" @(EmbeddedResourceSGResx) != '' " AfterTargets="_GenerateResxSource">
<WriteLinesToFile
File=" %(EmbeddedResourceSGResx.SourceOutputPath) "
Lines=" $([System.IO.File]::ReadAllText(%(EmbeddedResourceSGResx.SourceOutputPath))
.Replace('internal const', 'public const')
.Replace('internal static', 'public static')
.Replace('static partial class', 'partial class')) "
Overwrite="true"
Encoding="Unicode" />
</Target>
</Project>

2
Directory.Packages.props

@ -42,6 +42,7 @@
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="2.1.2" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="2.1.2" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="2.1.1" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="2.1.1" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="2.1.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="2.1.1" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="2.1.6" />
@ -63,6 +64,7 @@
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.6" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="3.1.6" />
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="3.1.6" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="3.1.6" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="3.1.6" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="3.1.6" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="3.1.6" />

2
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; }

3
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)

4
shared/OpenIddict.Extensions/OpenIddict.Extensions.csproj

@ -5,4 +5,8 @@
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\OpenIddict.Abstractions\OpenIddict.Abstractions.csproj" />
</ItemGroup>
</Project>

1
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;

1
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;

5
src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFrameworks>net461;netstandard2.0;netstandard2.1</TargetFrameworks>
<GenerateResxSourceEmitFormatMethods>true</GenerateResxSourceEmitFormatMethods>
</PropertyGroup>
<PropertyGroup>
@ -29,4 +30,8 @@
<PackageReference Include="System.ComponentModel.Annotations" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="**\*Resources.resx" GenerateSource="true" GenerateResourcesCodeAsConstants="true" />
</ItemGroup>
</Project>

3
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));
}
/// <summary>

57
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);

17
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);

11
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));
}
}

1432
src/OpenIddict.Abstractions/Resources/OpenIddictResources.resx

File diff suppressed because it is too large

4
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
{

2
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
{

4
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
{

2
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
{

17
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());

41
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());

17
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());

37
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());

83
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<TApplication> cache,
[NotNull] IOpenIddictApplicationStoreResolver resolver,
[NotNull] IStringLocalizer<OpenIddictResources> localizer,
[NotNull] ILogger<OpenIddictApplicationManager<TApplication>> logger,
[NotNull] IOptionsMonitor<OpenIddictCoreOptions> options)
[NotNull] IOptionsMonitor<OpenIddictCoreOptions> options,
[NotNull] IOpenIddictApplicationStoreResolver resolver)
{
Cache = cache;
Store = resolver.Get<TApplication>();
Localizer = localizer;
Logger = logger;
Options = options;
Store = resolver.Get<TApplication>();
}
/// <summary>
@ -64,6 +69,11 @@ namespace OpenIddict.Core
/// </summary>
protected IOpenIddictApplicationCache<TApplication> Cache { get; }
/// <summary>
/// Gets the string localizer associated with the current manager.
/// </summary>
protected IStringLocalizer Localizer { get; }
/// <summary>
/// Gets the logger associated with the current manager.
/// </summary>
@ -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);

74
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<TAuthorization> cache,
[NotNull] IOpenIddictAuthorizationStoreResolver resolver,
[NotNull] IStringLocalizer<OpenIddictResources> localizer,
[NotNull] ILogger<OpenIddictAuthorizationManager<TAuthorization>> logger,
[NotNull] IOptionsMonitor<OpenIddictCoreOptions> options)
[NotNull] IOptionsMonitor<OpenIddictCoreOptions> options,
[NotNull] IOpenIddictAuthorizationStoreResolver resolver)
{
Cache = cache;
Store = resolver.Get<TAuthorization>();
Localizer = localizer;
Logger = logger;
Options = options;
Store = resolver.Get<TAuthorization>();
}
/// <summary>
@ -51,6 +56,11 @@ namespace OpenIddict.Core
/// </summary>
protected IOpenIddictAuthorizationCache<TAuthorization> Cache { get; }
/// <summary>
/// Gets the string localizer associated with the current manager.
/// </summary>
protected IStringLocalizer Localizer { get; }
/// <summary>
/// Gets the logger associated with the current manager.
/// </summary>
@ -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;
}

36
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<TScope> cache,
[NotNull] IOpenIddictScopeStoreResolver resolver,
[NotNull] IStringLocalizer<OpenIddictResources> localizer,
[NotNull] ILogger<OpenIddictScopeManager<TScope>> logger,
[NotNull] IOptionsMonitor<OpenIddictCoreOptions> options)
[NotNull] IOptionsMonitor<OpenIddictCoreOptions> options,
[NotNull] IOpenIddictScopeStoreResolver resolver)
{
Cache = cache;
Store = resolver.Get<TScope>();
Localizer = localizer;
Logger = logger;
Options = options;
Store = resolver.Get<TScope>();
}
/// <summary>
@ -50,6 +55,11 @@ namespace OpenIddict.Core
/// </summary>
protected IOpenIddictScopeCache<TScope> Cache { get; }
/// <summary>
/// Gets the string localizer associated with the current manager.
/// </summary>
protected IStringLocalizer Localizer { get; }
/// <summary>
/// Gets the logger associated with the current manager.
/// </summary>
@ -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]);
}
}
}

69
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<TToken> cache,
[NotNull] IOpenIddictTokenStoreResolver resolver,
[NotNull] IStringLocalizer<OpenIddictResources> localizer,
[NotNull] ILogger<OpenIddictTokenManager<TToken>> logger,
[NotNull] IOptionsMonitor<OpenIddictCoreOptions> options)
[NotNull] IOptionsMonitor<OpenIddictCoreOptions> options,
[NotNull] IOpenIddictTokenStoreResolver resolver)
{
Cache = cache;
Store = resolver.Get<TToken>();
Localizer = localizer;
Logger = logger;
Options = options;
Store = resolver.Get<TToken>();
}
/// <summary>
@ -51,6 +56,11 @@ namespace OpenIddict.Core
/// </summary>
protected IOpenIddictTokenCache<TToken> Cache { get; }
/// <summary>
/// Gets the string localizer associated with the current manager.
/// </summary>
protected IStringLocalizer Localizer { get; }
/// <summary>
/// Gets the logger associated with the current manager.
/// </summary>
@ -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.

1
src/OpenIddict.Core/OpenIddict.Core.csproj

@ -15,6 +15,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
<PackageReference Include="Microsoft.Extensions.Localization" />
<PackageReference Include="Microsoft.Extensions.Logging" />
<PackageReference Include="Microsoft.Extensions.Options" />
</ItemGroup>

51
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);

19
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;
/// <summary>
/// Exposes extensions allowing to register the OpenIddict core services.
/// </summary>
@ -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<IStringLocalizer<OpenIddictResources>>(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<OpenIddictResources>(factory);
});
return new OpenIddictCoreBuilder(builder.Services);
}

19
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
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
/// <returns>An <see cref="IOpenIddictApplicationStore{TApplication}"/>.</returns>
public IOpenIddictApplicationStore<TApplication> Get<TApplication>() where TApplication : class
{
var store = _provider.GetService<IOpenIddictApplicationStore<TApplication>>();
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<IOpenIddictApplicationStore<TApplication>>() ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1227));
}
}

19
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
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
/// <returns>An <see cref="IOpenIddictAuthorizationStore{TAuthorization}"/>.</returns>
public IOpenIddictAuthorizationStore<TAuthorization> Get<TAuthorization>() where TAuthorization : class
{
var store = _provider.GetService<IOpenIddictAuthorizationStore<TAuthorization>>();
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<IOpenIddictAuthorizationStore<TAuthorization>>() ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1228));
}
}

19
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
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
/// <returns>An <see cref="IOpenIddictScopeStore{TScope}"/>.</returns>
public IOpenIddictScopeStore<TScope> Get<TScope>() where TScope : class
{
var store = _provider.GetService<IOpenIddictScopeStore<TScope>>();
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<IOpenIddictScopeStore<TScope>>() ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1229));
}
}

19
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
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
/// <returns>An <see cref="IOpenIddictTokenStore{TToken}"/>.</returns>
public IOpenIddictTokenStore<TToken> Get<TToken>() where TToken : class
{
var store = _provider.GetService<IOpenIddictTokenStore<TToken>>();
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<IOpenIddictTokenStore<TToken>>() ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1230));
}
}

3
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);

15
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<TContext>()'.")
.ToString());
throw new InvalidOperationException(SR.GetResourceString(SR.ID1234));
}
return typeof(OpenIddictEntityFrameworkApplicationStore<,,,,>).MakeGenericType(

15
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<TContext>()'.")
.ToString());
throw new InvalidOperationException(SR.GetResourceString(SR.ID1234));
}
return typeof(OpenIddictEntityFrameworkAuthorizationStore<,,,,>).MakeGenericType(

15
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<TContext>()'.")
.ToString());
throw new InvalidOperationException(SR.GetResourceString(SR.ID1234));
}
return typeof(OpenIddictEntityFrameworkScopeStore<,,>).MakeGenericType(

15
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<TContext>()'.")
.ToString());
throw new InvalidOperationException(SR.GetResourceString(SR.ID1234));
}
return typeof(OpenIddictEntityFrameworkTokenStore<,,,,>).MakeGenericType(

25
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<TApplication>(Task.FromException<TApplication>(
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);
}
}

54
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<TAuthorization>(Task.FromException<TAuthorization>(
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);
}
}

25
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<TScope>(Task.FromException<TScope>(
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);
}
}

52
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<TToken>(Task.FromException<TToken>(
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);
}
}

3
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);

15
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<TContext>()'.")
.ToString());
throw new InvalidOperationException(SR.GetResourceString(SR.ID1252));
}
return typeof(OpenIddictEntityFrameworkCoreApplicationStore<,,,,>).MakeGenericType(

15
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<TContext>()'.")
.ToString());
throw new InvalidOperationException(SR.GetResourceString(SR.ID1252));
}
return typeof(OpenIddictEntityFrameworkCoreAuthorizationStore<,,,,>).MakeGenericType(

15
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<TContext>()'.")
.ToString());
throw new InvalidOperationException(SR.GetResourceString(SR.ID1252));
}
return typeof(OpenIddictEntityFrameworkCoreScopeStore<,,>).MakeGenericType(

15
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<TContext>()'.")
.ToString());
throw new InvalidOperationException(SR.GetResourceString(SR.ID1252));
}
return typeof(OpenIddictEntityFrameworkCoreTokenStore<,,,,>).MakeGenericType(

25
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<TApplication>(Task.FromException<TApplication>(
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);
}
}

54
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<TAuthorization>(Task.FromException<TAuthorization>(
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);
}
}

25
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<TScope>(Task.FromException<TScope>(
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);
}
}

52
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<TToken>(Task.FromException<TToken>(
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);
}
}

9
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);

9
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<IMongoDatabase>(Task.FromException<IMongoDatabase>(
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<IMongoDatabase>(database);

1
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

9
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);

9
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);

9
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);

9
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);

26
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<TApplication>(Task.FromException<TApplication>(
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));
}
}
}

50
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<TAuthorization>(Task.FromException<TAuthorization>(
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));
}
}
}

26
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<TScope>(Task.FromException<TScope>(
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));
}
}
}

46
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<TToken>(Task.FromException<TToken>(
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));
}
}
}

3
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);

18
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<OpenIddictServerAspNetCoreHandler>(
@ -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));
}
}
}

36
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<AuthenticateResult> HandleAuthenticateAsync()
{
var transaction = Context.Features.Get<OpenIddictServerAspNetCoreFeature>()?.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<OpenIddictServerAspNetCoreFeature>()?.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<OpenIddictServerAspNetCoreFeature>()?.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<OpenIddictServerAspNetCoreFeature>()?.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));
}
}
}

36
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<OpenIddictServerAspNetCoreOptions> _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) ||

33
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<OpenIddictServerAspNetCoreOptions> _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))

66
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<AuthenticationProperties>(typeof(AuthenticationProperties).FullName);

7
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

3
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);

7
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));
}
}
}

38
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<OpenIddictServerTransaction>(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<ProcessRequestContext>(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<OpenIddictServerTransaction>(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<OpenIddictServerTransaction>(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<OpenIddictServerTransaction>(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<OpenIddictServerTransaction>(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));
}
}
}

36
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<OpenIddictServerOwinOptions> _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) ||

2
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
{

33
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<OpenIddictServerOwinOptions> _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))

61
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<AuthenticationProperties>(typeof(AuthenticationProperties).FullName);

17
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<IServiceProvider>(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<T>(IServiceProvider provider)
=> provider.GetService<T>() ?? 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<T>(IServiceProvider provider) => provider.GetService<T>() ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1121));
}
}
}

1
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
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Localization" />
<PackageReference Include="Microsoft.Extensions.Logging" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" />
</ItemGroup>

102
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));
}
/// <summary>
@ -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<X509KeyUsageExtension>().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));
}
/// <summary>
@ -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<X509KeyUsageExtension>().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));

109
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<ValidateAuthorizationRequestContext>' 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<ValidateDeviceRequestContext>' 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<ValidateIntrospectionRequestContext>' 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<ValidateLogoutRequestContext>' 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<ValidateRevocationRequestContext>' 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<ValidateTokenRequestContext>' 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<ValidateVerificationRequestContext>' 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<ProcessAuthenticationContext>' 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<ProcessSignInContext>' 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));
}
}
}

13
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<TContext> 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))

7
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;

7
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;

2
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

7
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;
}
/// <summary>
/// Gets the localizer used to localize the messages generated by OpenIddict.
/// </summary>
public IStringLocalizer Localizer => Transaction.Localizer;
/// <summary>
/// Gets the logger responsible of logging processed operations.
/// </summary>

19
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;
/// <summary>
/// Exposes extensions allowing to register the OpenIddict server services.
/// </summary>
@ -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<RequireUserinfoRequest>();
builder.Services.TryAddSingleton<RequireVerificationRequest>();
builder.Services.TryAddSingleton<IStringLocalizer<OpenIddictResources>>(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<OpenIddictResources>(factory);
});
// Note: TryAddEnumerable() is used here to ensure the initializer is registered only once.
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<
IPostConfigureOptions<OpenIddictServerOptions>, OpenIddictServerConfiguration>());

8
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<OpenIddictServerDispatcher> _logger;
private readonly IStringLocalizer _localizer;
private readonly ILogger _logger;
private readonly IOptionsMonitor<OpenIddictServerOptions> _options;
/// <summary>
/// Creates a new instance of the <see cref="OpenIddictServerDispatcher"/> class.
/// </summary>
public OpenIddictServerFactory(
[NotNull] IStringLocalizer<OpenIddictResources> localizer,
[NotNull] ILogger<OpenIddictServerDispatcher> logger,
[NotNull] IOptionsMonitor<OpenIddictServerOptions> options)
{
_localizer = localizer;
_logger = logger;
_options = options;
}
@ -31,6 +36,7 @@ namespace OpenIddict.Server
=> new ValueTask<OpenIddictServerTransaction>(new OpenIddictServerTransaction
{
Issuer = _options.CurrentValue.Issuer,
Localizer = _localizer,
Logger = _logger,
Options = _options.CurrentValue
});

7
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
};
}

169
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<ExtractAuthorizationRequestContext>' ")
.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<HandleAuthorizationRequestContext>' ")
.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<ApplyAuthorizationResponseContext>' ")
.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;
}

109
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<ProcessErrorContext>.Descriptor,
ApplyVerificationResponse<ProcessRequestContext>.Descriptor,
ApplyVerificationResponse<ProcessSignInContext>.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<ExtractDeviceRequestContext>' ")
.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<ApplyDeviceResponseContext>' ")
.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<ExtractVerificationRequestContext>' ")
.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<HandleVerificationRequestContext>' ")
.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<ApplyVerificationResponseContext>' ")
.AppendLine("and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.")
.ToString());
throw new InvalidOperationException(SR.GetResourceString(SR.ID1035));
}
}

23
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<ExtractConfigurationRequestContext>' ")
.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<ExtractCryptographyRequestContext>' ")
.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<ApplyCryptographyResponseContext>' ")
.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);

182
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<ExtractTokenRequestContext>' ")
.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<HandleTokenRequestContext>' ")
.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<ApplyTokenResponseContext>' ")
.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<ValidateTokenRequestContext>(
typeof(ValidateTokenRequestContext).FullName) ??
throw new InvalidOperationException("The authentication context cannot be found.");
throw new InvalidOperationException(SR.GetResourceString(SR.ID1006));
context.Principal ??= notification.Principal;

90
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<ExtractIntrospectionRequestContext>' ")
.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<ApplyIntrospectionResponseContext>' ")
.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<ValidateIntrospectionRequestContext>(
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.

94
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<ExtractRevocationRequestContext>' ")
.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<ApplyRevocationResponseContext>' ")
.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<ValidateRevocationRequestContext>(
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;
}

37
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<ExtractLogoutRequestContext>' ")
.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<HandleLogoutRequestContext>' ")
.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<ApplyRevocationResponseContext>' ")
.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;
}

18
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<ExtractUserinfoRequestContext>' ")
.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<ApplyUserinfoResponseContext>' ")
.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<ValidateUserinfoRequestContext>(
typeof(ValidateUserinfoRequestContext).FullName) ??
throw new InvalidOperationException("The authentication context cannot be found.");
throw new InvalidOperationException(SR.GetResourceString(SR.ID1006));
context.Principal ??= notification.Principal;

466
src/OpenIddict.Server/OpenIddictServerHandlers.cs

File diff suppressed because it is too large

5
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)

7
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
};

6
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
/// </summary>
public Uri Issuer { get; set; }
/// <summary>
/// Gets or sets the localizer associated with the current request.
/// </summary>
public IStringLocalizer Localizer { get; set; }
/// <summary>
/// Gets or sets the logger associated with the current request.
/// </summary>

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

Loading…
Cancel
Save