62 lines
2.1 KiB
C#
62 lines
2.1 KiB
C#
using OED.Api.Core.Interfaces.Services;
|
|
|
|
namespace OED.Api.Infrastructure.Esi;
|
|
|
|
public interface IEsiTokenRefreshService
|
|
{
|
|
Task<string> RefreshAsync(long characterId);
|
|
}
|
|
|
|
public class EsiTokenRefreshService(
|
|
IHttpClientFactory httpClientFactory,
|
|
ITokenStore tokenStore,
|
|
IConfiguration config
|
|
) : IEsiTokenRefreshService
|
|
{
|
|
public async Task<string> RefreshAsync(long characterId)
|
|
{
|
|
var refreshToken = await tokenStore.GetRefreshTokenAsync(characterId)
|
|
?? throw new InvalidOperationException($"No refresh token found for character {characterId}");
|
|
|
|
var clientId = config["Eve:ClientId"]!;
|
|
var secretKey = config["Eve:SecretKey"]!;
|
|
|
|
var credentials = Convert.ToBase64String(
|
|
System.Text.Encoding.UTF8.GetBytes($"{clientId}:{secretKey}")
|
|
);
|
|
|
|
var client = httpClientFactory.CreateClient();
|
|
var request = new HttpRequestMessage(HttpMethod.Post, "https://login.eveonline.com/v2/oauth/token");
|
|
request.Headers.Add("Authorization", $"Basic {credentials}");
|
|
request.Content = new FormUrlEncodedContent(new Dictionary<string, string>
|
|
{
|
|
["grant_type"] = "refresh_token",
|
|
["refresh_token"] = refreshToken
|
|
});
|
|
|
|
var response = await client.SendAsync(request);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<EsiTokenResponse>()
|
|
?? throw new InvalidOperationException("Empty token response from EVE SSO");
|
|
|
|
// Always overwrite — EVE may rotate the refresh token
|
|
await tokenStore.SetRefreshTokenAsync(characterId, result.RefreshToken);
|
|
await tokenStore.SetAccessTokenAsync(characterId, result.AccessToken, TimeSpan.FromSeconds(result.ExpiresIn - 30));
|
|
|
|
return result.AccessToken;
|
|
}
|
|
}
|
|
|
|
public record EsiTokenResponse(
|
|
string access_token,
|
|
int expires_in,
|
|
string token_type,
|
|
string refresh_token
|
|
)
|
|
{
|
|
public string AccessToken => access_token;
|
|
public int ExpiresIn => expires_in;
|
|
public string RefreshToken => refresh_token;
|
|
}
|