Blazor & WASM in combination to get statistics from Spotify API for performing the song analysis. With separate microservices for auth, Spotify, user data tracking, and application, connected through gRPC with Polly.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AuthService.cs 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. //using IdentityProvider.Protos.AuthService;
  2. using Blazored.LocalStorage;
  3. using Grpc.Net.Client;
  4. using GrpcShared;
  5. using GrpcShared.DTO;
  6. using GrpcShared.DTO.Auth;
  7. using GrpcShared.DTO.User;
  8. using GrpcShared.Interfaces;
  9. using Microsoft.Extensions.Options;
  10. using Microsoft.Net.Http.Headers;
  11. using Newtonsoft.Json;
  12. using System.Diagnostics;
  13. using System.IO;
  14. using System.Net;
  15. using System.Net.Http.Headers;
  16. using System.Text;
  17. using System.Text.Json;
  18. namespace SpotifyService.Services
  19. {
  20. public class AuthService : IAuthService
  21. {
  22. private readonly ILogger<AuthService> _logger;
  23. private readonly CodeRequest _params;
  24. private readonly IHttpClientFactory _httpClientFactory;
  25. //private ISessionStorageService _sessionStorageService;
  26. public AuthService(ILogger<AuthService> logger, IOptions<CodeRequest> options, IHttpClientFactory httpClientFactory)
  27. {
  28. _logger = logger;
  29. _params = options.Value;
  30. _httpClientFactory = httpClientFactory;
  31. }
  32. public async Task<TokenResponse> GetAccessToken(TokenRequest tokenRequest)
  33. {
  34. var http = _httpClientFactory.CreateClient("HttpClient");
  35. string url = "https://accounts.spotify.com/api/token";
  36. http.BaseAddress = new Uri(url);
  37. //get client id and secret, and redirect uri from appsettings, convert to base64 and set as header
  38. var secrets = await GetAuthParams();
  39. byte[] contentType = Encoding.UTF8.GetBytes($"{secrets.ClientId}:{secrets.ClientSecret}");
  40. tokenRequest.RedirectUri = secrets.RedirectURI;
  41. //AUTHORIZATION HEADER
  42. http.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Basic " + Convert.ToBase64String(contentType));
  43. ////ACCEPT HEADER
  44. //http.DefaultRequestHeaders.Accept.Add(
  45. // new MediaTypeWithQualityHeaderValue("application/json"));
  46. //BODY PARAMS
  47. var requestBody = new Dictionary<string, string>();
  48. requestBody["grant_type"] = tokenRequest.GrantType;
  49. requestBody["code"] = tokenRequest.Code!;
  50. requestBody["redirect_uri"] = tokenRequest.RedirectUri!;
  51. //REQUEST
  52. var response = await http.PostAsync(url, new FormUrlEncodedContent(requestBody));
  53. var contents = JsonConvert.DeserializeObject<TokenResponse>(await response.Content.ReadAsStringAsync());
  54. return contents;
  55. }
  56. public async Task<CodeRequest> GetAuthParams()
  57. {
  58. var authParams = new CodeRequest
  59. {
  60. ClientId = _params.ClientId,
  61. RedirectURI = _params.RedirectURI,
  62. Scope = _params.Scope,
  63. ClientSecret = _params.ClientSecret
  64. };
  65. return await Task.FromResult(authParams);
  66. }
  67. public async Task<UserInfoResponse> GetUserInfo(TokenMessage tokenM)
  68. {
  69. // expired token example "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN"
  70. var http = _httpClientFactory.CreateClient("HttpClient");
  71. http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenM.Token!);
  72. var response = await http.GetAsync("me");
  73. //make this a method in http utils
  74. if (response.StatusCode == HttpStatusCode.Unauthorized)
  75. {
  76. //refresh the token
  77. var refreshResponse = await RefreshAccessToken(tokenM);
  78. //if response is invalid redirect to login
  79. http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", refreshResponse.AccessToken);
  80. response = await http.GetAsync("me");
  81. }
  82. //var headerError = response.Headers.WwwAuthenticate.;
  83. var userInfo = JsonConvert.DeserializeObject<UserInfoResponse>(await response.Content.ReadAsStringAsync())!;
  84. userInfo.ResponseMsg = response.StatusCode;
  85. return userInfo;
  86. }
  87. public async Task<RefreshTokenResponse> RefreshAccessToken(TokenMessage tokenM)
  88. {
  89. var client = _httpClientFactory.CreateClient("HttpClient");
  90. client.BaseAddress = new Uri("https://accounts.spotify.com/api/token");
  91. //BODY PARAMS
  92. var requestBody = new Dictionary<string, string>();
  93. requestBody["refresh_token"] = tokenM.RefreshToken!;
  94. requestBody["grant_type"] = "refresh_token";
  95. var secrets = await GetAuthParams();
  96. byte[] contentType = Encoding.UTF8.GetBytes($"{secrets.ClientId}:{secrets.ClientSecret}");
  97. //AUTHORIZATION HEADER
  98. client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Basic " + Convert.ToBase64String(contentType));
  99. //REQUEST
  100. var response = await client.PostAsync("https://accounts.spotify.com/api/token", new FormUrlEncodedContent(requestBody));
  101. if (response.StatusCode == HttpStatusCode.Unauthorized)
  102. {
  103. //delete tokens from localstorage
  104. //redirect to login
  105. }
  106. var contents = JsonConvert.DeserializeObject<RefreshTokenResponse>(await response.Content.ReadAsStringAsync())!;
  107. return contents;
  108. }
  109. }
  110. }