using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using Flurl; using Newtonsoft.Json; using Sony.Filtr.Contracts.Abstractions; using Sony.Filtr.Contracts.Entities; using Sony.Filtr.SoundCloud.Model; namespace Sony.Filtr.SoundCloud { public class SoundCloudAuthorizationHttpMessageHandler : DelegatingHandler { private ServiceAccount _serviceAccount; private readonly IServiceAccountManager _serviceAccountManager; private readonly string _clientId; private readonly string _clientSecret; public SoundCloudAuthorizationHttpMessageHandler(ServiceAccount serviceAccount, IServiceAccountManager serviceAccountManager, string clientId, string clientSecret, HttpMessageHandler httpMessageHandler) : base(httpMessageHandler) { _serviceAccount = serviceAccount; _serviceAccountManager = serviceAccountManager; _clientId = clientId; _clientSecret = clientSecret; } protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var url = new Url(request.RequestUri.ToString()); url.SetQueryParam("oauth_token", _serviceAccount.AccessToken); request.RequestUri = new Uri(url); var response = await base.SendAsync(request, cancellationToken); if (response.StatusCode == HttpStatusCode.Unauthorized) { //Our access code be old, try and refresh var refreshedAccessToken = await RequestRefreshedAccessToken(_serviceAccount.RefreshToken); if (refreshedAccessToken == null || string.IsNullOrWhiteSpace(refreshedAccessToken.access_token)) { throw new SoundCloudException("Could not get access token by refresh token", HttpMethod.Post, HttpStatusCode.Unauthorized); } _serviceAccount = SaveAccessToken(_serviceAccount, refreshedAccessToken); //Try request once more with updated access token url.SetQueryParam("oauth_token", _serviceAccount.AccessToken); request.RequestUri = new Uri(url); response = await base.SendAsync(request, cancellationToken); } return response; } private ServiceAccount SaveAccessToken(ServiceAccount serviceAccount, SoundCloudAuthResponse refreshedAccessToken) { _serviceAccount.UpdatedDate = DateTime.Now; _serviceAccount.AccessToken = refreshedAccessToken.access_token; _serviceAccount.AccessTokenExpiry = refreshedAccessToken.expires_in; var updatedServiceAccount = _serviceAccountManager.SaveServiceAccount(serviceAccount); return updatedServiceAccount; } private async Task RequestRefreshedAccessToken(string refreshToken) { var url = $"https://api.soundcloud.com/oauth2/token"; var client = new HttpClient(); var formDictionary = new Dictionary() { { "client_id", _clientId }, { "client_secret", _clientSecret}, { "grant_type", "refresh_token" }, { "refresh_token", refreshToken }, {"redirect_uri", "http://adminapi.filtr.local.circuit.se/serviceAccounts/soundcloudcallback" } }; var response = await client.PostAsync(url, new FormUrlEncodedContent(formDictionary)); var soundCloudResponseString = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject(soundCloudResponseString); } } }