| @@ -0,0 +1,22 @@ | |||
| using Newtonsoft.Json; | |||
| using ProtoBuf; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.Auth | |||
| { | |||
| [ProtoContract] | |||
| public class RefreshTokenResponse : StatusCodeMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| [JsonProperty("access_token")] | |||
| public string? AccessToken { get; set; } | |||
| [ProtoMember(2)] | |||
| [JsonProperty("expires_in")] | |||
| public int? Expiration { get; set; } | |||
| } | |||
| } | |||
| @@ -8,7 +8,7 @@ using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.Search | |||
| { | |||
| [ProtoContract] | |||
| public class SearchResponse | |||
| public class SearchResponse : StatusCodeMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| public Tracks? Tracks { get; set; } | |||
| @@ -0,0 +1,23 @@ | |||
| using ProtoBuf; | |||
| using System.Net; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO | |||
| { | |||
| [ProtoContract] | |||
| [ProtoInclude(5, typeof(Search.SearchResponse))] | |||
| [ProtoInclude(6, typeof(TopItem.TopItemResponse))] | |||
| [ProtoInclude(7, typeof(Track.MultipleTrack.MultipleTrackResponse))] | |||
| [ProtoInclude(8, typeof(Track.SingleTrack.SingleTrackResponse))] | |||
| [ProtoInclude(9, typeof(TrackByID.TrackResponse))] | |||
| [ProtoInclude(10, typeof(User.UserInfoResponse))] | |||
| [ProtoInclude(11, typeof(Track.CurrentTrackResponse))] | |||
| [ProtoInclude(12, typeof(Auth.RefreshTokenResponse))] | |||
| public class StatusCodeMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| public HttpStatusCode ResponseMsg { get; set; } | |||
| } | |||
| } | |||
| @@ -25,5 +25,7 @@ namespace GrpcShared.DTO | |||
| { | |||
| [ProtoMember(1)] | |||
| public string? Token { get; set; } | |||
| [ProtoMember(2)] | |||
| public string? RefreshToken { get; set; } | |||
| } | |||
| } | |||
| @@ -9,7 +9,7 @@ using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.TopItem | |||
| { | |||
| [ProtoContract] | |||
| public class TopItemResponse | |||
| public class TopItemResponse : StatusCodeMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| [JsonProperty("items")] | |||
| @@ -9,7 +9,7 @@ using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.Track | |||
| { | |||
| [ProtoContract] | |||
| public class CurrentTrackResponse | |||
| public class CurrentTrackResponse : StatusCodeMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| [JsonProperty("timestamp")] | |||
| @@ -8,7 +8,7 @@ using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.Track.MultipleTrack | |||
| { | |||
| [ProtoContract] | |||
| public class MultipleTrackResponse | |||
| public class MultipleTrackResponse : StatusCodeMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| public List<AudioFeature>? Audio_Features { get; set; } | |||
| @@ -3,7 +3,7 @@ | |||
| namespace GrpcShared.DTO.Track.SingleTrack | |||
| { | |||
| [ProtoContract] | |||
| public class SingleTrackResponse | |||
| public class SingleTrackResponse : StatusCodeMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| public float? Danceability { get; set; } | |||
| @@ -10,7 +10,7 @@ using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.TrackByID | |||
| { | |||
| [ProtoContract] | |||
| public class TrackResponse | |||
| public class TrackResponse : StatusCodeMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| [JsonProperty("album")] | |||
| @@ -4,7 +4,7 @@ using ProtoBuf; | |||
| namespace GrpcShared.DTO.User | |||
| { | |||
| [ProtoContract] | |||
| public class UserInfoResponse | |||
| public class UserInfoResponse : StatusCodeMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| [JsonProperty("email")] | |||
| @@ -11,6 +11,7 @@ namespace GrpcShared.Interfaces | |||
| Task<TokenResponse> GetAccessToken(TokenRequest code); | |||
| Task<CodeRequest> GetAuthParams(); | |||
| Task<UserInfoResponse> GetUserInfo(TokenMessage token); | |||
| Task<RefreshTokenResponse> RefreshAccessToken(TokenMessage msg); | |||
| //Task<ClientSecrets> GetClientSecrets(); | |||
| } | |||
| } | |||
| @@ -24,4 +24,8 @@ | |||
| <ProjectReference Include="..\NemAnCore\NemAnBlazor.csproj" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Folder Include="Services\" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -1,10 +1,9 @@ | |||
| using GrpcShared; | |||
| using IdentityProvider.Services; | |||
| using SpotifyService.Services; | |||
| using Microsoft.AspNetCore.Server.Kestrel.Core; | |||
| using ProtoBuf.Grpc.Server; | |||
| using Microsoft.Extensions.Options; | |||
| using GrpcShared.DTO.Auth; | |||
| using SpotifyService.Services; | |||
| using Blazored.LocalStorage; | |||
| var builder = WebApplication.CreateBuilder(args); | |||
| @@ -28,7 +27,6 @@ builder.Services.AddHttpClient("HttpClient", c => | |||
| builder.Services.AddOptions(); | |||
| // Additional configuration is required to successfully run gRPC on macOS. | |||
| // For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682 | |||
| builder.Services.Configure<CodeRequest>(builder.Configuration.GetSection("AuthParams")); | |||
| builder.Services.AddControllersWithViews(); | |||
| builder.Services.AddRazorPages(); | |||
| @@ -40,6 +38,7 @@ builder.Services.AddCodeFirstGrpcReflection(); | |||
| builder.Services.AddBlazoredLocalStorage(); | |||
| //call spotify api | |||
| builder.Services.AddHttpClient(); | |||
| builder.Services.Configure<CodeRequest>(builder.Configuration.GetSection("AuthParams")); | |||
| var app = builder.Build(); | |||
| @@ -1,11 +1,10 @@ | |||
| @using NemAnBlazor.Pages | |||
| <CascadingAuthenticationState> | |||
| <Router AppAssembly="@typeof(App).Assembly"> | |||
| <Found Context="routeData"> | |||
| <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" > | |||
| <Authorizing> | |||
| <text>Please wait, we are authorizint the user.</text> | |||
| </Authorizing> | |||
| <text>Please wait, we are authorizing the user.</text> | |||
| </Authorizing> | |||
| </AuthorizeRouteView> | |||
| <FocusOnNavigate RouteData="@routeData" Selector="h1" /> | |||
| </Found> | |||
| @@ -16,4 +15,3 @@ | |||
| </LayoutView> | |||
| </NotFound> | |||
| </Router> | |||
| </CascadingAuthenticationState> | |||
| @@ -36,10 +36,18 @@ | |||
| { | |||
| var token = await localStorage.GetItemAsync<string>("token"); | |||
| TokenMessage tm = new() { Token = token }; | |||
| string refreshT = await localStorage.GetItemAsync<string>("refresh_token"); | |||
| TokenMessage tokenM = new TokenMessage{Token = token, RefreshToken = refreshT}; | |||
| SearchRequest request = new() { Query = "aitch", Type = "track", Token = token }; | |||
| SearchResponse searchResponse = await SearchService.GetListSearchAsync(request); | |||
| if (searchResponse.ResponseMsg == System.Net.HttpStatusCode.Unauthorized) | |||
| { | |||
| string? tempToken = await SpotifyHelper.TryRefreshToken(AuthService, tokenM, localStorage); | |||
| token = tempToken == null ? token : tempToken; | |||
| } | |||
| } | |||
| @@ -5,6 +5,7 @@ | |||
| @inject Blazored.LocalStorage.ILocalStorageService localStorage | |||
| @inject IStatsClientService spotifyService | |||
| @inject ITrackClientService trackService | |||
| @inject IAuthClientService AuthService | |||
| <h3>Home</h3> | |||
| @@ -14,14 +15,31 @@ | |||
| protected override async Task OnInitializedAsync() | |||
| { | |||
| string tokenS = await localStorage.GetItemAsync<string>("token"); | |||
| TokenMessage token = new TokenMessage{Token = tokenS}; | |||
| string refreshT = await localStorage.GetItemAsync<string>("refresh_token"); | |||
| CurrentTrackResponse response = await spotifyService.GetCurrentlyPlayingTrack(token); | |||
| //tokenS = "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN"; | |||
| TokenMessage token = new TokenMessage { Token = tokenS, RefreshToken = refreshT }; | |||
| //napravi komponentu koja ce da prikazuje sta trenutno slusas i passuj joj parametre | |||
| CurrentTrackResponse response = await spotifyService.GetCurrentlyPlayingTrack(token); | |||
| //4fy1A2WBTPX55mUI16TQXa | |||
| //if token expired, refresh it | |||
| if (response.ResponseMsg == System.Net.HttpStatusCode.Unauthorized) | |||
| { | |||
| string? tempToken = await SpotifyHelper.TryRefreshToken(AuthService, token, localStorage); | |||
| tokenS = tempToken == null ? tokenS : tempToken; | |||
| //if refreshed token is null, that means that refresh token was invalid, so you should redirect to login | |||
| } | |||
| //napravi komponentu koja ce da prikazuje sta trenutno slusas i passuj joj parametre | |||
| //var trackById = await trackService.GetById(new GrpcShared.DTO.TrackByID.TrackRequest { TrackID = "4fy1A2WBTPX55mUI16TQXa", Token = tokenS }); | |||
| var items = await spotifyService.GetTopItems(new GrpcShared.DTO.TopItem.TopItemRequest { Token = tokenS, IsTracks = false, Offset = 5}); | |||
| var items = await spotifyService.GetTopItems(new GrpcShared.DTO.TopItem.TopItemRequest { Token = tokenS, IsTracks = false, Offset = 5 }); | |||
| if (items.ResponseMsg == System.Net.HttpStatusCode.Unauthorized) | |||
| { | |||
| string? tempToken = await SpotifyHelper.TryRefreshToken(AuthService, token, localStorage); | |||
| tokenS = tempToken == null ? tokenS : tempToken; | |||
| } | |||
| } | |||
| } | |||
| @@ -11,13 +11,14 @@ | |||
| @using System.Security.Claims | |||
| <AuthorizeView> | |||
| <Authorized> | |||
| Dobrodosli @context.User.Claims.FirstOrDefault(x => x.Type == "name")?.Value.ToUpper() | |||
| <p>Dobrodosli @context.User.Claims.FirstOrDefault(x => x.Type == "name")?.Value.ToUpper()</p> | |||
| </Authorized> | |||
| <NotAuthorized> | |||
| Nisi autorizovan. | |||
| <button class="btn btn-primary" @onclick="LoginUser">Autorizuj</button> | |||
| <button class="btn btn-primary" @onclick="LoginUser">Login</button> | |||
| </NotAuthorized> | |||
| </AuthorizeView> | |||
| @@ -34,10 +35,6 @@ Dobrodošli u našu NemAn aplikaciju. | |||
| @code { | |||
| private string? message; | |||
| protected override async Task OnInitializedAsync() | |||
| { | |||
| message = "Cao"; | |||
| } | |||
| private async Task LoginUser() | |||
| { | |||
| @@ -23,12 +23,12 @@ builder.Services.AddScoped(_ => | |||
| return channel; | |||
| }); | |||
| builder.Services.AddAuthorizationCore(); | |||
| builder.Services.AddScoped<AuthenticationStateProvider, AuthClientService>(); | |||
| //builder.Services.AddScoped<AuthenticationStateProvider, AuthClientService>(); | |||
| builder.Services.AddScoped<ITrackClientService, TrackClientService>(); | |||
| builder.Services.AddScoped<IAuthClientService, AuthClientService>(); | |||
| builder.Services.AddScoped<IStatsClientService, StatsClientService>(); | |||
| builder.Services.AddBlazoredLocalStorage(); | |||
| builder.Services.AddBlazoredLocalStorage(); | |||
| builder.Services.AddScoped<AuthenticationStateProvider, AuthClientService>(); | |||
| builder.Services.AddAuthorizationCore(); | |||
| @@ -16,11 +16,11 @@ namespace NemAnBlazor.Services | |||
| { | |||
| private IAuthService _serviceClient; | |||
| private ILocalStorageService _sessionStorage; | |||
| private ILocalStorageService _localStorage; | |||
| public AuthClientService(GrpcChannel grpcChannel, ILocalStorageService sessionStorage) | |||
| { | |||
| _serviceClient = grpcChannel.CreateGrpcService<IAuthService>(); | |||
| _sessionStorage = sessionStorage; | |||
| _localStorage = sessionStorage; | |||
| } | |||
| public async Task<TokenResponse> GetAccessToken(TokenRequest request) | |||
| { | |||
| @@ -29,12 +29,12 @@ namespace NemAnBlazor.Services | |||
| //public override async Task<AuthenticationState> GetAuthenticationStateAsync() | |||
| //{ | |||
| // string token = await _sessionStorage.GetItemAsync<string>("token"); | |||
| // string token = await _localStorage.GetItemAsync<string>("token"); | |||
| // //token = "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN"; | |||
| // token = "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN"; | |||
| // if (token == null) return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); | |||
| // var userInfo = await _serviceClient.GetUserInfo(new TokenMessage ( token )); | |||
| // var userInfo = await _serviceClient.GetUserInfo(new TokenMessage { Token = token }); | |||
| // List<Claim> claims = new(); | |||
| @@ -43,7 +43,7 @@ namespace NemAnBlazor.Services | |||
| // claims.Add(new Claim("name", userInfo.display_name!)); | |||
| // ClaimsIdentity identity = new(claims, "jwt"); | |||
| // //ClaimsIdentity identity = new(); | |||
| // ClaimsIdentity identity = new(); | |||
| // ClaimsPrincipal user = new(identity); | |||
| // AuthenticationState state = new(user); | |||
| @@ -64,14 +64,16 @@ namespace NemAnBlazor.Services | |||
| public override async Task<AuthenticationState> GetAuthenticationStateAsync() | |||
| { | |||
| await Task.Delay(1500); | |||
| //return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); | |||
| await Task.Delay(500); | |||
| string token = await _sessionStorage.GetItemAsync<string>("token"); | |||
| string token = await _localStorage.GetItemAsync<string>("token"); | |||
| string refreshT = await _localStorage.GetItemAsync<string>("refresh_token"); | |||
| //token = "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN"; | |||
| if (token == null) return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); | |||
| var userInfo = await _serviceClient.GetUserInfo(new TokenMessage{Token = token}); | |||
| var userInfo = await _serviceClient.GetUserInfo(new TokenMessage { Token = token, RefreshToken = refreshT }); | |||
| List<Claim> claims = new(); | |||
| @@ -84,9 +86,14 @@ namespace NemAnBlazor.Services | |||
| ClaimsPrincipal user = new(identity); | |||
| AuthenticationState state = new(user); | |||
| NotifyAuthenticationStateChanged(Task.FromResult(state)); | |||
| // NotifyAuthenticationStateChanged(Task.FromResult(state)); | |||
| return state; | |||
| } | |||
| public async Task<RefreshTokenResponse> RefreshAccessToken(TokenMessage token) | |||
| { | |||
| return await _serviceClient.RefreshAccessToken(token); | |||
| } | |||
| } | |||
| } | |||
| @@ -10,5 +10,6 @@ namespace NemAnBlazor.Services.Interfaces | |||
| Task<TokenResponse> GetAccessToken(TokenRequest tokenRequest); | |||
| Task<CodeRequest> GetAuthParams(); | |||
| Task<UserInfoResponse> GetUserInfo(TokenMessage token); | |||
| Task<RefreshTokenResponse> RefreshAccessToken(TokenMessage token); | |||
| } | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| using Blazored.LocalStorage; | |||
| using GrpcShared.DTO; | |||
| using NemAnBlazor.Services.Interfaces; | |||
| namespace NemAnBlazor | |||
| { | |||
| public static class SpotifyHelper | |||
| { | |||
| public static async Task<string?> TryRefreshToken(IAuthClientService authService, TokenMessage msg, ILocalStorageService localStorage) | |||
| { | |||
| var refreshResponse = await authService.RefreshAccessToken(msg); | |||
| if (refreshResponse.AccessToken != null) | |||
| { | |||
| await localStorage.SetItemAsync<string>("token", refreshResponse.AccessToken); | |||
| return refreshResponse.AccessToken; | |||
| } | |||
| else return null; | |||
| } | |||
| } | |||
| } | |||
| @@ -6,6 +6,7 @@ using SpotifyService.Services; | |||
| using GrpcShared.Interfaces; | |||
| using Polly; | |||
| using Polly.Extensions.Http; | |||
| using GrpcShared.DTO.Auth; | |||
| var builder = WebApplication.CreateBuilder(args); | |||
| @@ -75,7 +76,7 @@ IAsyncPolicy<HttpResponseMessage> GetRetryPolicy() | |||
| // Retry two times after delay | |||
| .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt))); | |||
| } | |||
| builder.Services.AddOptions(); | |||
| builder.Services.AddControllersWithViews(); | |||
| builder.Services.AddRazorPages(); | |||
| @@ -87,6 +88,7 @@ builder.Services.AddCodeFirstGrpc(); | |||
| builder.Services.AddCodeFirstGrpcReflection(); | |||
| var app = builder.Build(); | |||
| builder.Services.Configure<CodeRequest>(builder.Configuration.GetSection("AuthParams")); | |||
| app.UseSwagger(); | |||
| app.UseSwaggerUI(); | |||
| @@ -10,13 +10,13 @@ using Microsoft.Extensions.Options; | |||
| using Microsoft.Net.Http.Headers; | |||
| using Newtonsoft.Json; | |||
| using System.Diagnostics; | |||
| using System.IdentityModel.Tokens.Jwt; | |||
| using System.IO; | |||
| using System.Net; | |||
| using System.Net.Http.Headers; | |||
| using System.Text; | |||
| using System.Text.Json; | |||
| namespace IdentityProvider.Services | |||
| namespace SpotifyService.Services | |||
| { | |||
| public class AuthService : IAuthService | |||
| { | |||
| @@ -31,10 +31,9 @@ namespace IdentityProvider.Services | |||
| _httpClientFactory = httpClientFactory; | |||
| } | |||
| public async Task<TokenResponse> GetAccessToken(TokenRequest tokenRequest) | |||
| { | |||
| var http = _httpClientFactory.CreateClient(); | |||
| var http = _httpClientFactory.CreateClient("HttpClient"); | |||
| string url = "https://accounts.spotify.com/api/token"; | |||
| http.BaseAddress = new Uri(url); | |||
| @@ -62,7 +61,7 @@ namespace IdentityProvider.Services | |||
| var contents = JsonConvert.DeserializeObject<TokenResponse>(await response.Content.ReadAsStringAsync()); | |||
| return contents; | |||
| } | |||
| public async Task<CodeRequest> GetAuthParams() | |||
| @@ -79,28 +78,59 @@ namespace IdentityProvider.Services | |||
| public async Task<UserInfoResponse> GetUserInfo(TokenMessage tokenM) | |||
| { | |||
| //var des = JsonConvert.DeserializeObject<TokenMessage>(tokenM); | |||
| //var tokenStorage = _sessionStorageService.GetItemAsync<string>("token"); | |||
| //hc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken); | |||
| //var response = hc.GetAsync(userInfoUrl).Result; | |||
| //dynamic userInfo = response.Content.ReadAsAsync().Result; | |||
| //return userInfo; | |||
| var http = _httpClientFactory.CreateClient(); | |||
| http.BaseAddress = new Uri("https://api.spotify.com/v1/me"); | |||
| http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenM.Token); | |||
| var response = http.GetAsync(http.BaseAddress).Result; | |||
| // expired token example "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN" | |||
| var http = _httpClientFactory.CreateClient("HttpClient"); | |||
| http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenM.Token!); | |||
| var response = await http.GetAsync("me"); | |||
| //make this a method in http utils | |||
| if (response.StatusCode == HttpStatusCode.Unauthorized) | |||
| { | |||
| //refresh the token | |||
| var refreshResponse = await RefreshAccessToken(tokenM); | |||
| //if response is invalid redirect to login | |||
| http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", refreshResponse.AccessToken); | |||
| response = await http.GetAsync("me"); | |||
| } | |||
| //var headerError = response.Headers.WwwAuthenticate.; | |||
| var userInfo = JsonConvert.DeserializeObject<UserInfoResponse>(await response.Content.ReadAsStringAsync())!; | |||
| userInfo.ResponseMsg = response.StatusCode; | |||
| return userInfo; | |||
| //http.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + token.Token); | |||
| } | |||
| public async Task<RefreshTokenResponse> RefreshAccessToken(TokenMessage tokenM) | |||
| { | |||
| var client = _httpClientFactory.CreateClient("HttpClient"); | |||
| client.BaseAddress = new Uri("https://accounts.spotify.com/api/token"); | |||
| //BODY PARAMS | |||
| var requestBody = new Dictionary<string, string>(); | |||
| requestBody["refresh_token"] = tokenM.RefreshToken!; | |||
| requestBody["grant_type"] = "refresh_token"; | |||
| var secrets = await GetAuthParams(); | |||
| byte[] contentType = Encoding.UTF8.GetBytes($"{secrets.ClientId}:{secrets.ClientSecret}"); | |||
| //var response = await http.GetAsync(http.BaseAddress + "me"); | |||
| //AUTHORIZATION HEADER | |||
| client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Basic " + Convert.ToBase64String(contentType)); | |||
| //var user = JsonConvert.DeserializeObject<UserInfoResponse>(await response.Content.ReadAsStringAsync()); | |||
| //REQUEST | |||
| var response = await client.PostAsync("https://accounts.spotify.com/api/token", new FormUrlEncodedContent(requestBody)); | |||
| //return await Task.FromResult(user!); | |||
| if (response.StatusCode == HttpStatusCode.Unauthorized) | |||
| { | |||
| //delete tokens from localstorage | |||
| //redirect to login | |||
| } | |||
| var contents = JsonConvert.DeserializeObject<RefreshTokenResponse>(await response.Content.ReadAsStringAsync())!; | |||
| return contents; | |||
| } | |||
| } | |||
| } | |||
| @@ -23,7 +23,9 @@ namespace SpotifyService.Services | |||
| var client = _httpClientFactory.CreateClient("HttpClient"); | |||
| string url = "me/player/currently-playing"; | |||
| return await HttpUtils<CurrentTrackResponse>.GetData(client, url, token.Token!); | |||
| var response = await HttpUtils<CurrentTrackResponse>.GetData(client, url, token.Token!); | |||
| return response; | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| using Google.Rpc; | |||
| using Grpc.Core; | |||
| using GrpcShared; | |||
| using GrpcShared.DTO; | |||
| using GrpcShared.DTO.Search; | |||
| using GrpcShared.DTO.Track.MultipleTrack; | |||
| using GrpcShared.DTO.Track.SaveTracks; | |||
| @@ -66,7 +67,7 @@ namespace SpotifyService.Services | |||
| string url = $"me/tracks/{query}"; | |||
| //the response type has nothing to do with the method, it's there so that the method can be called | |||
| await HttpUtils.HttpUtils<MultipleTrackResponse>.PutData(client, url, request.Token!); | |||
| await HttpUtils.HttpUtils<StatusCodeMessage>.PutData(client, url, request.Token!); | |||
| } | |||
| public static string UriUtil(Dictionary<string, List<string>> param) | |||
| @@ -10,5 +10,11 @@ | |||
| "EndpointDefaults": { | |||
| "Protocols": "Http1AndHttp2" | |||
| } | |||
| }, | |||
| "AuthParams": { | |||
| "ClientId": "83e1d09876b049c4bb1953185a4b3bfb", | |||
| "RedirectURI": "https://localhost:44342/callback", | |||
| "Scope": "user-read-currently-playing user-read-email user-library-modify user-top-read user-read-private", | |||
| "ClientSecret": "ea752433d0774fad87fab5c1ee788c8d" | |||
| } | |||
| } | |||