From b8112bb2356f510b2f81c231b2cb49c65660db1d Mon Sep 17 00:00:00 2001
From: Klaus Fischer <klaus.fischer@eloware.com>
Date: Fri, 19 Aug 2022 12:07:24 +0200
Subject: [PATCH] Getting destination ID missing

---
 FitConnect/Services/SubmissionService.cs | 63 ++++++++++++++++++------
 1 file changed, 49 insertions(+), 14 deletions(-)

diff --git a/FitConnect/Services/SubmissionService.cs b/FitConnect/Services/SubmissionService.cs
index 8cfc982f..cf09fa93 100644
--- a/FitConnect/Services/SubmissionService.cs
+++ b/FitConnect/Services/SubmissionService.cs
@@ -155,7 +155,7 @@ internal class SubmissionService : RestCallService, ISubmissionService {
         // Download well known keys
         var valid = await ValidateSignature(events);
         // TODO: Check JSON Schema
-        valid &= await ValidateSchema(events, false);
+        // valid &= await ValidateSchema(events, false);
 
         if (!valid) {
             _logger?.LogError("Invalid SET, signature can not be verified");
@@ -226,18 +226,12 @@ internal class SubmissionService : RestCallService, ISubmissionService {
         return valid;
     }
 
-    private async Task<bool> ValidateSignature(EventLogDto? events) {
-        // Load Key from GET {{submission_api_url}}/v1/destinations/{{destinationId}}/keys/{{keyId}}
-        var keyIds = GetKeyIdsFromEvent(events);
+    private async Task<bool> ValidateSignature(EventLogDto events) {
+        var keys = await GetJsonWebKeysForEvent(events);
 
-        var keySet = new JsonWebKeySet(await Router.GetSubmissionServiceValidationJwk(_baseUrl));
-        var keys = _signatureValidationKey == null
-            ? keySet.Keys
-            : keySet.Keys.Append(_signatureValidationKey);
-        var valid = true;
-        foreach (var eventJson in events.EventLog) {
-            valid &= FitEncryption.VerifyJwt(eventJson, keys, logger: _logger);
-        }
+        var valid = events.EventLog?.Aggregate(true,
+            (current, eventJson) =>
+                current & FitEncryption.VerifyJwt(eventJson, keys, logger: _logger)) ?? true;
 
         if (!valid) {
             _logger?.LogDebug("Signature is invalid");
@@ -248,8 +242,49 @@ internal class SubmissionService : RestCallService, ISubmissionService {
         return valid;
     }
 
-    private IEnumerable<JsonWebKey> GetKeyIdsFromEvent(EventLogDto events) {
-        return new List<JsonWebKey>();
+    private async Task<IEnumerable<JsonWebKey>> GetJsonWebKeysForEvent(EventLogDto events) {
+        var keySet = new JsonWebKeySet(await Router.GetSubmissionServiceValidationJwk(_baseUrl));
+        var keys = _signatureValidationKey == null
+            ? keySet.Keys
+            : keySet.Keys.Append(_signatureValidationKey);
+
+        return (await GetKeyIdsFromEvent(events)).Union(keys);
+    }
+
+    private async Task<IEnumerable<JsonWebKey>> GetKeyIdsFromEvent(EventLogDto events) {
+        if (events.EventLog == null)
+            return new List<JsonWebKey>();
+
+        // Load Key from GET {{submission_api_url}}/v1/destinations/{{destinationId}}/keys/{{keyId}}
+        var keyIds = events.EventLog.Select(ExtractSubmissionIdFromEvent).ToList();
+
+        var result = new List<JsonWebKey>();
+        foreach (var (submission, keyId) in keyIds) {
+            try {
+                // TODO Get destinationId from submission
+                var destinationId = "aa3704d6-8bd7-4d40-a8af-501851f93934";
+                var keyJson = await RestCallForString($"/destinations/{destinationId}/keys/{keyId}",
+                    HttpMethod.Get);
+                result.Add(new JsonWebKey(keyJson));
+            }
+            catch (Exception e) {
+                _logger?.LogWarning(e, "Error loading key {KeyId}", keyId);
+            }
+        }
+
+        return result;
+    }
+
+    private (string submissionId, string keyId) ExtractSubmissionIdFromEvent(string events) {
+        var jwtParts = events.Split('.').Select(Base64UrlEncoder.Decode).ToList();
+
+        var header = JsonConvert.DeserializeObject<Dictionary<string, object>>(jwtParts[0]);
+        var payload = JsonConvert.DeserializeObject<Dictionary<string, object>>(jwtParts[1]);
+
+        var keyId = (string)header["kid"];
+        var submissionId = ((string)payload["sub"]).Split(':')[1];
+
+        return (submissionId, keyId);
     }
 
     public async Task GetValidationJwk() {
-- 
GitLab