private static void ConfigureDynamics(IServiceCollection services, ProjectConfiguration project, ProjectResource projectResource, Serilog.ILogger logger)
        {
            Debug.Assert(services != null, "Required ServiceCollection is null");
            Debug.Assert(project != null, "Required ProjectConfiguration is null");
            Debug.Assert(projectResource != null, "Required ProjectResource is null");
            Debug.Assert(projectResource.Type == ProjectType.Dynamics, "Project type must be Dynamics");

            // the projectResourceKey convention is repeated also in OAuthClientFactory which gets the HttpClient using the same convention,
            //
            // {Id}-dynamics-authorization
            //
            string projectResourceKey = project.Id + "-dynamics";

            // add authorization HttpClient
            services.AddHttpClient(projectResourceKey + "-authorization", configure => configure.BaseAddress = projectResource.AuthorizationUri)
            ;

            // add odata HttpClient
            // note: I do not like this IoC anti-pattern where we are using the service locator directly, however,
            //       there are many named dependencies. There may be an opportunity to address this in the future

            var builder = services.AddHttpClient(projectResourceKey, configure =>
            {
                configure.BaseAddress = projectResource.Resource;
            })
                          .AddHttpMessageHandler(serviceProvider =>
            {
                // build the token service that talk to the OAuth endpoint
                IOAuthClientFactory oauthClientFactory = serviceProvider.GetRequiredService <IOAuthClientFactory>();
                IOAuthClient client = oauthClientFactory.Create(project);
                ITokenCache <OAuthOptions, Token> tokenCache = serviceProvider.GetRequiredService <ITokenCache <OAuthOptions, Token> >();

                ITokenService tokenService = new OAuthTokenService(client, tokenCache);
                var handler = new TokenAuthorizationHandler(tokenService, CreateOAuthOptions(projectResource));
                return(handler);
            });

            var apiGatewayHost   = projectResource.ApiGatewayHost;
            var apiGatewayPolicy = projectResource.ApiGatewayPolicy;

            if (!string.IsNullOrEmpty(apiGatewayHost) && !string.IsNullOrEmpty(apiGatewayPolicy))
            {
                // add the ApiGatewayHandler
                logger.Information("Using {@ApiGateway} for {Resource}", new { Host = apiGatewayHost, Policy = apiGatewayPolicy }, projectResource.Resource);
                builder.AddHttpMessageHandler(() => new ApiGatewayHandler(apiGatewayHost, apiGatewayPolicy));
            }
        }
Exemple #2
0
        private static void ConfigureDynamics(IServiceCollection services, ProjectConfiguration project, ProjectResource projectResource, Serilog.ILogger logger)
        {
            Debug.Assert(services != null, "Required ServiceCollection is null");
            Debug.Assert(project != null, "Required ProjectConfiguration is null");
            Debug.Assert(projectResource != null, "Required ProjectResource is null");
            Debug.Assert(projectResource.Type == ProjectType.Dynamics, "Project type must be Dynamics");

            string projectResourceKey = project.Id + "-dynamics";

            // add authorization HttpClient
            services.AddHttpClient(projectResourceKey + "-authorization", configure => configure.BaseAddress = projectResource.AuthorizationUri)
            ;

            // add odata HttpClient
            // note: I do not like this IoC anti-pattern where we are using the service locator directly, however,
            //       there are many named dependencies. There may be an opportunity to address this in the future

            services.AddHttpClient(projectResourceKey, configure =>
            {
                configure.BaseAddress = projectResource.BaseAddress;

                // use the API Gateway if required
                if (projectResource.BaseAddress.Host != projectResource.Resource.Host)
                {
                    configure.DefaultRequestHeaders.Add("RouteToHost", projectResource.Resource.Host);
                }
            })
            .AddHttpMessageHandler((serviceProvider) =>
            {
                // build the token service that talk to the OAuth endpoint
                IHttpClientFactory httpClientFactory = serviceProvider.GetRequiredService <IHttpClientFactory>();
                HttpClient httpClient = httpClientFactory.CreateClient(projectResourceKey + "-authorization");

                // create the handler that will authenticate the call and add authorization header
                ILogger <OAuthClient> logger = serviceProvider.GetRequiredService <ILogger <OAuthClient> >();
                ITokenCache tokenCache       = serviceProvider.GetRequiredService <ITokenCache>();
                ITokenService tokenService   = new OAuthTokenService(new OAuthClient(httpClient, logger), tokenCache);
                var handler = new TokenAuthorizationHandler(tokenService, CreateOAuthOptions(projectResource));
                return(handler);
            });
        }
Exemple #3
0
        private async Task <Tuple <ProjectResource, Exception> > GetOAuthAccessTokenAsync(ProjectConfiguration project, ProjectResource resource)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }
            if (resource == null)
            {
                throw new ArgumentNullException(nameof(resource));
            }

            var options = new OAuthOptions
            {
                AuthorizationUri = resource.AuthorizationUri,
                ClientId         = resource.ClientId,
                ClientSecret     = resource.ClientSecret,
                Username         = resource.Username,
                Password         = resource.Password,
                Resource         = resource.Resource
            };

            try
            {
                IOAuthClient oAuthClient = _oAuthClientFactory.Create(project);
                ITokenCache <OAuthOptions, Token> tokenCache = _serviceProvider.GetRequiredService <ITokenCache <OAuthOptions, Token> >();

                ITokenService tokenService = new OAuthTokenService(oAuthClient, tokenCache);

                // IOAuthClient does not cache tokens
                var token = await tokenService.GetTokenAsync(options, CancellationToken.None);

                return(Tuple.Create(resource, _noException));
            }
            catch (Exception e)
            {
                return(Tuple.Create(resource, e));
            }
        }