Newer
Older
using System.Text;
using System.Text.Encodings.Web;
using FitConnect.Encryption;
using FitConnect.Services;
using FitConnect.Services.Interfaces;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
namespace FitConnect;
public class Router : IRouter {
private readonly FitConnectEnvironment _environment;
private readonly ILogger? _logger;
private readonly IRouteService _routeService;
private readonly ISelfServicePortalService _selfServicePortalService;
public Router(FitConnectEnvironment environment, ILogger? logger = null) {
_environment = environment;
_logger = logger;
_routeService = new RouteService(environment.RoutingUrl, "v1", logger);
_selfServicePortalService = new SelfServicePortalService(environment.SspUrl, "v1", logger);
public async Task<List<Route>> FindDestinationsAsync(string leiaKey, string? ags = null,
string? areaId = null, bool skipValidation = false) {
var routes = await _routeService.GetDestinationIdAsync(leiaKey, ags, ars, areaId);
if (skipValidation) return routes;
var validation = await _selfServicePortalService.GetValidationJwk();
foreach (var route in routes) {
var token = new JsonWebToken(route.DestinationSignature);
var key = validation.Keys.First(k => k.Kid == token.Kid);
var verifyJwt =
FitEncryption.VerifyJwt(route.DestinationSignature, key, out var _, _logger);
var submissionKey =
await GetSubmissionServiceValidationJwk(route.DestinationParameters.SubmissionUrl);
// Get Key from SubmissionAPI
var parametersJson =
Base64Url.Encode(
Encoding.UTF8.GetBytes(
JsonConvert.SerializeObject(route.DestinationParameters)));
var signature =
route.DestinationParametersSignature.Replace("..", $".{parametersJson}.");
// KID to check is in signature header kid
var header = JsonConvert.DeserializeObject<dynamic>(
Base64UrlEncoder.Decode(route.DestinationParametersSignature.Split('.')[0])
);
var kid = (string)header.kid;
Console.WriteLine("Looking for key with kid: " + kid);
verifyJwt &= FitEncryption.VerifyJwt(signature,
submissionKey.Keys.First(k => k.Kid == kid), out var _, _logger);
if (!verifyJwt) {
throw new Exception("Invalid signature");
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private async Task<JsonWebKeySet> GetSubmissionServiceValidationJwk(string baseUrl) {
var client = new HttpClient() {
BaseAddress = new Uri(baseUrl),
};
var result = await client.GetAsync("/.well-known/jwks.json");
return new JsonWebKeySet(await result.Content.ReadAsStringAsync());
}
/// </summary>
/// <param name="filter"></param>
/// <param name="totalCount"></param>
/// <param name="offset"></param>
/// <param name="limit"></param>
/// <returns></returns>
public IEnumerable<Area> GetAreas(string filter, out int totalCount, int offset = 0,
int limit = 100) {
var dto = _routeService.GetAreas(filter, offset, limit).Result;
totalCount = dto?.TotalCount ?? 0;
return dto?.Areas ?? new List<Area>();
}