瀏覽代碼

refresh token configured

master
anastasijasavov 3 年之前
父節點
當前提交
3ed00b19c5

+ 22
- 0
GrpcShared/DTO/Auth/RefreshTokenResponse.cs 查看文件

@@ -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; }
}
}

+ 1
- 1
GrpcShared/DTO/Search/SearchResponse.cs 查看文件

@@ -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; }

+ 23
- 0
GrpcShared/DTO/StatusCodeMessage.cs 查看文件

@@ -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; }
}
}

+ 2
- 0
GrpcShared/DTO/TokenMessage.cs 查看文件

@@ -25,5 +25,7 @@ namespace GrpcShared.DTO
{
[ProtoMember(1)]
public string? Token { get; set; }
[ProtoMember(2)]
public string? RefreshToken { get; set; }
}
}

+ 1
- 1
GrpcShared/DTO/TopItem/TopItemResponse.cs 查看文件

@@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace GrpcShared.DTO.TopItem
{
[ProtoContract]
public class TopItemResponse
public class TopItemResponse : StatusCodeMessage
{
[ProtoMember(1)]
[JsonProperty("items")]

+ 1
- 1
GrpcShared/DTO/Track/CurrentTrackResponse.cs 查看文件

@@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace GrpcShared.DTO.Track
{
[ProtoContract]
public class CurrentTrackResponse
public class CurrentTrackResponse : StatusCodeMessage
{
[ProtoMember(1)]
[JsonProperty("timestamp")]

+ 1
- 1
GrpcShared/DTO/Track/MultipleTrack/MultipleTrackResponse.cs 查看文件

@@ -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; }

+ 1
- 1
GrpcShared/DTO/Track/SingleTrack/SingleTrackResponse.cs 查看文件

@@ -3,7 +3,7 @@
namespace GrpcShared.DTO.Track.SingleTrack
{
[ProtoContract]
public class SingleTrackResponse
public class SingleTrackResponse : StatusCodeMessage
{
[ProtoMember(1)]
public float? Danceability { get; set; }

+ 1
- 1
GrpcShared/DTO/Track/TrackByID/TrackResponse.cs 查看文件

@@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace GrpcShared.DTO.TrackByID
{
[ProtoContract]
public class TrackResponse
public class TrackResponse : StatusCodeMessage
{
[ProtoMember(1)]
[JsonProperty("album")]

+ 1
- 1
GrpcShared/DTO/User/UserInfoResponse.cs 查看文件

@@ -4,7 +4,7 @@ using ProtoBuf;
namespace GrpcShared.DTO.User
{
[ProtoContract]
public class UserInfoResponse
public class UserInfoResponse : StatusCodeMessage
{
[ProtoMember(1)]
[JsonProperty("email")]

+ 1
- 0
GrpcShared/Interfaces/IAuthService.cs 查看文件

@@ -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();
}
}

+ 4
- 0
IdentityProvider/IdentityProvider.csproj 查看文件

@@ -24,4 +24,8 @@
<ProjectReference Include="..\NemAnCore\NemAnBlazor.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>

</Project>

+ 2
- 3
IdentityProvider/Program.cs 查看文件

@@ -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();


+ 2
- 4
NemAnCore/App.razor 查看文件

@@ -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>

+ 9
- 1
NemAnCore/Pages/FetchData.razor 查看文件

@@ -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;
}
}



+ 23
- 5
NemAnCore/Pages/Home.razor 查看文件

@@ -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;
}

}
}

+ 3
- 6
NemAnCore/Pages/Login.razor 查看文件

@@ -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()
{

+ 2
- 2
NemAnCore/Program.cs 查看文件

@@ -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();


+ 18
- 11
NemAnCore/Services/AuthClientService.cs 查看文件

@@ -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);
}
}
}

+ 1
- 0
NemAnCore/Services/Interfaces/IAuthClientService.cs 查看文件

@@ -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);
}
}

+ 21
- 0
NemAnCore/SpotifyHelper.cs 查看文件

@@ -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;
}
}
}

+ 3
- 1
gRPCServer/Program.cs 查看文件

@@ -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();

IdentityProvider/Services/AuthService.cs → gRPCServer/Services/AuthService.cs 查看文件

@@ -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;
}
}
}

+ 3
- 1
gRPCServer/Services/StatsService.cs 查看文件

@@ -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;

}


+ 2
- 1
gRPCServer/Services/TrackService.cs 查看文件

@@ -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)

+ 6
- 0
gRPCServer/appsettings.json 查看文件

@@ -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"
}
}

Loading…
取消
儲存