using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Runtime.Caching; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; using Sony.Filtr.AppleMusicAPI.Models; namespace Sony.Filtr.AppleMusicAPI { public class AppleMusicAuthClientCredentialsHttpMessageHandler : DelegatingHandler { private readonly string _clientId; private readonly string _clientSecret; private static readonly SemaphoreSlim SyncLock = new SemaphoreSlim(1); public AppleMusicAuthClientCredentialsHttpMessageHandler(string clientId, string clientSecret, HttpMessageHandler httpMessageHandler): base(httpMessageHandler) { _clientId = clientId; _clientSecret = clientSecret; } protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request.Headers.Authorization == null) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await GetAuthenticationTokenAsync()); } return await base.SendAsync(request, cancellationToken); } private async Task GetAuthenticationTokenAsync() { var cacheKey = "AppleMusicWebApiSession-Token" + _clientId; //Locking for token? //var token = MemoryCache.Default.Get(cacheKey) as string; //if (token == null) //{ // SyncLock.Wait(); // try // { // token = MemoryCache.Default.Get(cacheKey) as string; // if (token == null) // { // var timeBeforeRequest = DateTime.Now; // var response = await GetAuthenticationTokenResponse(); // // var expireTime = timeBeforeRequest.AddSeconds(Convert.ToInt32(response.expires_in)); // MemoryCache.Default.Set(cacheKey, token, new DateTimeOffset(expireTime)); // } // } // finally // { // SyncLock.Release(); // } //} return await GetAuthenticationTokenResponse(); //return token; } public static string Base64Encode(string plainText) { var plainTextBytes = Encoding.UTF8.GetBytes(plainText); return Convert.ToBase64String(plainTextBytes); } private async Task GetAuthenticationTokenResponse() { HttpClient client = new HttpClient(); var content = new FormUrlEncodedContent(new[] { new KeyValuePair("grant_type", "client_credentials") //new KeyValuePair("scope", "") }); var authHeader = Base64Encode(_clientId + ":" + _clientSecret); var jwtToken = GetJwtToken(); var requestMessage = new HttpRequestMessage(HttpMethod.Post, "https://accounts.spotify.com/api/token"); requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", authHeader); requestMessage.Content = content; var response = await client.SendAsync(requestMessage); var responseString = await response.Content.ReadAsStringAsync(); return responseString; //var authenticationResponse = JsonConvert.DeserializeObject(responseString); //return authenticationResponse; } private string GetJwtToken() { //jose-jwt //var header = JsonConvert.SerializeObject(new JwtHeader() //{ // alg = "ES256", // kid = "9K26W5TDWH" //}); //var unixEpochTimeSpan = (DateTime.UtcNow – new DateTime(1970, 1, 1)); //var expiresAt = (long)t.TotalSeconds; //var payload = JsonConvert.SerializeObject(new JwtPayload() //{ // iss = "Y38Y7276CK", // exp = DateTime.Now.Ticks // iat = "" //}); //return $"{header} {payload}"; var payload = new Dictionary() { { "iss", "Y38Y7276CK" }, }; var privateKey = new X509Certificate2("ecc-key.p12", "password").GetECDsaPrivateKey(); string token = Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.ES256); return null; } } }