using Sony.Filtr.ApolloAPI.EventSource; using Sony.Filtr.ApolloAPI.Models; using System; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; namespace Sony.Filtr.ApolloAPI { public class ApolloAuthTokenMessageHandler : DelegatingHandler { private readonly string jsonPayload; private readonly string tokenServiceUrl; private readonly HttpClient authHttpClient; private static readonly SemaphoreSlim SyncLock = new SemaphoreSlim(1); private AuthResponse AuthResponse; public ApolloAuthTokenMessageHandler(string jsonPayload, string tokenServiceUrl, HttpMessageHandler innerHandler) : base(innerHandler) { this.jsonPayload = jsonPayload; this.tokenServiceUrl = tokenServiceUrl; this.authHttpClient = this.CreateAuthHttpClient(); } protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request.Headers.Authorization == null) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await GetAuthenticationTokenAsync()); } var response = await base.SendAsync(request, cancellationToken); if (response.StatusCode == HttpStatusCode.Unauthorized) { this.AuthResponse = null; request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await GetAuthenticationTokenAsync()); response = await base.SendAsync(request, cancellationToken); } return response; } private async Task GetAuthenticationTokenAsync() { if (this.AuthResponse == null) { await SyncLock.WaitAsync(); try { if (this.AuthResponse == null) { var authResponse = await this.RequestAccessToken(); if (authResponse == null || string.IsNullOrWhiteSpace(authResponse.access_token)) { throw new ApolloWebAPIException("Could not get access token by refresh token for Apollo", HttpMethod.Post, HttpStatusCode.Unauthorized); } this.SaveAccessToken(authResponse); } } finally { SyncLock.Release(); } } else { } return this.AuthResponse.access_token; } private void SaveAccessToken(AuthResponse authResponse) { this.AuthResponse = authResponse; } private async Task RequestAccessToken() { var content = new StringContent(this.jsonPayload, System.Text.Encoding.UTF8, "application/json"); ApolloApolloWebApiEventSource.Log.RequestAccessTokenStart(); var response = await this.authHttpClient.PostAsync(this.tokenServiceUrl, content); var authenticationResponse = await response.Content.ReadAsAsync(); ApolloApolloWebApiEventSource.Log.RequestAccessTokenStop(); return authenticationResponse; } private HttpClient CreateAuthHttpClient() { HttpClient client = new HttpClient(); //client.BaseAddress = new Uri("https://sme-dna.auth0.com/oauth/token"); return client; } } }