public async Task StopsRevalidatingAfterDisposal()
        {
            // Arrange
            using var provider = new TestRevalidatingServerAuthenticationStateProvider(
                      TimeSpan.FromMilliseconds(50));
            provider.SetAuthenticationState(CreateAuthenticationStateTask("test user"));
            provider.NextValidationResult = Task.FromResult(true);

            // Act
            ((IDisposable)provider).Dispose();
            await Task.Delay(200);

            // Assert
            Assert.Empty(provider.RevalidationCallLog);
        }
        public void AcceptsAndReturnsAuthStateFromHost()
        {
            // Arrange
            using var provider = new TestRevalidatingServerAuthenticationStateProvider(TimeSpan.MaxValue);

            // Act/Assert: Host can supply a value
            var hostAuthStateTask = (new TaskCompletionSource <AuthenticationState>()).Task;

            provider.SetAuthenticationState(hostAuthStateTask);
            Assert.Same(hostAuthStateTask, provider.GetAuthenticationStateAsync());

            // Act/Assert: Host can supply a changed value
            var hostAuthStateTask2 = (new TaskCompletionSource <AuthenticationState>()).Task;

            provider.SetAuthenticationState(hostAuthStateTask2);
            Assert.Same(hostAuthStateTask2, provider.GetAuthenticationStateAsync());
        }
        public async Task IfValidateAuthenticationStateAsyncReturnsTrue_ContinuesRevalidating()
        {
            // Arrange
            using var provider = new TestRevalidatingServerAuthenticationStateProvider(
                      TimeSpan.FromMilliseconds(50));
            provider.SetAuthenticationState(CreateAuthenticationStateTask("test user"));
            provider.NextValidationResult = Task.FromResult(true);
            var didNotifyAuthenticationStateChanged = false;

            provider.AuthenticationStateChanged += _ => { didNotifyAuthenticationStateChanged = true; };

            // Act
            for (var i = 0; i < 10; i++)
            {
                await provider.NextValidateAuthenticationStateAsyncCall;
            }

            // Assert
            Assert.Equal(10, provider.RevalidationCallLog.Count);
            Assert.False(didNotifyAuthenticationStateChanged);
            Assert.Equal("test user", (await provider.GetAuthenticationStateAsync()).User.Identity.Name);
        }
        public async Task SuppliesCancellationTokenThatSignalsWhenRevalidationLoopIsBeingDiscarded()
        {
            // Arrange
            var validationTcs = new TaskCompletionSource <bool>();
            var authenticationStateChangedCount = 0;

            using var provider = new TestRevalidatingServerAuthenticationStateProvider(
                      TimeSpan.FromMilliseconds(50));
            provider.NextValidationResult = validationTcs.Task;
            provider.SetAuthenticationState(CreateAuthenticationStateTask("test user"));
            provider.AuthenticationStateChanged += _ => { authenticationStateChangedCount++; };

            // Act/Assert 1: token isn't cancelled initially
            await provider.NextValidateAuthenticationStateAsyncCall;
            var firstRevalidationCall = provider.RevalidationCallLog.Single();

            Assert.False(firstRevalidationCall.CancellationToken.IsCancellationRequested);
            Assert.Equal(0, authenticationStateChangedCount);

            // Have the task throw a TCE to show this doesn't get treated as a failure
            firstRevalidationCall.CancellationToken.Register(() => validationTcs.TrySetCanceled(firstRevalidationCall.CancellationToken));

            // Act/Assert 2: token is cancelled when the loop is superseded
            provider.NextValidationResult = Task.FromResult(true);
            provider.SetAuthenticationState(CreateAuthenticationStateTask("different user"));
            Assert.True(firstRevalidationCall.CancellationToken.IsCancellationRequested);

            // Since we asked for that operation to be cancelled, we don't treat it as a failure and
            // don't force a logout
            Assert.Equal(1, authenticationStateChangedCount);
            Assert.Equal("different user", (await provider.GetAuthenticationStateAsync()).User.Identity.Name);

            // Subsequent revalidation can complete successfully
            await provider.NextValidateAuthenticationStateAsyncCall;

            Assert.Collection(provider.RevalidationCallLog.Skip(1),
                              call => Assert.Equal("different user", call.AuthenticationState.User.Identity.Name));
        }
示例#5
0
    public async Task IfValidateAuthenticationStateAsyncReturnsUnrelatedCancelledTask_TreatAsFailure()
    {
        // Arrange
        var validationTcs     = new TaskCompletionSource <bool>();
        var incrementExecuted = new TaskCompletionSource <bool>();
        var authenticationStateChangedCount = 0;

        using var provider = new TestRevalidatingServerAuthenticationStateProvider(
                  TimeSpan.FromMilliseconds(50));
        provider.NextValidationResult = validationTcs.Task;
        provider.SetAuthenticationState(CreateAuthenticationStateTask("test user"));
        provider.AuthenticationStateChanged += _ =>
        {
            authenticationStateChangedCount++;
            incrementExecuted.TrySetResult(true);
        };

        // Be waiting for the first ValidateAuthenticationStateAsync to complete
        await provider.NextValidateAuthenticationStateAsyncCall;
        var firstRevalidationCall = provider.RevalidationCallLog.Single();

        Assert.Equal(0, authenticationStateChangedCount);

        // Act: ValidateAuthenticationStateAsync returns canceled task, but the cancellation
        // is unrelated to the CT we supplied
        validationTcs.TrySetCanceled(new CancellationTokenSource().Token);

        // Assert: Since we didn't ask for that operation to be canceled, this is treated as
        // a failure to validate, so we force a logout
        await incrementExecuted.Task.TimeoutAfter(TimeSpan.FromSeconds(5));

        Assert.Equal(1, authenticationStateChangedCount);
        var newAuthState = await provider.GetAuthenticationStateAsync();

        Assert.False(newAuthState.User.Identity.IsAuthenticated);
        Assert.Null(newAuthState.User.Identity.Name);
    }
        public async Task IfValidateAuthenticationStateAsyncThrows_ForcesSignOut()
        {
            // Arrange
            using var provider = new TestRevalidatingServerAuthenticationStateProvider(
                      TimeSpan.FromMilliseconds(50));
            provider.SetAuthenticationState(CreateAuthenticationStateTask("test user"));
            provider.NextValidationResult = Task.FromException <bool>(new InvalidTimeZoneException());

            var newAuthStateNotificationTcs = new TaskCompletionSource <Task <AuthenticationState> >();

            provider.AuthenticationStateChanged += newStateTask => newAuthStateNotificationTcs.SetResult(newStateTask);

            // Act
            var newAuthStateTask = await newAuthStateNotificationTcs.Task;
            var newAuthState     = await newAuthStateTask;

            // Assert
            Assert.False(newAuthState.User.Identity.IsAuthenticated);

            // Assert: no longer revalidates
            await Task.Delay(200);

            Assert.Single(provider.RevalidationCallLog);
        }