public async Task Authenticated_request_from_upstream_should_trigger_authenticated_request_to_proper_downstream_when_multiple_clients_registered()
        {
            var tokenEndpointA = TokenEndpointHandler.ValidBearerToken("downstream-token-a", TimeSpan.MaxValue);
            var downstreamApiA = new DownstreamApiHandler();
            var tokenEndpointB = TokenEndpointHandler.ValidBearerToken("downstream-token-b", TimeSpan.MaxValue);
            var downstreamApiB = new DownstreamApiHandler();
            var client         = WebHostFactory.CreateClient(
                services =>
            {
                services.AddHttpClient("api-a-authority").AddHttpMessageHandler(() => tokenEndpointA);
                services.AddHttpClient("api-b-authority").AddHttpMessageHandler(() => tokenEndpointB);
            },
                false,
                new DownstreamApi("downstream-a", downstreamApiA, b => b.AddOidcTokenDelegation(o =>
            {
                _options(o);
                o.Scope = "downstream-api-a";
                o.AuthorityHttpClientName = "api-a-authority";
            })),
                new DownstreamApi("downstream-b", downstreamApiB, b => b.AddOidcTokenDelegation(o =>
            {
                _options(o);
                o.Scope = "downstream-api-b";
                o.AuthorityHttpClientName = "api-b-authority";
            })));

            client.SetBearerToken("upstream-token");

            await client.GetAsync("https://downstream-b");

            Check.That(downstreamApiA.LastRequestToken).IsNull();
            Check.That(downstreamApiB.LastRequestToken).IsEqualTo("downstream-token-b");
        }
        public async Task Successful_token_request_should_trigger_authenticated_request_to_proper_api_when_multiple_clients_registered()
        {
            var tokenEndpointA = TokenEndpointHandler.ValidBearerToken("api-token-a", TimeSpan.MaxValue);
            var apiA           = new DownstreamApiHandler();
            var tokenEndpointB = TokenEndpointHandler.ValidBearerToken("api-token-b", TimeSpan.MaxValue);
            var apiB           = new DownstreamApiHandler();
            var client         = HostFactory.CreateClient(
                "api-b",
                services =>
            {
                services.AddHttpClient("api-a-authority").AddHttpMessageHandler(() => tokenEndpointA);
                services.AddHttpClient("api-b-authority").AddHttpMessageHandler(() => tokenEndpointB);
            },
                false,
                new DownstreamApi("api-a", apiA, b => b.AddOidcRefreshToken(o =>
            {
                _options(o);
                o.AuthorityHttpClientName = "api-a-authority";
            })),
                new DownstreamApi("api-b", apiB, b => b.AddOidcRefreshToken(o =>
            {
                _options(o);
                o.AuthorityHttpClientName = "api-b-authority";
            })));

            await client.GetAsync("https://api-b");

            Check.That(apiA.LastRequestToken).IsNull();
            Check.That(apiB.LastRequestToken).IsEqualTo("api-token-b");
        }
        public async Task Unauthenticated_request_from_upstream_should_not_trigger_delegation()
        {
            var downstreamApi = new DownstreamApiHandler();
            var client        = WebHostFactory.CreateClient(
                b => b.AddOidcTokenDelegation(_options),
                downstreamApi: downstreamApi);

            await client.GetAsync("https://default");

            Check.That(downstreamApi.LastRequestToken).IsNull();
        }
        public async Task Unauthenticated_request_from_upstream_should_not_be_passed_through()
        {
            var downstreamApi = new DownstreamApiHandler();
            var client        = WebHostFactory.CreateClient(
                b => b.AddAccessTokenPassThrough(),
                downstreamApi: downstreamApi);

            await client.GetAsync("https://default");

            Check.That(downstreamApi.LastRequestToken).IsNull();
        }
        public async Task Token_request_error_should_trigger_unauthenticated_request_to_api()
        {
            var api    = new DownstreamApiHandler();
            var client = HostFactory.CreateClient(
                b => b.AddOidcRefreshToken(_options),
                TokenEndpointHandler.OidcProtocolError("invalid_grant"),
                api: api);

            await client.GetAsync("https://default");

            Check.That(api.LastRequestToken).IsNull();
        }
        public async Task Token_delegation_error_should_trigger_unauthenticated_request_to_downstream()
        {
            var downstreamApi = new DownstreamApiHandler();
            var client        = WebHostFactory.CreateClient(
                b => b.AddOidcTokenDelegation(_options),
                TokenEndpointHandler.OidcProtocolError("invalid_grant"),
                downstreamApi: downstreamApi);

            client.SetBearerToken("1234");

            await client.GetAsync("https://default");

            Check.That(downstreamApi.LastRequestToken).IsNull();
        }
        public async Task Authenticated_request_from_upstream_should_be_passed_through()
        {
            const string accessToken = "1234";

            var downstreamApi = new DownstreamApiHandler();
            var client        = WebHostFactory.CreateClient(
                b => b.AddAccessTokenPassThrough(),
                downstreamApi: downstreamApi);

            client.SetBearerToken(accessToken);

            await client.GetAsync("https://default");

            Check.That(downstreamApi.LastRequestToken).IsEqualTo(accessToken);
        }
        public async Task Successful_token_request_should_trigger_authenticated_request_to_api()
        {
            var tokenEndpoint = TokenEndpointHandler.ValidBearerToken("access-token", TimeSpan.MaxValue);
            var api           = new DownstreamApiHandler();
            var client        = HostFactory.CreateClient(
                b => b.AddOidcRefreshToken(_options),
                tokenEndpoint,
                api: api);

            await client.GetAsync("https://default");

            Check.That(tokenEndpoint.LastRequestClientId).IsEqualTo(ClientId);
            Check.That(tokenEndpoint.LastRequestClientSecret).IsEqualTo(ClientSecret);
            Check.That(tokenEndpoint.LastRequestRefreshToken).IsEqualTo(RefreshToken);
            Check.That(api.LastRequestToken).IsEqualTo("access-token");
        }
        public async Task Authenticated_request_from_upstream_should_trigger_authenticated_request_to_downstream()
        {
            var tokenEndpoint = TokenEndpointHandler.ValidBearerToken("downstream-token", TimeSpan.MaxValue);
            var downstreamApi = new DownstreamApiHandler();
            var client        = WebHostFactory.CreateClient(
                b => b.AddOidcTokenDelegation(_options),
                tokenEndpoint,
                downstreamApi: downstreamApi);

            client.SetBearerToken("upstream-token");

            await client.GetAsync("https://default");

            Check.That(tokenEndpoint.LastRequestToken).IsEqualTo("upstream-token");
            Check.That(downstreamApi.LastRequestToken).IsEqualTo("downstream-token");
        }