public async Task ProcessAsync_when_user_code_collision_expect_retry() { var creationTime = DateTime.UtcNow; clock.UtcNowFunc = () => creationTime; testResult.ValidatedRequest.Client.UserCodeType = FakeUserCodeGenerator.UserCodeTypeValue; await deviceFlowCodeService.StoreDeviceAuthorizationAsync(FakeUserCodeGenerator.TestCollisionUserCode, new DeviceCode()); var response = await generator.ProcessAsync(testResult, TestBaseUrl); response.UserCode.Should().Be(FakeUserCodeGenerator.TestUniqueUserCode); }
/// <summary> /// Processes the response. /// </summary> /// <param name="validationResult">The validation result.</param> /// <param name="baseUrl">The base URL.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">validationResult or Client</exception> /// <exception cref="ArgumentException">Value cannot be null or whitespace. - baseUrl</exception> public virtual async Task <DeviceAuthorizationResponse> ProcessAsync(DeviceAuthorizationRequestValidationResult validationResult, string baseUrl) { if (validationResult == null) { throw new ArgumentNullException(nameof(validationResult)); } if (validationResult.ValidatedRequest.Client == null) { throw new ArgumentNullException(nameof(validationResult.ValidatedRequest.Client)); } if (string.IsNullOrWhiteSpace(baseUrl)) { throw new ArgumentException("Value cannot be null or whitespace.", nameof(baseUrl)); } Logger.LogTrace("Creating response for device authorization request"); var response = new DeviceAuthorizationResponse(); // generate user_code var userCodeGenerator = await UserCodeService.GetGenerator( validationResult.ValidatedRequest.Client.UserCodeType ?? Options.DeviceFlow.DefaultUserCodeType); var retryCount = 0; while (retryCount < userCodeGenerator.RetryLimit) { var userCode = await userCodeGenerator.GenerateAsync(); var deviceCode = await DeviceFlowCodeService.FindByUserCodeAsync(userCode); if (deviceCode == null) { response.UserCode = userCode; break; } retryCount++; } if (response.UserCode == null) { throw new InvalidOperationException("Unable to create unique device flow user code"); } // generate verification URIs response.VerificationUri = Options.UserInteraction.DeviceVerificationUrl; if (response.VerificationUri.IsLocalUrl()) { // if url is relative, parse absolute URL response.VerificationUri = baseUrl.RemoveTrailingSlash() + Options.UserInteraction.DeviceVerificationUrl; } if (!string.IsNullOrWhiteSpace(Options.UserInteraction.DeviceVerificationUserCodeParameter)) { response.VerificationUriComplete = $"{response.VerificationUri}?{Options.UserInteraction.DeviceVerificationUserCodeParameter}={response.UserCode}"; } // expiration response.DeviceCodeLifetime = validationResult.ValidatedRequest.Client.DeviceCodeLifetime; // interval response.Interval = Options.DeviceFlow.Interval; // store device request (device code & user code) response.DeviceCode = await DeviceFlowCodeService.StoreDeviceAuthorizationAsync(response.UserCode, new DeviceCode { ClientId = validationResult.ValidatedRequest.Client.ClientId, IsOpenId = validationResult.ValidatedRequest.IsOpenIdRequest, Lifetime = response.DeviceCodeLifetime, CreationTime = Clock.UtcNow.UtcDateTime, RequestedScopes = validationResult.ValidatedRequest.ValidatedResources.ScopeValues }); return(response); }