Просмотр исходного кода

refresh token configured

master
anastasijasavov 3 лет назад
Родитель
Сommit
3ed00b19c5

+ 22
- 0
GrpcShared/DTO/Auth/RefreshTokenResponse.cs Просмотреть файл

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 Просмотреть файл

namespace GrpcShared.DTO.Search namespace GrpcShared.DTO.Search
{ {
[ProtoContract] [ProtoContract]
public class SearchResponse
public class SearchResponse : StatusCodeMessage
{ {
[ProtoMember(1)] [ProtoMember(1)]
public Tracks? Tracks { get; set; } public Tracks? Tracks { get; set; }

+ 23
- 0
GrpcShared/DTO/StatusCodeMessage.cs Просмотреть файл

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 Просмотреть файл

{ {
[ProtoMember(1)] [ProtoMember(1)]
public string? Token { get; set; } public string? Token { get; set; }
[ProtoMember(2)]
public string? RefreshToken { get; set; }
} }
} }

+ 1
- 1
GrpcShared/DTO/TopItem/TopItemResponse.cs Просмотреть файл

namespace GrpcShared.DTO.TopItem namespace GrpcShared.DTO.TopItem
{ {
[ProtoContract] [ProtoContract]
public class TopItemResponse
public class TopItemResponse : StatusCodeMessage
{ {
[ProtoMember(1)] [ProtoMember(1)]
[JsonProperty("items")] [JsonProperty("items")]

+ 1
- 1
GrpcShared/DTO/Track/CurrentTrackResponse.cs Просмотреть файл

namespace GrpcShared.DTO.Track namespace GrpcShared.DTO.Track
{ {
[ProtoContract] [ProtoContract]
public class CurrentTrackResponse
public class CurrentTrackResponse : StatusCodeMessage
{ {
[ProtoMember(1)] [ProtoMember(1)]
[JsonProperty("timestamp")] [JsonProperty("timestamp")]

+ 1
- 1
GrpcShared/DTO/Track/MultipleTrack/MultipleTrackResponse.cs Просмотреть файл

namespace GrpcShared.DTO.Track.MultipleTrack namespace GrpcShared.DTO.Track.MultipleTrack
{ {
[ProtoContract] [ProtoContract]
public class MultipleTrackResponse
public class MultipleTrackResponse : StatusCodeMessage
{ {
[ProtoMember(1)] [ProtoMember(1)]
public List<AudioFeature>? Audio_Features { get; set; } public List<AudioFeature>? Audio_Features { get; set; }

+ 1
- 1
GrpcShared/DTO/Track/SingleTrack/SingleTrackResponse.cs Просмотреть файл

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

+ 1
- 1
GrpcShared/DTO/Track/TrackByID/TrackResponse.cs Просмотреть файл

namespace GrpcShared.DTO.TrackByID namespace GrpcShared.DTO.TrackByID
{ {
[ProtoContract] [ProtoContract]
public class TrackResponse
public class TrackResponse : StatusCodeMessage
{ {
[ProtoMember(1)] [ProtoMember(1)]
[JsonProperty("album")] [JsonProperty("album")]

+ 1
- 1
GrpcShared/DTO/User/UserInfoResponse.cs Просмотреть файл

namespace GrpcShared.DTO.User namespace GrpcShared.DTO.User
{ {
[ProtoContract] [ProtoContract]
public class UserInfoResponse
public class UserInfoResponse : StatusCodeMessage
{ {
[ProtoMember(1)] [ProtoMember(1)]
[JsonProperty("email")] [JsonProperty("email")]

+ 1
- 0
GrpcShared/Interfaces/IAuthService.cs Просмотреть файл

Task<TokenResponse> GetAccessToken(TokenRequest code); Task<TokenResponse> GetAccessToken(TokenRequest code);
Task<CodeRequest> GetAuthParams(); Task<CodeRequest> GetAuthParams();
Task<UserInfoResponse> GetUserInfo(TokenMessage token); Task<UserInfoResponse> GetUserInfo(TokenMessage token);
Task<RefreshTokenResponse> RefreshAccessToken(TokenMessage msg);
//Task<ClientSecrets> GetClientSecrets(); //Task<ClientSecrets> GetClientSecrets();
} }
} }

+ 4
- 0
IdentityProvider/IdentityProvider.csproj Просмотреть файл

<ProjectReference Include="..\NemAnCore\NemAnBlazor.csproj" /> <ProjectReference Include="..\NemAnCore\NemAnBlazor.csproj" />
</ItemGroup> </ItemGroup>


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

</Project> </Project>

+ 2
- 3
IdentityProvider/Program.cs Просмотреть файл

using GrpcShared; using GrpcShared;
using IdentityProvider.Services;
using SpotifyService.Services;
using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core;
using ProtoBuf.Grpc.Server; using ProtoBuf.Grpc.Server;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using GrpcShared.DTO.Auth; using GrpcShared.DTO.Auth;
using SpotifyService.Services;
using Blazored.LocalStorage; using Blazored.LocalStorage;


var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOptions(); builder.Services.AddOptions();
// Additional configuration is required to successfully run gRPC on macOS. // 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 // 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.AddControllersWithViews();
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();


builder.Services.AddBlazoredLocalStorage(); builder.Services.AddBlazoredLocalStorage();
//call spotify api //call spotify api
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();
builder.Services.Configure<CodeRequest>(builder.Configuration.GetSection("AuthParams"));


var app = builder.Build(); var app = builder.Build();



+ 2
- 4
NemAnCore/App.razor Просмотреть файл

@using NemAnBlazor.Pages @using NemAnBlazor.Pages
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly"> <Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData"> <Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" > <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" >
<Authorizing> <Authorizing>
<text>Please wait, we are authorizint the user.</text>
</Authorizing>
<text>Please wait, we are authorizing the user.</text>
</Authorizing>
</AuthorizeRouteView> </AuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1" /> <FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found> </Found>
</LayoutView> </LayoutView>
</NotFound> </NotFound>
</Router> </Router>
</CascadingAuthenticationState>

+ 9
- 1
NemAnCore/Pages/FetchData.razor Просмотреть файл

{ {


var token = await localStorage.GetItemAsync<string>("token"); 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 }; SearchRequest request = new() { Query = "aitch", Type = "track", Token = token };
SearchResponse searchResponse = await SearchService.GetListSearchAsync(request); 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 Просмотреть файл

@inject Blazored.LocalStorage.ILocalStorageService localStorage @inject Blazored.LocalStorage.ILocalStorageService localStorage
@inject IStatsClientService spotifyService @inject IStatsClientService spotifyService
@inject ITrackClientService trackService @inject ITrackClientService trackService
@inject IAuthClientService AuthService


<h3>Home</h3> <h3>Home</h3>


protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
string tokenS = await localStorage.GetItemAsync<string>("token"); 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 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 Просмотреть файл

@using System.Security.Claims @using System.Security.Claims




<AuthorizeView> <AuthorizeView>
<Authorized> <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> </Authorized>
<NotAuthorized> <NotAuthorized>
Nisi autorizovan. Nisi autorizovan.
<button class="btn btn-primary" @onclick="LoginUser">Autorizuj</button>
<button class="btn btn-primary" @onclick="LoginUser">Login</button>
</NotAuthorized> </NotAuthorized>
</AuthorizeView> </AuthorizeView>


@code { @code {
private string? message; private string? message;


protected override async Task OnInitializedAsync()
{
message = "Cao";
}


private async Task LoginUser() private async Task LoginUser()
{ {

+ 2
- 2
NemAnCore/Program.cs Просмотреть файл

return channel; return channel;
}); });
builder.Services.AddAuthorizationCore(); builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AuthenticationStateProvider, AuthClientService>();
//builder.Services.AddScoped<AuthenticationStateProvider, AuthClientService>();


builder.Services.AddScoped<ITrackClientService, TrackClientService>(); builder.Services.AddScoped<ITrackClientService, TrackClientService>();
builder.Services.AddScoped<IAuthClientService, AuthClientService>(); builder.Services.AddScoped<IAuthClientService, AuthClientService>();
builder.Services.AddScoped<IStatsClientService, StatsClientService>(); builder.Services.AddScoped<IStatsClientService, StatsClientService>();
builder.Services.AddBlazoredLocalStorage();
builder.Services.AddBlazoredLocalStorage();
builder.Services.AddScoped<AuthenticationStateProvider, AuthClientService>(); builder.Services.AddScoped<AuthenticationStateProvider, AuthClientService>();
builder.Services.AddAuthorizationCore(); builder.Services.AddAuthorizationCore();



+ 18
- 11
NemAnCore/Services/AuthClientService.cs Просмотреть файл

{ {


private IAuthService _serviceClient; private IAuthService _serviceClient;
private ILocalStorageService _sessionStorage;
private ILocalStorageService _localStorage;
public AuthClientService(GrpcChannel grpcChannel, ILocalStorageService sessionStorage) public AuthClientService(GrpcChannel grpcChannel, ILocalStorageService sessionStorage)
{ {
_serviceClient = grpcChannel.CreateGrpcService<IAuthService>(); _serviceClient = grpcChannel.CreateGrpcService<IAuthService>();
_sessionStorage = sessionStorage;
_localStorage = sessionStorage;
} }
public async Task<TokenResponse> GetAccessToken(TokenRequest request) public async Task<TokenResponse> GetAccessToken(TokenRequest request)
{ {


//public override async Task<AuthenticationState> GetAuthenticationStateAsync() //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())); // 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(); // List<Claim> claims = new();


// claims.Add(new Claim("name", userInfo.display_name!)); // claims.Add(new Claim("name", userInfo.display_name!));


// ClaimsIdentity identity = new(claims, "jwt"); // ClaimsIdentity identity = new(claims, "jwt");
// //ClaimsIdentity identity = new();
// ClaimsIdentity identity = new();
// ClaimsPrincipal user = new(identity); // ClaimsPrincipal user = new(identity);
// AuthenticationState state = new(user); // AuthenticationState state = new(user);




public override async Task<AuthenticationState> GetAuthenticationStateAsync() 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"; //token = "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN";
if (token == null) return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); 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(); List<Claim> claims = new();


ClaimsPrincipal user = new(identity); ClaimsPrincipal user = new(identity);
AuthenticationState state = new(user); AuthenticationState state = new(user);


NotifyAuthenticationStateChanged(Task.FromResult(state));
// NotifyAuthenticationStateChanged(Task.FromResult(state));


return state; return state;
} }

public async Task<RefreshTokenResponse> RefreshAccessToken(TokenMessage token)
{
return await _serviceClient.RefreshAccessToken(token);
}
} }
} }

+ 1
- 0
NemAnCore/Services/Interfaces/IAuthClientService.cs Просмотреть файл

Task<TokenResponse> GetAccessToken(TokenRequest tokenRequest); Task<TokenResponse> GetAccessToken(TokenRequest tokenRequest);
Task<CodeRequest> GetAuthParams(); Task<CodeRequest> GetAuthParams();
Task<UserInfoResponse> GetUserInfo(TokenMessage token); Task<UserInfoResponse> GetUserInfo(TokenMessage token);
Task<RefreshTokenResponse> RefreshAccessToken(TokenMessage token);
} }
} }

+ 21
- 0
NemAnCore/SpotifyHelper.cs Просмотреть файл

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 Просмотреть файл

using GrpcShared.Interfaces; using GrpcShared.Interfaces;
using Polly; using Polly;
using Polly.Extensions.Http; using Polly.Extensions.Http;
using GrpcShared.DTO.Auth;


var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);


// Retry two times after delay // Retry two times after delay
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt))); .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt)));
} }
builder.Services.AddOptions();
builder.Services.AddControllersWithViews(); builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();


builder.Services.AddCodeFirstGrpcReflection(); builder.Services.AddCodeFirstGrpcReflection();


var app = builder.Build(); var app = builder.Build();
builder.Services.Configure<CodeRequest>(builder.Configuration.GetSection("AuthParams"));


app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(); app.UseSwaggerUI();

IdentityProvider/Services/AuthService.cs → gRPCServer/Services/AuthService.cs Просмотреть файл

using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Diagnostics; using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.IO; using System.IO;
using System.Net;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;


namespace IdentityProvider.Services
namespace SpotifyService.Services
{ {
public class AuthService : IAuthService public class AuthService : IAuthService
{ {
_httpClientFactory = httpClientFactory; _httpClientFactory = httpClientFactory;
} }



public async Task<TokenResponse> GetAccessToken(TokenRequest tokenRequest) public async Task<TokenResponse> GetAccessToken(TokenRequest tokenRequest)
{ {
var http = _httpClientFactory.CreateClient();
var http = _httpClientFactory.CreateClient("HttpClient");


string url = "https://accounts.spotify.com/api/token"; string url = "https://accounts.spotify.com/api/token";
http.BaseAddress = new Uri(url); http.BaseAddress = new Uri(url);


var contents = JsonConvert.DeserializeObject<TokenResponse>(await response.Content.ReadAsStringAsync()); var contents = JsonConvert.DeserializeObject<TokenResponse>(await response.Content.ReadAsStringAsync());
return contents; return contents;
} }


public async Task<CodeRequest> GetAuthParams() public async Task<CodeRequest> GetAuthParams()


public async Task<UserInfoResponse> GetUserInfo(TokenMessage tokenM) 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())!; var userInfo = JsonConvert.DeserializeObject<UserInfoResponse>(await response.Content.ReadAsStringAsync())!;
userInfo.ResponseMsg = response.StatusCode;
return userInfo; 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 Просмотреть файл

var client = _httpClientFactory.CreateClient("HttpClient"); var client = _httpClientFactory.CreateClient("HttpClient");
string url = "me/player/currently-playing"; 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 Просмотреть файл

using Google.Rpc; using Google.Rpc;
using Grpc.Core; using Grpc.Core;
using GrpcShared; using GrpcShared;
using GrpcShared.DTO;
using GrpcShared.DTO.Search; using GrpcShared.DTO.Search;
using GrpcShared.DTO.Track.MultipleTrack; using GrpcShared.DTO.Track.MultipleTrack;
using GrpcShared.DTO.Track.SaveTracks; using GrpcShared.DTO.Track.SaveTracks;
string url = $"me/tracks/{query}"; 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 //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) public static string UriUtil(Dictionary<string, List<string>> param)

+ 6
- 0
gRPCServer/appsettings.json Просмотреть файл

"EndpointDefaults": { "EndpointDefaults": {
"Protocols": "Http1AndHttp2" "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"
} }
} }

Загрузка…
Отмена
Сохранить