public ServiceAgentSettings ReadConfig(IConfigurationRoot config)
        {
            var serviceAgentSettings = new ServiceAgentSettings();

            var sections = config.GetChildren().ToDictionary(s => s.Key);

            if (sections.ContainsKey("Global"))
            {
                var globalSection = sections["Global"];

                globalSection.Bind(serviceAgentSettings);
                sections.Remove("Global");
            }

            foreach (var item in sections)
            {
                try
                {
                    var settings = new ServiceSettings();

                    item.Value.Bind(settings);

                    serviceAgentSettings.Services.Add(item.Key, settings);
                }
                catch (Exception)
                {
                }
            }

            return serviceAgentSettings;
        }
        public void Defaults()
        {
            var settings = new ServiceSettings();

            Assert.Equal(AuthScheme.None, settings.AuthScheme);
            Assert.Equal(HttpSchema.Https, settings.Scheme);
            Assert.Equal("api", settings.Path);
        }
 private void SetOAuthClientCredentialsAuthHeader(HttpClient client, ServiceSettings settings)
 {
     
     var tokenHelper = _serviceProvider.GetService<ITokenHelper>();
     if (tokenHelper == null) throw new NullReferenceException($"{nameof(ITokenHelper)} cannot be null.");
     var token = tokenHelper.ReadOrRetrieveToken(settings).Result.access_token;
     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(AuthScheme.Bearer, token);
 }
        private void SetBasicAuthHeader(HttpClient client, ServiceSettings settings)
        {
            if (IsDevelopmentEnvironment() == false && settings.Scheme != HttpSchema.Https)
                throw new ServiceAgentException($"Failed to set Basic Authentication header on service agent for host: '{settings.Host}', the actual scheme is '{settings.Scheme}' and should be 'https'!");

            var headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{settings.BasicAuthUserName}:{settings.BasicAuthPassword}"));
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(AuthScheme.Basic, headerValue);
        }
        public void ThrowExceptionWhenNonHttpsSchemeUsedWithBasicAuthentication()
        {
            var serviceAgentSettings = new ServiceAgentSettings { };
            var settings = new ServiceSettings { AuthScheme = AuthScheme.Basic, BasicAuthUserName = "******", BasicAuthPassword = "******", Scheme = HttpSchema.Http, Host = "test.be", Path = "api" };
            var clientFactory = new HttpClientFactory(CreateServiceProvider(settings));

            Assert.Throws<ServiceAgentException>(() => clientFactory.CreateClient(serviceAgentSettings, settings));
        }
        public void ConstuctUrlWithoutPath()
        {
            var settings = new ServiceSettings
            {
                Scheme = HttpSchema.Http,
                Host = "test.com",
                Path = ""
            };

            Assert.Equal("http://test.com/", settings.Url);
        }
        public void CreateClientWithBasicAuthentication()
        {
            var serviceAgentSettings = new ServiceAgentSettings { };
            var settings = new ServiceSettings { AuthScheme = AuthScheme.Basic, BasicAuthUserName = "******", BasicAuthPassword = "******", Host = "test.be", Path = "api" };
            var clientFactory = new HttpClientFactory(CreateServiceProvider(settings));

            var client = clientFactory.CreateClient(serviceAgentSettings, settings);

            Assert.NotNull(client);
            Assert.Equal(AuthScheme.Basic, client.DefaultRequestHeaders.Authorization.Scheme);
            Assert.Equal("QWxhZGRpbjpPcGVuU2VzYW1l", client.DefaultRequestHeaders.Authorization.Parameter);
        }
        public void CreateClientWithOAuthClientCredentials()
        {
            var serviceAgentSettings = new ServiceAgentSettings { };
            var settings = new ServiceSettings { AuthScheme = AuthScheme.OAuthClientCredentials, OAuthClientId = "clientId", OAuthClientSecret = "clientSecret", Host = "test.be", Path = "api" };
            var clientFactory = new HttpClientFactory(CreateServiceProvider(settings));

            var client = clientFactory.CreateClient(serviceAgentSettings, settings);

            Assert.NotNull(client);
            Assert.Equal(AuthScheme.Bearer, client.DefaultRequestHeaders.Authorization.Scheme);
            Assert.Equal("AccessToken", client.DefaultRequestHeaders.Authorization.Parameter);
        }
        public void ConstuctUrl()
        {
            var settings = new ServiceSettings
            {
                Scheme = HttpSchema.Http,
                Host = "test.com",
                Port = "80",
                Path = "api"
            };

            Assert.Equal("http://test.com:80/api/", settings.Url);
        }
        public void CreateDefaultClient()
        {
            var serviceAgentSettings = new ServiceAgentSettings();
            var settings = new ServiceSettings { Scheme = HttpSchema.Http, Host = "test.be", Path = "api" };
            var clientFactory = new HttpClientFactory(CreateServiceProvider(settings));

            var client = clientFactory.CreateClient(serviceAgentSettings, settings);

            Assert.NotNull(client);
            Assert.Equal("http://test.be/api/", client.BaseAddress.AbsoluteUri);
            Assert.Equal("application/json", client.DefaultRequestHeaders.Accept.Single().MediaType);
            Assert.Null(client.DefaultRequestHeaders.Authorization);
        }
        public TokenHelperTests()
        {
            _startup = new TestStartup();

            _cacheKey = "clientIdclientSecretscopehttp://localhost/api/oauth/token";
            _settings = new ServiceSettings
            {
                Scheme = HttpSchema.Http,
                Host = "localhost",
                Path = "api",
                OAuthPathAddition = "oauth/token",
                OAuthClientId = "clientId",
                OAuthClientSecret = "clientSecret",
                OAuthScope = "scope"
            };
        }
        public async Task<TokenReply> ReadOrRetrieveToken(ServiceSettings options)
        {
            TokenReply tokenReplyResult = null;
            var cacheKey = options.OAuthClientId + options.OAuthClientSecret + options.OAuthScope + options.OAuthTokenEndpoint;

            tokenReplyResult = _cache.Get<TokenReply>(cacheKey);

            if (tokenReplyResult == null)
            {
                tokenReplyResult = await RetrieveToken(options.OAuthClientId, options.OAuthClientSecret, options.OAuthScope, options.OAuthTokenEndpoint);

                var cacheExpiration = tokenReplyResult.expires_in - 60;
                cacheExpiration = cacheExpiration > 0 ? cacheExpiration : 0;

                if (cacheExpiration > 0)
                {
                    _cache.Set(cacheKey, tokenReplyResult, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(cacheExpiration) });
                }
            }

            return tokenReplyResult;
        }
        public HttpClient CreateClient(ServiceAgentSettings serviceAgentSettings, ServiceSettings settings)
        {
            var client = new HttpClient
            {
                BaseAddress = new Uri(settings.Url)
            };

            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            switch (settings.AuthScheme)
            {
                case AuthScheme.OAuthClientCredentials:
                    SetOAuthClientCredentialsAuthHeader(client, settings);
                    break;
                case AuthScheme.Bearer:
                    SetBearerAuthHeader(client);
                    break;
                case AuthScheme.Basic:
                    SetBasicAuthHeader(client, settings);
                    break;
                default:
                    break;
            }

            if (settings.Headers != null)
            {
                foreach (var header in settings?.Headers)
                {
                    client.DefaultRequestHeaders.Add(header.Key, header.Value);
                }
            }

            if (AfterClientCreated != null)
                AfterClientCreated(_serviceProvider, client);

            return client;
        }
        public void AfterClientCreatedGetsRaised()
        {
            var serviceAgentSettings = new ServiceAgentSettings();
            var settings = new ServiceSettings { AuthScheme = AuthScheme.Bearer, Scheme = HttpSchema.Http, Host = "test.be", Path = "api" };
            var clientFactory = new HttpClientFactory(CreateServiceProvider(settings));
            HttpClient passedClient = null;
            clientFactory.AfterClientCreated += (sp, c) => passedClient = c;

            clientFactory.CreateClient(serviceAgentSettings, settings);

            Assert.NotNull(passedClient);
        }
        public void DoesntThrowExceptionWhenNonHttpsSchemeUsedWithBasicAuthenticationInDevelopmentEnvironment()
        {
            var serviceAgentSettings = new ServiceAgentSettings { };
            var settings = new ServiceSettings { AuthScheme = AuthScheme.Basic, BasicAuthUserName = "******", BasicAuthPassword = "******", Scheme = HttpSchema.Http, Host = "test.be", Path = "api" };
            var clientFactory = new HttpClientFactory(CreateServiceProvider(settings, isDevelopmentEnvironment: true));

            clientFactory.CreateClient(serviceAgentSettings, settings);
        }
        public void CreateClientWithHeaders()
        {
            var serviceAgentSettings = new ServiceAgentSettings();
            var headers = new Dictionary<string, string>()
            {
                { "api-key", "localapikey" },
                 { "X-Custom-Header", "customvalue" },
            };
            var settings = new ServiceSettings { Headers = headers, Scheme = HttpSchema.Http, Host = "test.be", Path = "api" };
            var clientFactory = new HttpClientFactory(CreateServiceProvider(settings));

            var client = clientFactory.CreateClient(serviceAgentSettings, settings);

            Assert.NotNull(client);
            Assert.Equal("localapikey", client.DefaultRequestHeaders.First(h => h.Key == "api-key").Value.First());
            Assert.Equal("customvalue", client.DefaultRequestHeaders.First(h => h.Key == "X-Custom-Header").Value.First());
        }
        private IServiceProvider CreateServiceProvider(ServiceSettings settings, bool isDevelopmentEnvironment = false)
        {
            var serviceProviderMock = new Mock<IServiceProvider>();

            if (settings != null)
                serviceProviderMock.Setup(p => p.GetService(typeof(IOptions<ServiceSettings>))).Returns(Options.Create(settings));

            var authContextMock = new Mock<IAuthContext>();
            authContextMock.Setup(c => c.UserToken).Returns("TokenValue");

            serviceProviderMock.Setup(p => p.GetService(typeof(IAuthContext))).Returns(authContextMock.Object);

            var mockTokenHelper = new Mock<ITokenHelper>();
            mockTokenHelper.Setup(h => h.ReadOrRetrieveToken(settings))
                .ReturnsAsync(new TokenReply { access_token = "AccessToken", expires_in = 7200 });

            serviceProviderMock.Setup(p => p.GetService(typeof(ITokenHelper))).Returns(mockTokenHelper.Object);

            var mockHostingEnvironment = new Mock<IHostingEnvironment>();
            mockHostingEnvironment.Setup(h => h.EnvironmentName)
                .Returns(isDevelopmentEnvironment ? "Development" : "");

            serviceProviderMock.Setup(p => p.GetService(typeof(IHostingEnvironment))).Returns(mockHostingEnvironment.Object);

            return serviceProviderMock.Object;
        }