diff --git a/src/OpenIddict/OpenIddictProvider.Authentication.cs b/src/OpenIddict/OpenIddictProvider.Authentication.cs index cdedc5a1..e3ab1b60 100644 --- a/src/OpenIddict/OpenIddictProvider.Authentication.cs +++ b/src/OpenIddict/OpenIddictProvider.Authentication.cs @@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Logging; +using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Linq; @@ -306,9 +307,10 @@ namespace OpenIddict // to flow across requests and internal/external authentication/registration workflows. if (options.EnableRequestCaching && string.IsNullOrEmpty(context.Request.RequestId)) { - // Generate a request identifier. Note: using a crypto-secure - // random number generator is not necessary in this case. - context.Request.RequestId = Guid.NewGuid().ToString(); + // Generate a 256-bit request identifier using a crypto-secure random number generator. + var bytes = new byte[256 / 8]; + options.RandomNumberGenerator.GetBytes(bytes); + context.Request.RequestId = Base64UrlEncoder.Encode(bytes); // Store the serialized authorization request parameters in the distributed cache. var stream = new MemoryStream(); diff --git a/src/OpenIddict/OpenIddictProvider.Session.cs b/src/OpenIddict/OpenIddictProvider.Session.cs index a8a0ab3b..09e94030 100644 --- a/src/OpenIddict/OpenIddictProvider.Session.cs +++ b/src/OpenIddict/OpenIddictProvider.Session.cs @@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Logging; +using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Linq; @@ -133,9 +134,10 @@ namespace OpenIddict // to make it easier to flow across requests and internal/external logout workflows. if (options.EnableRequestCaching && string.IsNullOrEmpty(context.Request.RequestId)) { - // Generate a request identifier. Note: using a crypto-secure - // random number generator is not necessary in this case. - context.Request.RequestId = Guid.NewGuid().ToString(); + // Generate a 256-bit request identifier using a crypto-secure random number generator. + var bytes = new byte[256 / 8]; + options.RandomNumberGenerator.GetBytes(bytes); + context.Request.RequestId = Base64UrlEncoder.Encode(bytes); // Store the serialized logout request parameters in the distributed cache. var stream = new MemoryStream(); diff --git a/test/OpenIddict.Tests/OpenIddictProviderTests.Authentication.cs b/test/OpenIddict.Tests/OpenIddictProviderTests.Authentication.cs index 22098396..b1a43e75 100644 --- a/test/OpenIddict.Tests/OpenIddictProviderTests.Authentication.cs +++ b/test/OpenIddict.Tests/OpenIddictProviderTests.Authentication.cs @@ -5,6 +5,7 @@ */ using System.IO; +using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using AspNet.Security.OpenIdConnect.Client; @@ -435,6 +436,7 @@ namespace OpenIddict.Tests { // Arrange var cache = new Mock(); + var generator = new Mock(); var server = CreateAuthorizationServer(builder => { @@ -455,6 +457,8 @@ namespace OpenIddict.Tests builder.Services.AddSingleton(cache.Object); builder.EnableRequestCaching(); + + builder.Configure(options => options.RandomNumberGenerator = generator.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); @@ -478,6 +482,8 @@ namespace OpenIddict.Tests It.IsAny(), It.IsAny(), It.IsAny()), Times.Once()); + + generator.Verify(mock => mock.GetBytes(It.Is(bytes => bytes.Length == 256 / 8)), Times.Once()); } [Theory] diff --git a/test/OpenIddict.Tests/OpenIddictProviderTests.Session.cs b/test/OpenIddict.Tests/OpenIddictProviderTests.Session.cs index 2b62007a..b121ed41 100644 --- a/test/OpenIddict.Tests/OpenIddictProviderTests.Session.cs +++ b/test/OpenIddict.Tests/OpenIddictProviderTests.Session.cs @@ -4,6 +4,7 @@ * the license and the contributors participating to this project. */ +using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using AspNet.Security.OpenIdConnect.Client; @@ -119,6 +120,7 @@ namespace OpenIddict.Tests { // Arrange var cache = new Mock(); + var generator = new Mock(); var server = CreateAuthorizationServer(builder => { @@ -131,6 +133,8 @@ namespace OpenIddict.Tests builder.Services.AddSingleton(cache.Object); builder.EnableRequestCaching(); + + builder.Configure(options => options.RandomNumberGenerator = generator.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); @@ -152,6 +156,8 @@ namespace OpenIddict.Tests It.IsAny(), It.IsAny(), It.IsAny()), Times.Once()); + + generator.Verify(mock => mock.GetBytes(It.Is(bytes => bytes.Length == 256 / 8)), Times.Once()); } [Fact]