public async Task CanGetToken()
        {
            // GIVEN a token provider initialised with required secrets
            var provider = new ClientCredentialsFlowTokenProvider(ApiConfig.Value);

            // WHEN the token is requested
            var token = await provider.GetAuthenticationTokenAsync();

            // THEN it is populated
            Assert.That(token, Is.Not.Empty);
        }
        public async Task CanRefreshWithoutToken()
        {
            // GIVEN a token from the TokenProvider that DOES NOT contain a refresh token
            var provider = new ClientCredentialsFlowTokenProvider(ApiConfig.Value);
            var _        = await provider.GetAuthenticationTokenAsync();

            var firstTokenDetails = provider.GetLastToken();

            Assert.That(firstTokenDetails.RefreshToken, Is.Null, "refresh_token was returned so unable to verify refresh behaviour with a token.  This requires the userid defined in secrets.json to be set to NOT 'allow offline access' in Okta");

            // WHEN we pretend to delay until the original token has expired (for expediency update the expires_on on the token)
            provider.ExpireToken();

            Assert.That(DateTimeOffset.UtcNow, Is.GreaterThan(firstTokenDetails.ExpiresOn));
            var refreshedToken = await provider.GetAuthenticationTokenAsync();

            // THEN it should be populated, and the ExpiresOn should be in the future
            Assert.That(refreshedToken, Is.Not.Empty);
            Assert.That(provider.GetLastToken().ExpiresOn, Is.GreaterThan(DateTimeOffset.UtcNow));
        }
        public async Task CanGetNewTokenWhenRefreshTokenExpired()
        {
            var provider = new ClientCredentialsFlowTokenProvider(ApiConfig.Value);
            var _        = await provider.GetAuthenticationTokenAsync();

            var firstTokenDetails = provider.GetLastToken();

            Assert.That(firstTokenDetails.RefreshToken, Is.Not.Null.And.Not.Empty, "refresh_token not returned so unable to verify refresh behaviour.");

            Console.WriteLine($"Token expiring at {firstTokenDetails.ExpiresOn:o}");

            // WHEN we pretend to delay until both...
            // (1) the original token has expired (for expediency update the expires_on on the token)
            provider.ExpireToken();
            // (2) the refresh token has expired (for expediency update the refresh_token to an invalid value that will not be found)
            provider.GetLastToken().RefreshToken = "InvalidRefreshToken";
            Assert.That(DateTimeOffset.UtcNow, Is.GreaterThan(firstTokenDetails.ExpiresOn));
            var refreshedToken = await provider.GetAuthenticationTokenAsync();

            // THEN it should be populated, and the ExpiresOn should be in the future
            Assert.That(refreshedToken, Is.Not.Empty);
            Assert.That(provider.GetLastToken().ExpiresOn, Is.GreaterThan(DateTimeOffset.UtcNow));
        }