最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

asynchronous - Using OAuth2 in ODataV4getting Token asynchronously - Stack Overflow

programmeradmin0浏览0评论

I've got an OData connected service for V4 generated through a metadata file.

Since the service requires OAuth2, I have to obtain the token asynchronously from a web server before sent any message.

In order to achieve that, I've configured the service applying DI pattern using Microsoft.OData.Extensions.Client:

services.AddODataClient(nameof(ApiServices))
        .ConfigureODataClient(config =>
              {
                 config.AddAndUpdateResponsePreference = DataServiceResponsePreference.IncludeContent;
                 config.Format.UseJson();
                 config.MergeOption = MergeOption.OverwriteChanges;
              })
        .AddHttpClient()
        .AddHttpMessageHandler<BearerTokenAuthHandler>()
        .Services
        .AddTransient<BearerTokenAuthHandler>()
        .AddTransient<ApiServices>()
        .AddTransient<IServiceAuthentication, ApiServices>();

HttpMessageHandler is:

internal partial class BearerTokenAuthHandler : DelegatingHandler
{
      IAccessTokenProvider _tokenClient;

      public BearerTokenAuthHandler(IServiceAuthentication service)
      {
         _tokenClient = service.AuthenticationProvider.AccessTokenProvider;
      }

      protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
      {
         string url = string.Format(EntraApps.BcAuthorizationUrl, EntraApps.TenantId);

         string token = await _tokenClient.GetAuthorizationTokenAsync(new Uri(url), null, cancellationToken);
         request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);

         HttpRequestOptionsKey<string> option = new HttpRequestOptionsKey<string>("tenant");
         request.Options.Set(option, EntraApps.BcTenantId);

         return await base.SendAsync(request, cancellationToken);
      }
}

Problem is: BearerTokenAuthHandler is not instantiated when after building any query, ExecuteAsync() is executed. So, no authorisation happens, and no data is retrieved and a DataServiceClientException is thrown ("Unauthorised / The credentials provided are incorrect"):

ApiServices service = ServiceProvider.GetService<ApiServices>();

IEnumerable<Company> companies = await service .Companies.ExecuteAsync();

However, if I build same message using the query building and HttpClientFactory from the service instance, there's no problem. Authorization is Ok and data is retrieved from the server:

ApiServices service = ServiceProvider.GetService<ApiServices>();
HttpClient client = service.HttpClientFactory.CreateClient(nameof(ApiServices));

Uri uri = service.Companies.RequestUri;

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
HttpResponseMessage response = await client.SendAsync(request);

Is something wrong with my code? It seems that OData ExecuteAsync() doesn't use HttpClientFactory after all.

SendingRequest2 event is of no use, since it's synchronous.

Any suggestion will be appreciated.

发布评论

评论列表(0)

  1. 暂无评论