Procházet zdrojové kódy

fixed bug with refresh token

master
anastasijasavov před 3 roky
rodič
revize
e079090c54

+ 1
- 1
GrpcShared/DTO/Db/DbRequestMessage.cs Zobrazit soubor

public class DbRequestMessage public class DbRequestMessage
{ {
[ProtoMember(1)] [ProtoMember(1)]
public string Id { get; set; }
public string? Id { get; set; }


} }
} }

+ 1
- 1
GrpcShared/DTO/Db/SaveTrackRequest.cs Zobrazit soubor

public class SaveTrackRequest : TrackResponse public class SaveTrackRequest : TrackResponse
{ {
[ProtoMember(1)] [ProtoMember(1)]
public string UserId { get; set; }
public string? UserId { get; set; }
} }
} }

+ 5
- 5
GrpcShared/DTO/Db/TrackResponse.cs Zobrazit soubor

public class TrackResponse public class TrackResponse
{ {
[ProtoMember(1)] [ProtoMember(1)]
public string Id { get; set; }
public string? Id { get; set; }
[ProtoMember(2)] [ProtoMember(2)]
public string Title { get; set; }
public string? Title { get; set; }
[ProtoMember(3)] [ProtoMember(3)]
public string Artist { get; set; }
public string? Artist { get; set; }
[ProtoMember(4)] [ProtoMember(4)]
public string Album { get; set; }
public string? Album { get; set; }
[ProtoMember(5)] [ProtoMember(5)]
public string TrackId { get; set; }
public string? TrackId { get; set; }
} }
} }

+ 3
- 3
GrpcShared/DTO/Db/UserResponse.cs Zobrazit soubor

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

+ 1
- 1
GrpcShared/DTO/VoidMessage.cs Zobrazit soubor

public class VoidMessage public class VoidMessage
{ {
[ProtoMember(1)] [ProtoMember(1)]
public string InsertedId { get; set; }
public string? InsertedId { get; set; }
} }
} }

+ 2
- 2
GrpcShared/GLOBALS.cs Zobrazit soubor

{ {
public static class GLOBALS public static class GLOBALS
{ {
public const String SPOTIFYURL = "https://api.spotify.com/v1/";
public const String MEDIATYPE = "application/json";
public const string SPOTIFYURL = "https://api.spotify.com/v1/";
public const string MEDIATYPE = "application/json";
} }
} }

+ 6
- 6
IdentityProvider/Models/TrackModel.cs Zobrazit soubor

{ {
[BsonId] [BsonId]
[BsonRepresentation(BsonType.ObjectId)] [BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Title { get; set; }
public string Artist { get; set; }
public string Album { get; set; }
public string UserId { get; set; }
public string TrackId { get; set; }
public string? Id { get; set; }
public string? Title { get; set; }
public string? Artist { get; set; }
public string? Album { get; set; }
public string? UserId { get; set; }
public string? TrackId { get; set; }
} }
} }

+ 3
- 3
IdentityProvider/Models/UserModel.cs Zobrazit soubor

{ {
[BsonId] [BsonId]
[BsonRepresentation(BsonType.ObjectId)] [BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Token { get; set; }
public string RefreshToken { get; set; }
public string? Id { get; set; }
public string? Token { get; set; }
public string? RefreshToken { get; set; }
} }
} }

+ 14
- 14
NemAnCore/Pages/Home.razor Zobrazit soubor



if (userResponse != null) if (userResponse != null)
{ {
tokenS = userResponse.Token;
refreshT = userResponse.RefreshToken;
tokenS = userResponse.Token!;
refreshT = userResponse.RefreshToken!;
} }
else else
{ {
await identityService.SaveTrackAsync(new GrpcShared.DTO.Db.SaveTrackRequest await identityService.SaveTrackAsync(new GrpcShared.DTO.Db.SaveTrackRequest
{ {
TrackId = track.Item.Id,
Title = track.Item.Name,
Album = track.Item.Album.Name,
Artist = track.Item.Artists[0].Name,
UserId = userId
TrackId = track.Item!.Id!,
Title = track.Item!.Name!,
Album = track.Item.Album!.Name!,
Artist = track.Item.Artists![0].Name!,
UserId = userId!
}); });


//var resp = await identityService.ListUsersAsync(new VoidMessage()); //var resp = await identityService.ListUsersAsync(new VoidMessage());


var tokenFromDb = await identityService.GetTokenByIdAsync(new GrpcShared.DTO.Db.DbRequestMessage var tokenFromDb = await identityService.GetTokenByIdAsync(new GrpcShared.DTO.Db.DbRequestMessage
{ {
Id = userId
Id = userId!
}); });


var trackByUser = await identityService.GetTrackByUserAsync(new GrpcShared.DTO.Db.DbRequestMessage var trackByUser = await identityService.GetTrackByUserAsync(new GrpcShared.DTO.Db.DbRequestMessage
{ {
Id = userId
Id = userId!
}); });
//await identityService.DeleteTrackAsync(new GrpcShared.DTO.Db.DbRequestMessage //await identityService.DeleteTrackAsync(new GrpcShared.DTO.Db.DbRequestMessage
// { // {
await identityService.SaveTrackAsync(new GrpcShared.DTO.Db.SaveTrackRequest await identityService.SaveTrackAsync(new GrpcShared.DTO.Db.SaveTrackRequest
{ {


TrackId = track.Item.Id,
Title = track.Item.Name,
Album = track.Item.Album.Name,
Artist = track.Item.Artists[0].Name,
UserId = userId
TrackId = track.Item.Id!,
Title = track.Item.Name!,
Album = track.Item.Album.Name!,
Artist = track.Item.Artists[0].Name!,
UserId = userId!
}); });
//find id from local storage //find id from local storage
//await identityService.DeleteUserAsync(new GrpcShared.DTO.Db.DbRequestMessage //await identityService.DeleteUserAsync(new GrpcShared.DTO.Db.DbRequestMessage

+ 1
- 1
NemAnCore/Pages/Login.razor Zobrazit soubor





@code { @code {
private string? message;


protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {

+ 1
- 1
SpotifyWorker/Worker.cs Zobrazit soubor

public class Worker : BackgroundService public class Worker : BackgroundService
{ {
private readonly ILogger<Worker> _logger; private readonly ILogger<Worker> _logger;
private HttpClient _httpClient;
private HttpClient? _httpClient;
public Worker(ILogger<Worker> logger) public Worker(ILogger<Worker> logger)
{ {
_logger = logger; _logger = logger;

+ 34
- 6
gRPCServer/HttpUtils/HttpUtils.cs Zobrazit soubor



if (req.StatusCode == System.Net.HttpStatusCode.Unauthorized) if (req.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{ {
string newToken = await SpotifyHelper.TryRefreshToken(authService, userResponse, identityService);
string? newToken = await TryRefreshToken(authService, userResponse, identityService);
if (newToken != null) if (newToken != null)
{ {
client.DefaultRequestHeaders.Remove(HeaderNames.Authorization);
client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + newToken); client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + newToken);
req = await client.GetAsync(url); req = await client.GetAsync(url);
response = JsonConvert.DeserializeObject<T>(await req.Content.ReadAsStringAsync())!; response = JsonConvert.DeserializeObject<T>(await req.Content.ReadAsStringAsync())!;




} }
public static async Task PutData(HttpClient client, string url, string userId, IIdentityService identityService, IAuthService authService)

public static async Task PutData(HttpClient client,
string url,
string userId,
IIdentityService identityService,
IAuthService authService)
{ {
try try
{ {
var tokenMessage = await identityService.GetTokenByIdAsync(new GrpcShared.DTO.Db.DbRequestMessage { Id = userId });
var tokenMessage = await identityService.GetTokenByIdAsync(new DbRequestMessage { Id = userId });
//add header //add header
client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + tokenMessage.Token); client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + tokenMessage.Token);


//get request //get request
var responseMessage = await client.PutAsync(url, null); var responseMessage = await client.PutAsync(url, null);


if(responseMessage.StatusCode == System.Net.HttpStatusCode.Unauthorized)
if (responseMessage.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{ {
string newToken = await SpotifyHelper.TryRefreshToken(authService, tokenMessage, identityService);

string? newToken = await TryRefreshToken(authService, tokenMessage, identityService);
if (newToken != null) if (newToken != null)
{ {
client.DefaultRequestHeaders.Remove(HeaderNames.Authorization);
client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + newToken);
responseMessage = await client.PutAsync(url, null); responseMessage = await client.PutAsync(url, null);
} }
} }
} }


} }


public static async Task<string?> TryRefreshToken(
IAuthService authService,
UserResponse user,
IIdentityService identityService)
{
var refreshResponse = await authService.RefreshAccessToken(user);

if (refreshResponse.AccessToken != null)
{
await identityService.UpdateTokenAsync(new UserResponse
{
Id = user.Id,
Token = refreshResponse.AccessToken,
RefreshToken = user.RefreshToken
});
return refreshResponse.AccessToken;
}
else return null;
}
} }
} }

+ 0
- 30
gRPCServer/HttpUtils/SpotifyHelper.cs Zobrazit soubor

using GrpcShared.DTO;
using GrpcShared.DTO.Db;
using GrpcShared.Interfaces;
using NemAnBlazor.Services.Interfaces;

namespace SpotifyService
{
public static class SpotifyHelper
{
public static async Task<string?> TryRefreshToken
(IAuthService authService,
UserResponse user,
IIdentityService identityService)
{
var refreshResponse = await authService.RefreshAccessToken(user);

if (refreshResponse.AccessToken != null)
{
await identityService.UpdateTokenAsync(new UserResponse
{
Id = user.Id,
Token = refreshResponse.AccessToken,
RefreshToken = user.RefreshToken
});
return refreshResponse.AccessToken;
}
else return null;
}
}
}

+ 22
- 18
gRPCServer/Services/AuthService.cs Zobrazit soubor

//using IdentityProvider.Protos.AuthService; //using IdentityProvider.Protos.AuthService;
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Grpc.Core;
using Grpc.Net.Client; using Grpc.Net.Client;
using GrpcShared; using GrpcShared;
using GrpcShared.DTO; using GrpcShared.DTO;
//AUTHORIZATION HEADER //AUTHORIZATION HEADER
http.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Basic " + Convert.ToBase64String(contentType)); http.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Basic " + Convert.ToBase64String(contentType));


////ACCEPT HEADER
//http.DefaultRequestHeaders.Accept.Add(
// new MediaTypeWithQualityHeaderValue("application/json"));

//BODY PARAMS //BODY PARAMS
var requestBody = new Dictionary<string, string>(); var requestBody = new Dictionary<string, string>();
requestBody["grant_type"] = tokenRequest.GrantType; requestBody["grant_type"] = tokenRequest.GrantType;
requestBody["code"] = tokenRequest.Code!; requestBody["code"] = tokenRequest.Code!;
requestBody["redirect_uri"] = tokenRequest.RedirectUri!; requestBody["redirect_uri"] = tokenRequest.RedirectUri!;


//REQUEST
var response = await http.PostAsync(url, new FormUrlEncodedContent(requestBody));
try
{
//REQUEST
var response = await http.PostAsync(url, new FormUrlEncodedContent(requestBody));

var contents = JsonConvert.DeserializeObject<TokenResponse>(await response.Content.ReadAsStringAsync())!;
return contents;
}
catch (RpcException e)
{
if (e.StatusCode == StatusCode.Cancelled)
{
return new TokenResponse();
}
throw;
}


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


} }


public async Task<UserInfoResponse> GetUserInfo(UserResponse tokenM) public async Task<UserInfoResponse> GetUserInfo(UserResponse tokenM)
{ {
// expired token example "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN" // expired token example "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN"
var http = _httpClientFactory.CreateClient("HttpClient"); var http = _httpClientFactory.CreateClient("HttpClient");


http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenM.Token!); http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenM.Token!);
//make this a method in http utils //make this a method in http utils
if (response.StatusCode == HttpStatusCode.Unauthorized) if (response.StatusCode == HttpStatusCode.Unauthorized)
{ {
//refresh the token //refresh the token
var refreshResponse = await RefreshAccessToken(tokenM); var refreshResponse = await RefreshAccessToken(tokenM);


http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", refreshResponse.AccessToken); http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", refreshResponse.AccessToken);
response = await http.GetAsync("me"); response = await http.GetAsync("me");



} }
//var headerError = response.Headers.WwwAuthenticate.; //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; userInfo.ResponseMsg = response.StatusCode;
return userInfo; return userInfo;


} }
{ {
var client = _httpClientFactory.CreateClient("HttpClient"); var client = _httpClientFactory.CreateClient("HttpClient");
client.BaseAddress = new Uri("https://accounts.spotify.com/api/token"); client.BaseAddress = new Uri("https://accounts.spotify.com/api/token");

//BODY PARAMS //BODY PARAMS
var requestBody = new Dictionary<string, string>(); var requestBody = new Dictionary<string, string>();
requestBody["refresh_token"] = tokenM.RefreshToken!; requestBody["refresh_token"] = tokenM.RefreshToken!;


//REQUEST //REQUEST
var response = await client.PostAsync("https://accounts.spotify.com/api/token", new FormUrlEncodedContent(requestBody)); var response = await client.PostAsync("https://accounts.spotify.com/api/token", new FormUrlEncodedContent(requestBody));

if (response.StatusCode == HttpStatusCode.Unauthorized)
{
//delete tokens from localstorage
//redirect to login
}
var contents = JsonConvert.DeserializeObject<RefreshTokenResponse>(await response.Content.ReadAsStringAsync())!; var contents = JsonConvert.DeserializeObject<RefreshTokenResponse>(await response.Content.ReadAsStringAsync())!;
return contents; return contents;
} }

+ 12
- 2
gRPCServer/Services/StatsService.cs Zobrazit soubor

{ {
string url = "me/player/currently-playing"; string url = "me/player/currently-playing";
var response = await HttpUtils<CurrentTrackResponse>.GetData(_httpClientFactory, url, message.UserId, _identityService, _authService);
var response = await HttpUtils<CurrentTrackResponse>
.GetData(_httpClientFactory,
url,
message.UserId!,
_identityService,
_authService);
return response; return response;


if (request.Limit == null && request.Offset != null) url += $"?offset={request.Offset}"; if (request.Limit == null && request.Offset != null) url += $"?offset={request.Offset}";
else url += request.Offset == null ? "" : $"&offset={request.Offset}"; else url += request.Offset == null ? "" : $"&offset={request.Offset}";


return await HttpUtils<TopItemResponse>.GetData(_httpClientFactory, url, request.UserId!, _identityService, _authService);
return await HttpUtils<TopItemResponse>
.GetData(_httpClientFactory,
url,
request.UserId!,
_identityService,
_authService);


} }
} }

+ 30
- 5
gRPCServer/Services/TrackService.cs Zobrazit soubor



string url = $"search?q={request.Query}&type={request.Type}"; string url = $"search?q={request.Query}&type={request.Type}";


return await HttpUtils.HttpUtils<SearchResponse>.GetData(_httpClientFactory, url, request.UserId!, _identityService, _authService);
return await HttpUtils.HttpUtils<SearchResponse>
.GetData(_httpClientFactory,
url,
request.UserId!,
_identityService,
_authService);




} }
{ {
string url = $"audio-features/{request.Id}"; string url = $"audio-features/{request.Id}";
return await HttpUtils.HttpUtils<SingleTrackResponse>.GetData(_httpClientFactory, url, request.UserId!, _identityService,_authService);
return await HttpUtils.HttpUtils<SingleTrackResponse>
.GetData(_httpClientFactory,
url,
request.UserId!,
_identityService,
_authService);
} }
public async Task<MultipleTrackResponse> ListMultipleTrackAsync(MultipleTrackRequest request) public async Task<MultipleTrackResponse> ListMultipleTrackAsync(MultipleTrackRequest request)
{ {
var query = UriUtil(param); var query = UriUtil(param);
string url = $"audio-features{query}"; string url = $"audio-features{query}";


return await HttpUtils.HttpUtils<MultipleTrackResponse>.GetData(_httpClientFactory, url, request.UserId, _identityService, _authService);
return await HttpUtils.HttpUtils<MultipleTrackResponse>
.GetData(_httpClientFactory,
url,
request.UserId!,
_identityService,
_authService);
} }
public async Task SaveTracks(SaveTracksRequest request) public async Task SaveTracks(SaveTracksRequest request)
{ {
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<StatusCodeMessage>.PutData(client, url, request.UserId!, _identityService, _authService);
await HttpUtils.HttpUtils<StatusCodeMessage>
.PutData(client,
url,
request.UserId!,
_identityService,
_authService);
} }
public static string UriUtil(Dictionary<string, List<string>> param) public static string UriUtil(Dictionary<string, List<string>> param)
string url = $"tracks/{request.TrackID}"; string url = $"tracks/{request.TrackID}";


return await HttpUtils.HttpUtils<TrackResponse>.GetData(_httpClientFactory, url, request.UserId!, _identityService, _authService);
return await HttpUtils.HttpUtils<TrackResponse>
.GetData(_httpClientFactory,
url,
request.UserId!,
_identityService,
_authService);
} }
} }
} }

Načítá se…
Zrušit
Uložit