Skip to content
Snippets Groups Projects
Commit 3e6beb80 authored by Klaus Fischer's avatar Klaus Fischer
Browse files

Clean up

parent 3742352b
No related branches found
No related tags found
1 merge request!9.NET-SDK: SET-Empfang inkl. Signaturprüfung - Ticket 562
Showing
with 231 additions and 104 deletions
...@@ -10,22 +10,22 @@ ...@@ -10,22 +10,22 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.7.0" /> <PackageReference Include="FluentAssertions" Version="6.7.0"/>
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0"/>
<PackageReference Include="NUnit" Version="3.13.2" /> <PackageReference Include="NUnit" Version="3.13.2"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" /> <PackageReference Include="NUnit3TestAdapter" Version="4.0.0"/>
<PackageReference Include="coverlet.collector" Version="3.1.0" /> <PackageReference Include="coverlet.collector" Version="3.1.0"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FitConnect\FitConnect.csproj" /> <ProjectReference Include="..\FitConnect\FitConnect.csproj"/>
<ProjectReference Include="..\MockContainer\MockContainer.csproj" /> <ProjectReference Include="..\MockContainer\MockContainer.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Certificates" /> <Folder Include="Certificates"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
......
...@@ -138,23 +138,42 @@ public class FitEncryption { ...@@ -138,23 +138,42 @@ public class FitEncryption {
public static bool VerifyJwt(string signature, string secret) => VerifyJwt(signature, public static bool VerifyJwt(string signature, string secret) => VerifyJwt(signature,
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret))); ILogger? logger = null) {
return VerifyJwt(signature,
new JsonWebKey(secret), logger);
}
public static bool VerifyJwt(string signature, SecurityKey key) { public static bool VerifyJwt(string signature, SecurityKey key) {
var tokenHandler = new JsonWebTokenHandler(); var tokenHandler = new JsonWebTokenHandler();
var result = tokenHandler.ValidateToken(signature, new TokenValidationParameters { var result = tokenHandler.ValidateToken(signature, new TokenValidationParameters {
ValidateIssuerSigningKey = true, ValidAlgorithms = new[] { "PS512" },
IssuerSigningKey = key, IssuerSigningKey = key,
ValidateIssuerSigningKey = true,
ValidateIssuer = false, ValidateIssuer = false,
ValidateAudience = false, ValidateAudience = false,
ValidateLifetime = false, ValidateLifetime = false,
ValidateActor = true,
ValidateSignatureLast = true,
ValidateTokenReplay = true,
ValidateWithLKG = true,
RequireAudience = true,
RefreshBeforeValidation = true,
RequireSignedTokens = true,
RequireExpirationTime = false,
IgnoreTrailingSlashWhenValidatingAudience = true,
TryAllIssuerSigningKeys = true
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later) // set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
// ClockSkew = TimeSpan.Zero // ClockSkew = TimeSpan.Zero
}); });
Console.WriteLine(result.Exception?.Message); Console.WriteLine(result.Exception?.Message);
logger?.LogWarning("Validation error {Error}", error);
else
logger?.LogInformation("JWT is valid");
return result.IsValid; return result.IsValid;
} }
} }
using System.IdentityModel.Tokens.Jwt;
using System.Security.Principal;
using System.Text;
using Jose; using Jose;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
// ReSharper disable RedundantExplicitArrayCreation // ReSharper disable RedundantExplicitArrayCreation
......
...@@ -11,28 +11,28 @@ ...@@ -11,28 +11,28 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac" Version="6.4.0" /> <PackageReference Include="Autofac" Version="6.4.0"/>
<PackageReference Include="IdentityModel" Version="6.0.0" /> <PackageReference Include="IdentityModel" Version="6.0.0"/>
<PackageReference Include="jose-jwt" Version="4.0.0" /> <PackageReference Include="jose-jwt" Version="4.0.0"/>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0"/>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1"/>
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="6.21.0" /> <PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="6.22.0"/>
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.21.0" /> <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.22.0"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
<PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.14" /> <PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.14"/>
<PackageReference Include="NJsonSchema" Version="10.7.2" /> <PackageReference Include="NJsonSchema" Version="10.7.2"/>
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.21.0" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.21.0"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="metadata.schema.json" /> <None Remove="metadata.schema.json"/>
<EmbeddedResource Include="metadata.schema.json" /> <EmbeddedResource Include="metadata.schema.json"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="FunctionalBaseClass.cs" /> <Compile Remove="FunctionalBaseClass.cs"/>
<Compile Remove="Models\OAuthAccessToken.cs" /> <Compile Remove="Models\OAuthAccessToken.cs"/>
<Compile Remove="DiContainer.cs" /> <Compile Remove="DiContainer.cs"/>
</ItemGroup> </ItemGroup>
</Project> </Project>
...@@ -7,7 +7,6 @@ namespace FitConnect.Models; ...@@ -7,7 +7,6 @@ namespace FitConnect.Models;
// } // }
public class FitConnectEnvironment { public class FitConnectEnvironment {
public static readonly FitConnectEnvironment Testing = new( public static readonly FitConnectEnvironment Testing = new(
"https://auth-testing.fit-connect.fitko.dev/token", "https://auth-testing.fit-connect.fitko.dev/token",
new[] { "https://submission-api-testing.fit-connect.fitko.dev" }, new[] { "https://submission-api-testing.fit-connect.fitko.dev" },
...@@ -47,9 +46,10 @@ public class FitConnectEnvironment { ...@@ -47,9 +46,10 @@ public class FitConnectEnvironment {
} }
/// <summary> /// <summary>
/// Self service portal URL /// Self service portal URL
/// </summary> /// </summary>
public string SspUrl { get; } public string SspUrl { get; }
/// <summary> /// <summary>
/// URL for receiving the OAuth token. /// URL for receiving the OAuth token.
/// </summary> /// </summary>
......
using System.Diagnostics.CodeAnalysis;
using System.Text; using System.Text;
using System.Text.Encodings.Web;
using FitConnect.Encryption; using FitConnect.Encryption;
using FitConnect.Models; using FitConnect.Models;
using FitConnect.Services; using FitConnect.Services;
...@@ -36,18 +34,36 @@ public class Router : IRouter { ...@@ -36,18 +34,36 @@ public class Router : IRouter {
foreach (var route in routes) { foreach (var route in routes) {
_logger?.LogInformation("Testing destination {DestinationId}", route.DestinationId);
// GET destination from here: https://dvdv-testsystem.governikus.de/dvdv-fitconnect/v1/destinations/{id
// var destination = await (new DvdvService("https://dvdv-testsystem.governikus.de/dvdv-fitconnect", logger: _logger)).GetDestinationJson(route.DestinationId);
var verifyJwt = await VerifyDestinationSignature(route); var verifyJwt = await VerifyDestinationSignature(route);
verifyJwt &= await VerifyDestinationParameters(route); verifyJwt &= await VerifyDestinationParameters(route);
if (!verifyJwt) { if (!verifyJwt) throw new Exception("Invalid signature");
throw new Exception($"Invalid signature");
}
} }
return routes; return routes;
} }
/// <summary>
/// Finding Areas
/// </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>();
}
private async Task<bool> VerifyDestinationParameters(Route route) { private async Task<bool> VerifyDestinationParameters(Route route) {
var submissionKey = var submissionKey =
await GetSubmissionServiceValidationJwk(route.DestinationParameters.SubmissionUrl); await GetSubmissionServiceValidationJwk(route.DestinationParameters.SubmissionUrl);
...@@ -83,31 +99,23 @@ public class Router : IRouter { ...@@ -83,31 +99,23 @@ public class Router : IRouter {
} }
/// <summary> /// <summary>
///
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private async Task<JsonWebKeySet> GetSubmissionServiceValidationJwk(string baseUrl) { public async Task<string> GetSubmissionServiceValidationJwk(string baseUrl) {
var client = new HttpClient() { var client = new HttpClient {
BaseAddress = new Uri(baseUrl), BaseAddress = new Uri(baseUrl)
}; };
var result = await client.GetAsync("/.well-known/jwks.json"); var result = await client.GetAsync("/.well-known/jwks.json");
return new JsonWebKeySet(await result.Content.ReadAsStringAsync()); return new JsonWebKeySet(await result.Content.ReadAsStringAsync());
} }
}
public class OrderedContractResolver : DefaultContractResolver {
/// <summary> protected override IList<JsonProperty> CreateProperties(Type type,
/// Finding Areas MemberSerialization memberSerialization) {
/// </summary> NamingStrategy = new CamelCaseNamingStrategy();
/// <param name="filter"></param> return base.CreateProperties(type, memberSerialization).OrderBy(p => p.PropertyName)
/// <param name="totalCount"></param> .ToList();
/// <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>();
} }
} }
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json;
namespace FitConnect.Services.Models.v1.Destination; namespace FitConnect.Services.Models.v1.Destination;
......
...@@ -99,9 +99,9 @@ public class Route { ...@@ -99,9 +99,9 @@ public class Route {
[JsonProperty("destinationName")] [JsonProperty("destinationName")]
public string DestinationName { get; set; } public string DestinationName { get; set; }
[System.Text.Json.Serialization.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore]
public string DestinationParameterString { get;set; } public string DestinationParameterString { get; set; }
} }
public class SubmissionSchema { public class SubmissionSchema {
......
using System.Net; using System.Net;
using System.Net.Http.Json;
using System.Runtime.CompilerServices;
using System.Security.Authentication; using System.Security.Authentication;
using FitConnect.Services.Interfaces; using FitConnect.Services.Interfaces;
using FitConnect.Services.Models; using FitConnect.Services.Models;
...@@ -66,7 +64,9 @@ internal class OAuthService : RestCallService, IOAuthService { ...@@ -66,7 +64,9 @@ internal class OAuthService : RestCallService, IOAuthService {
var response = await client.SendAsync(request); var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode) { if (response.IsSuccessStatusCode) {
var result = JsonConvert.DeserializeObject<OAuthAccessToken>(await response.Content.ReadAsStringAsync()); var result =
JsonConvert.DeserializeObject<OAuthAccessToken>(
await response.Content.ReadAsStringAsync());
if (result == null) if (result == null)
throw new AuthenticationException("Failed to authenticate"); throw new AuthenticationException("Failed to authenticate");
Token = result; Token = result;
...@@ -81,4 +81,4 @@ internal class OAuthService : RestCallService, IOAuthService { ...@@ -81,4 +81,4 @@ internal class OAuthService : RestCallService, IOAuthService {
public void EnsureAuthenticated() { public void EnsureAuthenticated() {
if (!IsAuthenticated) AuthenticateAsync().Wait(); if (!IsAuthenticated) AuthenticateAsync().Wait();
} }
} }
\ No newline at end of file
using System.Net; using System.Net;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
...@@ -38,9 +37,10 @@ internal class RestCallService : IRestCallService { ...@@ -38,9 +37,10 @@ internal class RestCallService : IRestCallService {
protected async Task<string> RestCallForString(string endpoint, HttpMethod method, protected async Task<string> RestCallForString(string endpoint, HttpMethod method,
string? body = null, string contentType = "application/json", string? body = null, string contentType = "application/json",
string accept = "application/json") => string accept = "application/json") {
await RestCallForString(new Uri($"{_baseUrl}{endpoint}"), method, body, contentType, return await RestCallForString(new Uri($"{_baseUrl}{endpoint}"), method, body, contentType,
accept); accept);
}
protected async Task<string> RestCallForString(Uri requestUri, HttpMethod method, protected async Task<string> RestCallForString(Uri requestUri, HttpMethod method,
string? body = null, string contentType = "application/json", string? body = null, string contentType = "application/json",
...@@ -67,7 +67,8 @@ internal class RestCallService : IRestCallService { ...@@ -67,7 +67,8 @@ internal class RestCallService : IRestCallService {
var response = await client.SendAsync(request); var response = await client.SendAsync(request);
if (response.Headers.Contains("jws-signature")) if (response.Headers.Contains("jws-signature"))
Console.WriteLine(response.Headers.GetValues("jws-signature").Aggregate((a,b)=>$"{a},{b}")); Console.WriteLine(response.Headers.GetValues("jws-signature")
.Aggregate((a, b) => $"{a},{b}"));
_logger?.LogDebug("Server call: {Method} {Uri} - {StatusCode}", method, request.RequestUri, _logger?.LogDebug("Server call: {Method} {Uri} - {StatusCode}", method, request.RequestUri,
response.StatusCode); response.StatusCode);
......
...@@ -41,4 +41,4 @@ public class RouteService : RestCallService, IRouteService { ...@@ -41,4 +41,4 @@ public class RouteService : RestCallService, IRouteService {
return result; return result;
} }
} }
\ No newline at end of file
using Jose; using FitConnect.Services.Interfaces;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
namespace FitConnect.Services; namespace FitConnect.Services;
public class SelfServicePortalService : RestCallService, ISelfServicePortalService { internal class SelfServicePortalService : RestCallService, ISelfServicePortalService {
public SelfServicePortalService(string baseUrl, string version = "v1", public SelfServicePortalService(string baseUrl, string version = "v1",
ILogger? logger = null) : base($"{baseUrl}", logger) { ILogger? logger = null) : base($"{baseUrl}", logger) {
} }
public async Task<JsonWebKeySet> GetSelfServiceValidationJwk() { public async Task<JsonWebKeySet> GetValidationJwk() {
var content = await RestCallForString("/.well-known/jwks.json", HttpMethod.Get); var content = await RestCallForString("/.well-known/jwks.json", HttpMethod.Get);
return new JsonWebKeySet(content); return new JsonWebKeySet(content);
} }
......
using System.Text.Encodings.Web;
using System.Text.Json;
using Newtonsoft.Json;
using FitConnect.Services.Interfaces; using FitConnect.Services.Interfaces;
using FitConnect.Services.Models.v1.Case; using FitConnect.Services.Models.v1.Case;
using FitConnect.Services.Models.v1.Submission; using FitConnect.Services.Models.v1.Submission;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using JsonSerializer = System.Text.Json.JsonSerializer; using Newtonsoft.Json;
namespace FitConnect.Services; namespace FitConnect.Services;
...@@ -70,7 +66,7 @@ internal class SubmissionService : RestCallService, ISubmissionService { ...@@ -70,7 +66,7 @@ internal class SubmissionService : RestCallService, ISubmissionService {
public async Task<SubmissionReducedDto?> SubmitSubmission(string submissionId, public async Task<SubmissionReducedDto?> SubmitSubmission(string submissionId,
SubmitSubmissionDto submitSubmission) { SubmitSubmissionDto submitSubmission) {
_oAuthService.EnsureAuthenticated(); _oAuthService.EnsureAuthenticated();
var body = JsonConvert.SerializeObject(submitSubmission, new JsonSerializerSettings() { var body = JsonConvert.SerializeObject(submitSubmission, new JsonSerializerSettings {
NullValueHandling = NullValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.Indented Formatting = Formatting.Indented
}); });
......
...@@ -8,21 +8,21 @@ ...@@ -8,21 +8,21 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DotNet.Testcontainers" Version="1.6.0" /> <PackageReference Include="DotNet.Testcontainers" Version="1.6.0"/>
<PackageReference Include="FluentAssertions" Version="6.7.0" /> <PackageReference Include="FluentAssertions" Version="6.7.0"/>
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" /> <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2"/>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0"/>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0"/>
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="6.21.0" /> <PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="6.22.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0"/>
<PackageReference Include="NUnit" Version="3.13.2" /> <PackageReference Include="NUnit" Version="3.13.2"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" /> <PackageReference Include="NUnit3TestAdapter" Version="4.0.0"/>
<PackageReference Include="coverlet.collector" Version="3.1.0" /> <PackageReference Include="coverlet.collector" Version="3.1.0"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FitConnect\FitConnect.csproj" /> <ProjectReference Include="..\FitConnect\FitConnect.csproj"/>
<ProjectReference Include="..\MockContainer\MockContainer.csproj" /> <ProjectReference Include="..\MockContainer\MockContainer.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
......
This diff is collapsed.
using System.Text.Encodings.Web; using Autofac;
using System.Text.Json;
using Newtonsoft.Json;
using Autofac;
using FitConnect.Encryption; using FitConnect.Encryption;
using FitConnect.Models.Api.Metadata; using FitConnect.Models.Api.Metadata;
using FitConnect.Services.Interfaces; using FitConnect.Services.Interfaces;
...@@ -11,7 +8,6 @@ using Microsoft.Extensions.Logging; ...@@ -11,7 +8,6 @@ using Microsoft.Extensions.Logging;
using Moq; using Moq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Data = FitConnect.Models.Data; using Data = FitConnect.Models.Data;
using JsonSerializer = System.Text.Json.JsonSerializer;
using Metadata = FitConnect.Models.Api.Metadata.Metadata; using Metadata = FitConnect.Models.Api.Metadata.Metadata;
using Route = FitConnect.Services.Models.v1.Routes.Route; using Route = FitConnect.Services.Models.v1.Routes.Route;
...@@ -135,7 +131,7 @@ public static class Container { ...@@ -135,7 +131,7 @@ public static class Container {
(string id, SubmitSubmissionDto dto) => { (string id, SubmitSubmissionDto dto) => {
Console.WriteLine( Console.WriteLine(
$@"Submitting submission {id} with $@"Submitting submission {id} with
{JsonConvert.SerializeObject(dto, new JsonSerializerSettings() { {JsonConvert.SerializeObject(dto, new JsonSerializerSettings {
NullValueHandling = NullValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.Indented Formatting = Formatting.Indented
})}"); })}");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment