Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion iSHARE/AccessToken/Args/AccessTokenRequestArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public AccessTokenRequestArgs(string requestUri, string clientId, string clientA

private static void ValidateArguments(string requestUri, string clientId, string clientAssertion)
{
static void ValidateSingle(string value, string nameOf)
void ValidateSingle(string value, string nameOf)
{
if (string.IsNullOrWhiteSpace(value))
{
Expand Down
6 changes: 4 additions & 2 deletions iSHARE/AccessToken/Responses/AccessTokenResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ public class AccessTokenResponse

public static async Task<AccessTokenResponse> FromHttpContentAsync(HttpContent httpContent)
{
await using var responseStream = await httpContent.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync<AccessTokenResponse>(responseStream);
using (var responseStream = await httpContent.ReadAsStreamAsync())
{
return await JsonSerializer.DeserializeAsync<AccessTokenResponse>(responseStream);
}
}
}
}
2 changes: 1 addition & 1 deletion iSHARE/Capabilities/Args/CapabilitiesRequestArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private static void ValidateArguments(
string schemeOwnerAccessToken,
string accessToken)
{
static void EnsureValidString(string name, string value)
void EnsureValidString(string name, string value)
{
if (string.IsNullOrWhiteSpace(value))
{
Expand Down
4 changes: 2 additions & 2 deletions iSHARE/IShareSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
{
public interface IShareSettings
{
public string SchemeOwnerUrl { get; }
string SchemeOwnerUrl { get; }

/// <summary>
/// Your organization's EORI number. Used to verify if JWT token audience is correct.
/// </summary>
public string Eori { get; }
string Eori { get; }
}
}
8 changes: 4 additions & 4 deletions iSHARE/IdentityProviders/IdentityProvidersQueryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private static string FormatIdpUri(string uri)

private async Task<ICollection<Party>> RetrieveIdpPartiesAsync(string accessToken, CancellationToken token)
{
static bool IsValidIdp(Party party)
bool IsValidIdp(Party party)
{
var certification = party.Certifications.FirstOrDefault(c => c.Role == IdentityProvider);
if (certification == null)
Expand Down Expand Up @@ -93,10 +93,10 @@ private async Task<List<Party>> RetrieveAllPartiesAsync(
PartiesResponse partiesResponse,
CancellationToken token)
{
static int CalculateTotalPages(PartiesResponse partiesResponse)
int CalculateTotalPages(PartiesResponse innerPartiesResponse)
{
var pagesCount = partiesResponse.Count / 10;
if (partiesResponse.Count % 10 != 0)
var pagesCount = innerPartiesResponse.Count / 10;
if (innerPartiesResponse.Count % 10 != 0)
{
pagesCount++;
}
Expand Down
26 changes: 14 additions & 12 deletions iSHARE/Internals/GenericHttpClient/TokenResponseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,22 @@ private static string AppendParametersIfNeeded(

private static async Task<string> ExtractToken(HttpContent httpContent, CancellationToken token)
{
await using var responseStream = await httpContent.ReadAsStreamAsync();
var response = await JsonSerializer.DeserializeAsync<Dictionary<string, string>>(
responseStream,
cancellationToken: token);

var tokenPair = response.FirstOrDefault(x => x.Key.EndsWith("_token"));
if (WasTokenFound(tokenPair))
using (var responseStream = await httpContent.ReadAsStreamAsync())
{
return tokenPair.Value;
}
var response = await JsonSerializer.DeserializeAsync<Dictionary<string, string>>(
responseStream,
cancellationToken: token);

var msg = $"Token with suffix '_token' was not found.{Environment.NewLine}" +
$"Response: {JsonSerializer.Serialize(response)}";
throw new TokenNotFoundException(msg);
var tokenPair = response.FirstOrDefault(x => x.Key.EndsWith("_token"));
if (WasTokenFound(tokenPair))
{
return tokenPair.Value;
}

var msg = $"Token with suffix '_token' was not found.{Environment.NewLine}" +
$"Response: {JsonSerializer.Serialize(response)}";
throw new TokenNotFoundException(msg);
}
}

private static bool WasTokenFound(KeyValuePair<string, string> tokenPair)
Expand Down
2 changes: 1 addition & 1 deletion iSHARE/Parties/PartiesQueryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void AddParameter(string name, bool? value)
AddParameter("certified_only", args.CertifiedOnly);
AddParameter("active_only", args.ActiveOnly);
AddParameterIfExists("certificate_subject_name", args.CertificateSubjectName);
AddParameterIfExists("page", args.Page == null ? null : args.Page.ToString());
AddParameterIfExists("page", args.Page?.ToString());
AddParameterIfExists("date_time", args.DateTime == null ? null : args.DateTime.Value.ToString("s") + "Z");

return dictionary;
Expand Down
2 changes: 1 addition & 1 deletion iSHARE/TokenConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static T DeserializeClaim<T>(JwtSecurityToken jwtToken, string claimName)

private static string BuildArrayString<T>(Claim[] claims)
{
return $"[{string.Join(',', claims.Select(x => x.Value))}]";
return $"[{string.Join(",", claims.Select(x => x.Value))}]";
}

private static void ValidateArguments(JwtSecurityToken jwtToken, string claimName)
Expand Down
8 changes: 5 additions & 3 deletions iSHARE/TokenValidator/CertificateUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ public static string GetSha256(this X509Certificate2 cert)
throw new ArgumentNullException(nameof(cert));
}

using var hasher = new SHA256Managed();
var hashBytes = hasher.ComputeHash(cert.RawData);
using (var hasher = new SHA256Managed())
{
var hashBytes = hasher.ComputeHash(cert.RawData);

return BitConverter.ToString(hashBytes).Replace("-", "", StringComparison.CurrentCultureIgnoreCase);
return BitConverter.ToString(hashBytes).Replace("-", "");
}
}
}
}
12 changes: 6 additions & 6 deletions iSHARE/TokenValidator/DecodedJwtValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,18 @@ private static TokenValidationParameters CreateTokenValidationParameters(

private static bool IsHeaderInvalid(JwtHeader header)
{
static bool IsAlgInvalid(string alg) => alg != SecurityAlgorithms.RsaSha256;
static bool IsTypInvalid(string typ) => typ != "JWT";
bool IsAlgInvalid(string alg) => alg != SecurityAlgorithms.RsaSha256;
bool IsTypInvalid(string typ) => typ != "JWT";

return IsAlgInvalid(header.Alg) || IsTypInvalid(header.Typ);
}

private static bool IsPayloadInvalid(JwtPayload payload)
{
static bool IsSubInvalid(string sub, string iss) => sub != iss;
static bool IsJtiInvalid(string jti) => string.IsNullOrWhiteSpace(jti);
static bool WasIssuedBeforeNow(int? iat) => iat == null || DateTime.UtcNow.ToEpochTime() < iat;
static bool HasIncorrectExpiration(int? iat, int? exp) => exp - iat != 30;
bool IsSubInvalid(string sub, string iss) => sub != iss;
bool IsJtiInvalid(string jti) => string.IsNullOrWhiteSpace(jti);
bool WasIssuedBeforeNow(int? iat) => iat == null || DateTime.UtcNow.ToEpochTime() < iat;
bool HasIncorrectExpiration(int? iat, int? exp) => exp - iat != 30;

return IsSubInvalid(payload.Sub, payload.Iss)
|| IsJtiInvalid(payload.Jti)
Expand Down
48 changes: 25 additions & 23 deletions iSHARE/TokenValidator/JwtCertificateValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,36 @@ public async Task<bool> IsValidAsync(

private bool IsChainValid(X509Certificate2 primaryCertificate, X509Certificate2[] additionalCertificates)
{
using var chain = new X509Chain();
chain.ChainPolicy.ExtraStore.AddRange(additionalCertificates);

chain.ChainPolicy.RevocationMode = _testCaStrategy.GetRevocationMode();
var isValid = chain.Build(primaryCertificate);
if (isValid)
using (var chain = new X509Chain())
{
return true;
}
chain.ChainPolicy.ExtraStore.AddRange(additionalCertificates);

var statuses = chain
.ChainElements
.OfType<X509ChainElement>()
.SelectMany(c => c.ChainElementStatus)
.ToArray();
chain.ChainPolicy.RevocationMode = _testCaStrategy.GetRevocationMode();
var isValid = chain.Build(primaryCertificate);
if (isValid)
{
return true;
}

if (_testCaStrategy.ShouldErrorsBeIgnored(statuses))
{
// allow untrusted root
// for the places where the iSHARE root is not installed (build server)
// even if it's untrusted, trusted list service will do the last check to assure it's actually trusted
isValid = true;
}
var statuses = chain
.ChainElements
.OfType<X509ChainElement>()
.SelectMany(c => c.ChainElementStatus)
.ToArray();

_logger.LogInformation(
"Chain validation status information {results}.", statuses.Select(c => c.StatusInformation).ToList());
if (_testCaStrategy.ShouldErrorsBeIgnored(statuses))
{
// allow untrusted root
// for the places where the iSHARE root is not installed (build server)
// even if it's untrusted, trusted list service will do the last check to assure it's actually trusted
isValid = true;
}

return isValid;
_logger.LogInformation(
"Chain validation status information {results}.", statuses.Select(c => c.StatusInformation).ToList());

return isValid;
}
}

private async Task<bool> DoesCertificateBelongToParty(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,33 +74,35 @@ private TokenValidationArgs CreateTokenValidationArgs(AssertionModel assertionMo

private bool IsChainValid(X509Certificate2 primaryCertificate, X509Certificate2[] additionalCertificates)
{
using var chain = new X509Chain();
chain.ChainPolicy.ExtraStore.AddRange(additionalCertificates);

chain.ChainPolicy.RevocationMode = _testCaStrategy.GetRevocationMode();
var isValidByPolicy = chain.Build(primaryCertificate);
if (isValidByPolicy)
using (var chain = new X509Chain())
{
return true;
}
chain.ChainPolicy.ExtraStore.AddRange(additionalCertificates);

var statuses = chain
.ChainElements
.OfType<X509ChainElement>()
.SelectMany(c => c.ChainElementStatus)
.ToList();
chain.ChainPolicy.RevocationMode = _testCaStrategy.GetRevocationMode();
var isValidByPolicy = chain.Build(primaryCertificate);
if (isValidByPolicy)
{
return true;
}

if (_testCaStrategy.ShouldErrorsBeIgnored(statuses))
{
// allow untrusted root
// for the places where the iSHARE root is not installed (build server)
isValidByPolicy = true;
}
var statuses = chain
.ChainElements
.OfType<X509ChainElement>()
.SelectMany(c => c.ChainElementStatus)
.ToList();

_logger.LogInformation(
"Chain validation status information {results}.", statuses.Select(c => c.StatusInformation).ToList());
if (_testCaStrategy.ShouldErrorsBeIgnored(statuses))
{
// allow untrusted root
// for the places where the iSHARE root is not installed (build server)
isValidByPolicy = true;
}

return isValidByPolicy;
_logger.LogInformation(
"Chain validation status information {results}.", statuses.Select(c => c.StatusInformation).ToList());

return isValidByPolicy;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace iSHARE.TokenValidator.SchemeOwner.TestCaStrategy
/// </summary>
internal interface ITestCaStrategy
{
public X509RevocationMode GetRevocationMode();
X509RevocationMode GetRevocationMode();

public bool ShouldErrorsBeIgnored(ICollection<X509ChainStatus> statuses);
bool ShouldErrorsBeIgnored(ICollection<X509ChainStatus> statuses);
}
}
3 changes: 2 additions & 1 deletion iSHARE/iSHARE.csproj
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.5" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.6.0" />
<PackageReference Include="System.Text.Json" Version="4.7.2" />
</ItemGroup>

</Project>