Browse Source

Update the ConvertReferenceUserCode handler to generate a new user code when a collision is detected

pull/1077/head
Kévin Chalet 6 years ago
parent
commit
7d1664e518
  1. 46
      src/OpenIddict.Server/OpenIddictServerHandlers.cs

46
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -3957,20 +3957,6 @@ namespace OpenIddict.Server
// only compound of 12 digits, generated using a crypto-secure random number generator.
// In this case, the resulting user code is estimated to have at most ~40 bits of entropy.
var data = new byte[12];
#if SUPPORTS_STATIC_RANDOM_NUMBER_GENERATOR_METHODS
RandomNumberGenerator.Fill(data);
#else
using var generator = RandomNumberGenerator.Create();
generator.GetBytes(data);
#endif
var builder = new StringBuilder(data.Length);
for (var index = 0; index < data.Length; index += 4)
{
builder.AppendFormat(CultureInfo.InvariantCulture, "{0:D4}", BitConverter.ToUInt32(data, index) % 10000);
}
var descriptor = new OpenIddictTokenDescriptor();
await _tokenManager.PopulateAsync(descriptor, token);
@ -3978,13 +3964,43 @@ namespace OpenIddict.Server
// and replace the returned token by the reference identifier.
descriptor.Payload = context.Response.UserCode;
descriptor.Principal = principal;
descriptor.ReferenceId = builder.ToString();
descriptor.ReferenceId = await GenerateReferenceIdentifierAsync(_tokenManager);
await _tokenManager.UpdateAsync(token, descriptor);
context.Response.UserCode = descriptor.ReferenceId;
context.Logger.LogTrace(SR.GetResourceString(SR.ID7027), identifier, descriptor.ReferenceId);
static async ValueTask<string> GenerateReferenceIdentifierAsync(IOpenIddictTokenManager manager)
{
string token;
do
{
var data = new byte[12];
#if SUPPORTS_STATIC_RANDOM_NUMBER_GENERATOR_METHODS
RandomNumberGenerator.Fill(data);
#else
using var generator = RandomNumberGenerator.Create();
generator.GetBytes(data);
#endif
var builder = new StringBuilder(data.Length);
for (var index = 0; index < data.Length; index += 4)
{
builder.AppendFormat(CultureInfo.InvariantCulture, "{0:D4}", BitConverter.ToUInt32(data, index) % 10000);
}
token = builder.ToString();
}
// User codes are relatively short. To help reduce the risks of collisions with
// existing entries, a database check is performed here before updating the entry.
while (await manager.FindByReferenceIdAsync(token) != null);
return token;
}
}
}

Loading…
Cancel
Save