Skip to content

Commit

Permalink
Merge pull request #964 from ITfoxtec/test
Browse files Browse the repository at this point in the history
Test
  • Loading branch information
Revsgaard authored Oct 3, 2024
2 parents e359ac4 + d588a96 commit ca30d69
Show file tree
Hide file tree
Showing 18 changed files with 145 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ public TMyTenantLogUsageController(TelemetryScopedLogger logger, UsageLogLogic u
{
logRequest.TrackName = logRequest.TrackName.ToLower();
}
else
{
logRequest.TrackName = null;
}

var logResponse = await usageLogLogic.GetTrackUsageLog(logRequest, RouteBinding.TenantName, logRequest.TrackName, isMasterTrack: true);
return Ok(logResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,18 @@ public TTenantLogUsageController(TelemetryScopedLogger logger, UsageLogLogic usa
if (!logRequest.TenantName.IsNullOrWhiteSpace())
{
logRequest.TenantName = logRequest.TenantName.ToLower();
if (!logRequest.TrackName.IsNullOrWhiteSpace())
{
logRequest.TrackName = logRequest.TrackName.ToLower();
}
else
{
logRequest.TrackName = null;
}
}
else
{
logRequest.TenantName = null;
}
if (!logRequest.TrackName.IsNullOrWhiteSpace())
{
logRequest.TrackName = logRequest.TrackName.ToLower();
}
else
{
logRequest.TrackName = null;
}

Expand Down
2 changes: 1 addition & 1 deletion src/FoxIDs.Control/FoxIDs.Control.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>1.10.8</Version>
<Version>1.10.9</Version>
<RootNamespace>FoxIDs</RootNamespace>
<Authors>Anders Revsgaard</Authors>
<Company>ITfoxtec</Company>
Expand Down
9 changes: 1 addition & 8 deletions src/FoxIDs.Control/Logic/Logs/LogOpenSearchLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,14 +254,7 @@ private async Task<IEnumerable<OpenSearchLogItem>> LoadLogsAsync(Api.LogRequest

private string GetIndexName()
{
var lifetime = settings.OpenSearch.LogLifetime.GetLifetimeInDays();

if (RouteBinding?.PlanLogLifetime != null)
{
lifetime = RouteBinding.PlanLogLifetime.Value.GetLifetimeInDays();
}

return $"{Constants.Logs.LogName}-{lifetime}d*";
return $"{Constants.Logs.LogName}*";
}

private IBoolQuery GetQuery(BoolQueryDescriptor<OpenSearchLogItem> boolQuery, Api.LogRequest logRequest, (DateTime start, DateTime end) queryTimeRange)
Expand Down
21 changes: 5 additions & 16 deletions src/FoxIDs.Control/Logic/Logs/UsageLogOpenSearchLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ private async Task<FiltersAggregate> LoadUsageEventsAsync(string tenantName, str
}

var response = await openSearchClient.SearchAsync<OpenSearchLogItem>(s => s
.Index(GetIndexName(Constants.Logs.IndexName.Events))
.Index(GetIndexName())
.Size(0)
.Query(q => q
.Bool(b => GetQuery(b, tenantName, trackName, queryTimeRange)))
Expand All @@ -191,17 +191,10 @@ private async Task<FiltersAggregate> LoadUsageEventsAsync(string tenantName, str

return response.Aggregations.Values.FirstOrDefault() as FiltersAggregate;
}

private string GetIndexName(string logIndexName)
{
var lifetime = settings.OpenSearch.LogLifetime.GetLifetimeInDays();

if (RouteBinding?.PlanLogLifetime != null)
{
lifetime = RouteBinding.PlanLogLifetime.Value.GetLifetimeInDays();
}

return $"{Constants.Logs.LogName}-{lifetime}d-{logIndexName}*";
private string GetIndexName()
{
return $"{Constants.Logs.LogName}*";
}

private IBoolQuery GetQuery(BoolQueryDescriptor<OpenSearchLogItem> boolQuery, string tenantName, string trackName, (DateTime start, DateTime end) queryTimeRange)
Expand All @@ -216,11 +209,7 @@ private IBoolQuery GetQuery(BoolQueryDescriptor<OpenSearchLogItem> boolQuery, st
}
else if (!tenantName.IsNullOrWhiteSpace())
{
boolQuery = boolQuery.Must(m => m.Term(t => t.TenantName, tenantName) && m.Exists(e => e.Field(f => f.TrackName)));
}
else if (!trackName.IsNullOrWhiteSpace())
{
boolQuery = boolQuery.Must(m => m.Exists(e => e.Field(f => f.TenantName)) && m.Term(t => t.TrackName, trackName));
boolQuery = boolQuery.Must(m => m.Term(t => t.TenantName, tenantName));
}

return boolQuery;
Expand Down
2 changes: 1 addition & 1 deletion src/FoxIDs.ControlClient/FoxIDs.ControlClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>1.10.8</Version>
<Version>1.10.9</Version>
<RootNamespace>FoxIDs.Client</RootNamespace>
<Authors>Anders Revsgaard</Authors>
<Company>ITfoxtec</Company>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ public class UsageLogRequestViewModel
[Display(Name = "Usage types")]
public List<string> IncludeTypes { get; set; } = new List<string> { UsageLogIncludeTypes.Tenants, UsageLogIncludeTypes.Tracks, UsageLogIncludeTypes.Users, UsageLogIncludeTypes.Logins, UsageLogIncludeTypes.TokenRequests };

[Display(Name = "Select one tenant by full tenant name")]
[Display(Name = "Select tenant by full tenant name")]
public string TenantName { get; set; }

[Display(Name = "Select one environment by full environment name")]
[Display(Name = "Select environment by full environment name")]
public string TrackName { get; set; }
}
}
4 changes: 2 additions & 2 deletions src/FoxIDs.ControlClient/Pages/LogUsages.razor
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
<FInputCheckboxSelect Items="IncludeTypeItems" SelectedItems="usageLogRequestForm.Model.IncludeTypes" For="@(() => usageLogRequestForm.Model.IncludeTypes)" />
@if (IsMasterTenant)
{
<FInputText @bind-Value="usageLogRequestForm.Model.TrackName" For="@(() => usageLogRequestForm.Model.TrackName)" />
<FInputTextFilter @bind-Value="usageLogRequestForm.Model.TenantName" For="@(() => usageLogRequestForm.Model.TenantName)" />
<FInputText @bind-Value="usageLogRequestForm.Model.TenantName" For="@(() => usageLogRequestForm.Model.TenantName)" />
<FInputTextFilter @bind-Value="usageLogRequestForm.Model.TrackName" For="@(() => usageLogRequestForm.Model.TrackName)" />
}
else @if (IsMasterTrack)
{
Expand Down
2 changes: 1 addition & 1 deletion src/FoxIDs.ControlShared/FoxIDs.ControlShared.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>1.10.8</Version>
<Version>1.10.9</Version>
<RootNamespace>FoxIDs</RootNamespace>
<Authors>Anders Revsgaard</Authors>
<Company>ITfoxtec</Company>
Expand Down
2 changes: 1 addition & 1 deletion src/FoxIDs.Shared/FoxIDs.Shared.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>1.10.8</Version>
<Version>1.10.9</Version>
<RootNamespace>FoxIDs</RootNamespace>
<Authors>Anders Revsgaard</Authors>
<Company>ITfoxtec</Company>
Expand Down
4 changes: 2 additions & 2 deletions src/FoxIDs.SharedBase/FoxIDs.SharedBase.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>1.10.8</Version>
<Version>1.10.9</Version>
<RootNamespace>FoxIDs</RootNamespace>
<Authors>Anders Revsgaard</Authors>
<Company>ITfoxtec</Company>
<Copyright>Copyright © 2024</Copyright>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ITfoxtec.Identity" Version="2.10.2" />
<PackageReference Include="ITfoxtec.Identity" Version="2.10.3" />
<PackageReference Include="ITfoxtec.Identity.Saml2" Version="4.12.7" />
<PackageReference Include="Microsoft.AspNetCore.Components.DataAnnotations.Validation" Version="3.2.0-rc1.20223.4" />
<PackageReference Include="System.Formats.Asn1" Version="8.0.1" />
Expand Down
2 changes: 1 addition & 1 deletion src/FoxIDs/FoxIDs.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>1.10.8</Version>
<Version>1.10.9</Version>
<RootNamespace>FoxIDs</RootNamespace>
<Authors>Anders Revsgaard</Authors>
<Company>ITfoxtec</Company>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public static IServiceCollection AddLogic(this IServiceCollection services, Sett
services.AddTransient<HrdLogic>();
services.AddTransient<SessionLoginUpPartyLogic>();
services.AddTransient<SessionUpPartyLogic>();
services.AddTransient<StateUpPartyLogic>();
services.AddTransient<ClaimTransformLogic>();
services.AddTransient<DynamicElementLogic>();

Expand Down
24 changes: 22 additions & 2 deletions src/FoxIDs/Logic/Oidc/OidcRpInitiatedLogoutUpLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,19 @@ public class OidcRpInitiatedLogoutUpLogic<TParty, TClient> : LogicSequenceBase w
private readonly ITenantDataRepository tenantDataRepository;
private readonly SequenceLogic sequenceLogic;
private readonly SessionUpPartyLogic sessionUpPartyLogic;
private readonly StateUpPartyLogic stateUpPartyLogic;
private readonly SingleLogoutDownLogic singleLogoutDownLogic;
private readonly OAuthRefreshTokenGrantDownLogic<OAuthDownClient, OAuthDownScope, OAuthDownClaim> oauthRefreshTokenGrantLogic;
private readonly SecurityHeaderLogic securityHeaderLogic;

public OidcRpInitiatedLogoutUpLogic(TelemetryScopedLogger logger, IServiceProvider serviceProvider, ITenantDataRepository tenantDataRepository, SequenceLogic sequenceLogic, SessionUpPartyLogic sessionUpPartyLogic, SingleLogoutDownLogic singleLogoutDownLogic, OAuthRefreshTokenGrantDownLogic<OAuthDownClient, OAuthDownScope, OAuthDownClaim> oauthRefreshTokenGrantLogic, SecurityHeaderLogic securityHeaderLogic, IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor)
public OidcRpInitiatedLogoutUpLogic(TelemetryScopedLogger logger, IServiceProvider serviceProvider, ITenantDataRepository tenantDataRepository, SequenceLogic sequenceLogic, SessionUpPartyLogic sessionUpPartyLogic, StateUpPartyLogic stateUpPartyLogic, SingleLogoutDownLogic singleLogoutDownLogic, OAuthRefreshTokenGrantDownLogic<OAuthDownClient, OAuthDownScope, OAuthDownClaim> oauthRefreshTokenGrantLogic, SecurityHeaderLogic securityHeaderLogic, IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor)
{
this.logger = logger;
this.serviceProvider = serviceProvider;
this.tenantDataRepository = tenantDataRepository;
this.sequenceLogic = sequenceLogic;
this.sessionUpPartyLogic = sessionUpPartyLogic;
this.stateUpPartyLogic = stateUpPartyLogic;
this.singleLogoutDownLogic = singleLogoutDownLogic;
this.oauthRefreshTokenGrantLogic = oauthRefreshTokenGrantLogic;
this.securityHeaderLogic = securityHeaderLogic;
Expand All @@ -53,6 +55,7 @@ await sequenceLogic.SaveSequenceDataAsync(new OidcUpSequenceData
SessionId = logoutRequest.SessionId,
RequireLogoutConsent = logoutRequest.RequireLogoutConsent,
PostLogoutRedirect = logoutRequest.PostLogoutRedirect,
ClientId = ResolveClientId(party)
});

return HttpContext.GetUpPartyUrl(partyLink.Name, Constants.Routes.OAuthUpJumpController, Constants.Endpoints.UpJump.EndSessionRequest, includeSequence: true, partyBindingPattern: party.PartyBindingPattern).ToRedirectResult(RouteBinding.DisplayName);
Expand Down Expand Up @@ -111,12 +114,19 @@ public async Task<IActionResult> EndSessionRequestAsync(string partyId)
var postLogoutRedirectUrl = HttpContext.GetUpPartyUrl(party.Name, Constants.Routes.OAuthController, Constants.Endpoints.EndSessionResponse, partyBindingPattern: party.PartyBindingPattern);
var rpInitiatedLogoutRequest = new RpInitiatedLogoutRequest
{
IdTokenHint = session.IdToken,
ClientId = oidcUpSequenceData.ClientId,
PostLogoutRedirectUri = postLogoutRedirectUrl,
State = await sequenceLogic.CreateExternalSequenceIdAsync(),
IdTokenHint = session.IdToken
};
logger.ScopeTrace(() => $"AuthMethod, End session request '{rpInitiatedLogoutRequest.ToJson()}'.", traceType: TraceTypes.Message);
var nameValueCollection = rpInitiatedLogoutRequest.ToDictionary();
if(party.Issuers.Any(i => i.Contains("amazonaws.com", StringComparison.OrdinalIgnoreCase)))
{
nameValueCollection.Add("logout_uri", rpInitiatedLogoutRequest.PostLogoutRedirectUri);
await stateUpPartyLogic.CreateOrUpdateStateCookieAsync(party, rpInitiatedLogoutRequest.State);
logger.ScopeTrace(() => $"AuthMethod, End session add custom 'logout_uri={rpInitiatedLogoutRequest.PostLogoutRedirectUri}' parameter and state cookie for Amazon AWS Cognito.");
}
logger.ScopeTrace(() => $"AuthMethod, End session request URL '{party.Client.EndSessionUrl}'.");
logger.ScopeTrace(() => "AuthMethod, Sending OIDC End session request.", triggerEvent: true);
return await nameValueCollection.ToRedirectResultAsync(party.Client.EndSessionUrl, RouteBinding.DisplayName);
Expand Down Expand Up @@ -147,6 +157,11 @@ private async Task<IActionResult> EndSessionResponseAsync(OidcUpParty party)
var rpInitiatedLogoutResponse = queryDictionary.ToObject<RpInitiatedLogoutResponse>();
logger.ScopeTrace(() => $"AuthMethod, End session response '{rpInitiatedLogoutResponse.ToJson()}'.", traceType: TraceTypes.Message);
rpInitiatedLogoutResponse.Validate();

if (party.Issuers.Any(i => i.Contains("amazonaws.com", StringComparison.OrdinalIgnoreCase)))
{
rpInitiatedLogoutResponse.State = await stateUpPartyLogic.GetAndDeleteStateCookieAsync(party);
}
if (rpInitiatedLogoutResponse.State.IsNullOrEmpty()) throw new ArgumentNullException(nameof(rpInitiatedLogoutResponse.State), rpInitiatedLogoutResponse.GetTypeName());

await sequenceLogic.ValidateExternalSequenceIdAsync(rpInitiatedLogoutResponse.State);
Expand Down Expand Up @@ -212,5 +227,10 @@ private async Task<IActionResult> LogoutResponseDownAsync(OidcUpSequenceData seq
throw new StopSequenceException("Falling logout response down", ex);
}
}

protected string ResolveClientId(OidcUpParty party)
{
return !party.Client.SpClientId.IsNullOrWhiteSpace() ? party.Client.SpClientId : party.Client.ClientId;
}
}
}
19 changes: 13 additions & 6 deletions src/FoxIDs/Logic/SequenceLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ public async Task<T> GetSequenceDataAsync<T>(bool remove = true, bool allowNull
}

var sequenceData = data.ToObject<T>();
if (remove)
if (settings.DeleteUsedSequences && remove)
{
await cacheProvider.DeleteAsync(key);
}
Expand Down Expand Up @@ -271,9 +271,12 @@ public async Task<T> ValidateKeySequenceDataAsync<T>(Sequence sequence, string t

public async Task RemoveSequenceDataAsync<T>() where T : ISequenceData, new()
{
var sequence = HttpContext.GetSequence();
var key = DataKey(typeof(T), sequence);
await cacheProvider.DeleteAsync(key);
if (settings.DeleteUsedSequences)
{
var sequence = HttpContext.GetSequence();
var key = DataKey(typeof(T), sequence);
await cacheProvider.DeleteAsync(key);
}
}

private Task<string> CreateSequenceStringAsync(Sequence sequence)
Expand Down Expand Up @@ -337,8 +340,12 @@ public async Task ValidateExternalSequenceIdAsync(string externalId)
{
throw new SequenceBrowserBackException($"Cache do not contain the sequence string with external sequence id '{externalId}'.");
}
await cacheProvider.DeleteAsync(key);


if (settings.DeleteUsedSequences)
{
await cacheProvider.DeleteAsync(key);
}

var sequence = await Task.FromResult(Unprotect(sequenceString));
HttpContext.Items[Constants.Sequence.Object] = sequence;
HttpContext.Items[Constants.Sequence.String] = sequenceString;
Expand Down
60 changes: 60 additions & 0 deletions src/FoxIDs/Logic/Tracks/StateUpPartyLogic.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using FoxIDs.Infrastructure;
using FoxIDs.Models;
using FoxIDs.Models.Config;
using FoxIDs.Models.Sequences;
using FoxIDs.Repository;
using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks;

namespace FoxIDs.Logic
{
public class StateUpPartyLogic : SessionBaseLogic
{
private readonly TelemetryScopedLogger logger;
private readonly UpPartyCookieRepository<StateUpPartyCookie> stateCookieRepository;

public StateUpPartyLogic(FoxIDsSettings settings, TelemetryScopedLogger logger, UpPartyCookieRepository<StateUpPartyCookie> stateCookieRepository, IHttpContextAccessor httpContextAccessor) : base(settings, httpContextAccessor)
{
this.logger = logger;
this.stateCookieRepository = stateCookieRepository;
}

public async Task CreateOrUpdateStateCookieAsync<T>(T upParty, string state) where T : UpParty
{
logger.ScopeTrace(() => $"Create or update authentication method state cookie, Route '{RouteBinding.Route}'.");

Action<StateUpPartyCookie> updateAction = (stateCookie) =>
{
stateCookie.State = state;
};

var stateCookie = await stateCookieRepository.GetAsync(upParty);
if (stateCookie != null)
{
updateAction(stateCookie);
stateCookie.LastUpdated = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
else
{
stateCookie = new StateUpPartyCookie();
updateAction(stateCookie);
stateCookie.LastUpdated = stateCookie.CreateTime;
}

await stateCookieRepository.SaveAsync(upParty, stateCookie, null);
}

public async Task<string> GetAndDeleteStateCookieAsync<T>(T upParty) where T : UpParty
{
logger.ScopeTrace(() => $"Get and delete authentication method state cookie, Route '{RouteBinding.Route}'.");

var stateCookie = await stateCookieRepository.GetAsync(upParty);
if(stateCookie != null)
{
await stateCookieRepository.DeleteAsync(upParty);
}
return stateCookie.State;
}
}
}
5 changes: 5 additions & 0 deletions src/FoxIDs/Models/Config/FoxIDsSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public class FoxIDsSettings : Settings
[Required]
public int SequenceGracePeriod { get; set; } = 7200;

/// <summary>
/// Should the sequences be deleted after they have been used, default not deleted.
/// </summary>
public bool DeleteUsedSequences { get; set; }

/// <summary>
/// Confirmation code lifetime in seconds, send in email.
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions src/FoxIDs/Models/Sequences/StateUpPartyCookie.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using FoxIDs.Models.Session;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;

namespace FoxIDs.Models.Sequences
{
public class StateUpPartyCookie : CookieMessage
{
[JsonIgnore]
public override SameSiteMode SameSite => SameSiteMode.None;

[JsonProperty(PropertyName = "s")]
public string State { get; set; }
}
}

0 comments on commit ca30d69

Please sign in to comment.