From 0655a977e94bc5f7dceb16763ba8b86f9d22876e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=ADsli=20Konr=C3=A1=C3=B0=20Bj=C3=B6rnsson?= Date: Tue, 5 Nov 2024 15:37:41 +0000 Subject: [PATCH 1/6] adds .idea to .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 17fa608..016afda 100644 --- a/.gitignore +++ b/.gitignore @@ -352,4 +352,5 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ -Solid.**.xml \ No newline at end of file +Solid.**.xml +.idea \ No newline at end of file From d8758f87ffcd20c933b7faee8f30ba0144bbc66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=ADsli=20Konr=C3=A1=C3=B0=20Bj=C3=B6rnsson?= Date: Tue, 5 Nov 2024 15:37:51 +0000 Subject: [PATCH 2/6] fixes namespace --- .../Saml2pEncodingServiceTests.cs | 2 +- .../Saml2pStatusConversionTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Solid.Identity.Protocols.Sam2p.Tests/Saml2pEncodingServiceTests.cs b/src/Solid.Identity.Protocols.Sam2p.Tests/Saml2pEncodingServiceTests.cs index ceb66c7..c884f12 100644 --- a/src/Solid.Identity.Protocols.Sam2p.Tests/Saml2pEncodingServiceTests.cs +++ b/src/Solid.Identity.Protocols.Sam2p.Tests/Saml2pEncodingServiceTests.cs @@ -6,7 +6,7 @@ using System.Text; using Xunit; -namespace Solid.Identity.Protocols.Sam2p.Tests +namespace Solid.Identity.Protocols.Saml2p.Tests { public class Saml2pEncodingServiceTests { diff --git a/src/Solid.Identity.Protocols.Sam2p.Tests/Saml2pStatusConversionTests.cs b/src/Solid.Identity.Protocols.Sam2p.Tests/Saml2pStatusConversionTests.cs index af054dc..395ebaa 100644 --- a/src/Solid.Identity.Protocols.Sam2p.Tests/Saml2pStatusConversionTests.cs +++ b/src/Solid.Identity.Protocols.Sam2p.Tests/Saml2pStatusConversionTests.cs @@ -5,7 +5,7 @@ using System.Text; using Xunit; -namespace Solid.Identity.Protocols.Sam2p.Tests +namespace Solid.Identity.Protocols.Saml2p.Tests { public class Saml2pStatusConversionTests { From 968aa85af115fb692295dd3240e989e20784f410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=ADsli=20Konr=C3=A1=C3=B0=20Bj=C3=B6rnsson?= Date: Tue, 5 Nov 2024 15:38:27 +0000 Subject: [PATCH 3/6] fixes errors due to dotnet 8 upgrade --- .../AspNetCore.IdpSample.csproj | 2 +- src/AspNetCore.IdpSample/Startup.cs | 2 +- .../AspNetCore.SpSample.csproj | 2 +- src/AspNetCore.SpSample/Startup.cs | 3 - ...olid.Identity.Protocols.Sam2p.Tests.csproj | 2 +- .../ISecurityTokenDescriptorFactory.cs | 1 + .../Saml2pAuthenticationHandler.cs | 14 ++++- .../Extensions/ClaimsIdentityExtensions.cs | 14 +++++ .../Factories/AuthnRequestFactory.cs | 30 ++++++++-- .../SecurityTokenDescriptorFactory.cs | 58 +++++++++++++------ .../Idp/CompleteSsoEndpointMiddleware.cs | 11 ++-- .../Sp/FinishSsoEndpointMiddleware.cs | 58 +++++++++++++++++-- .../Solid.Identity.Protocols.Saml2p.csproj | 2 +- 13 files changed, 159 insertions(+), 40 deletions(-) diff --git a/src/AspNetCore.IdpSample/AspNetCore.IdpSample.csproj b/src/AspNetCore.IdpSample/AspNetCore.IdpSample.csproj index 49f7afd..4887d90 100644 --- a/src/AspNetCore.IdpSample/AspNetCore.IdpSample.csproj +++ b/src/AspNetCore.IdpSample/AspNetCore.IdpSample.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 InProcess diff --git a/src/AspNetCore.IdpSample/Startup.cs b/src/AspNetCore.IdpSample/Startup.cs index 7f414d4..14b05d8 100644 --- a/src/AspNetCore.IdpSample/Startup.cs +++ b/src/AspNetCore.IdpSample/Startup.cs @@ -66,7 +66,7 @@ public void ConfigureServices(IServiceCollection services) { sp.BaseUrl = new Uri("https://localhost:5003"); sp.MaxClockSkew = TimeSpan.FromMinutes(2); - sp.AssertionConsumerServiceEndpoint = "/finish"; + sp.AssertionConsumerServiceEndpoint = "/saml2p/finish"; sp.AssertionSigningKey = new X509SecurityKey(new X509Certificate2(Convert.FromBase64String(SigningCertificateBase64))); sp.SupportedBindings.Clear(); diff --git a/src/AspNetCore.SpSample/AspNetCore.SpSample.csproj b/src/AspNetCore.SpSample/AspNetCore.SpSample.csproj index 76a7b45..8b1731e 100644 --- a/src/AspNetCore.SpSample/AspNetCore.SpSample.csproj +++ b/src/AspNetCore.SpSample/AspNetCore.SpSample.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 InProcess diff --git a/src/AspNetCore.SpSample/Startup.cs b/src/AspNetCore.SpSample/Startup.cs index 575bcf0..661a6f5 100644 --- a/src/AspNetCore.SpSample/Startup.cs +++ b/src/AspNetCore.SpSample/Startup.cs @@ -62,9 +62,6 @@ public void ConfigureServices(IServiceCollection services) idp.CanInitiateSso = true; idp.RequestedAuthnContextClassRef = Saml2pConstants.Classes.Kerberos; idp.AssertionSigningKeys.Add(new X509SecurityKey(new X509Certificate2(Convert.FromBase64String(SigningCertificateBase64)))); - //idp.Events.OnGeneratingRelayState = (provider, context) => new ValueTask(); - //idp.Events.OnValidatingToken = ValidatingToken; - //idp.Events.OnValidatingToken += (provider, context) => new ValueTask(); }); }) ; diff --git a/src/Solid.Identity.Protocols.Sam2p.Tests/Solid.Identity.Protocols.Sam2p.Tests.csproj b/src/Solid.Identity.Protocols.Sam2p.Tests/Solid.Identity.Protocols.Sam2p.Tests.csproj index 469becd..8357fff 100644 --- a/src/Solid.Identity.Protocols.Sam2p.Tests/Solid.Identity.Protocols.Sam2p.Tests.csproj +++ b/src/Solid.Identity.Protocols.Sam2p.Tests/Solid.Identity.Protocols.Sam2p.Tests.csproj @@ -1,7 +1,7 @@ - net6.0;net7.0 + net6.0;net8.0 false diff --git a/src/Solid.Identity.Protocols.Saml2p/Abstractions/ISecurityTokenDescriptorFactory.cs b/src/Solid.Identity.Protocols.Saml2p/Abstractions/ISecurityTokenDescriptorFactory.cs index 56e8b49..e1d277b 100644 --- a/src/Solid.Identity.Protocols.Saml2p/Abstractions/ISecurityTokenDescriptorFactory.cs +++ b/src/Solid.Identity.Protocols.Saml2p/Abstractions/ISecurityTokenDescriptorFactory.cs @@ -6,6 +6,7 @@ using System.Security.Claims; using System.Text; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; namespace Solid.Identity.Protocols.Saml2p.Abstractions { diff --git a/src/Solid.Identity.Protocols.Saml2p/Authentication/Saml2pAuthenticationHandler.cs b/src/Solid.Identity.Protocols.Saml2p/Authentication/Saml2pAuthenticationHandler.cs index 1dda296..13b508c 100644 --- a/src/Solid.Identity.Protocols.Saml2p/Authentication/Saml2pAuthenticationHandler.cs +++ b/src/Solid.Identity.Protocols.Saml2p/Authentication/Saml2pAuthenticationHandler.cs @@ -18,20 +18,32 @@ using System.Security.Claims; using Solid.Identity.Protocols.Saml2p.Options; using Solid.Identity.Protocols.Saml2p.Exceptions; +// ReSharper disable InconsistentNaming namespace Solid.Identity.Protocols.Saml2p.Authentication { internal class Saml2pAuthenticationHandler : RemoteAuthenticationHandler, IDisposable { private Saml2pOptions _saml2p; - private IDisposable _optionsChangeToken; + private readonly IDisposable _optionsChangeToken; +#if NET6_0 public Saml2pAuthenticationHandler(IOptionsMonitor saml2pOptionsMonitor, IOptionsMonitor monitor, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(monitor, logger, encoder, clock) { _saml2p = saml2pOptionsMonitor.CurrentValue; _optionsChangeToken = saml2pOptionsMonitor.OnChange((options, _) => _saml2p = options); } +#else + public Saml2pAuthenticationHandler(IOptionsMonitor saml2pOptionsMonitor, IOptionsMonitor monitor, ILoggerFactory logger, UrlEncoder encoder) + : base(monitor, logger, encoder) + { + _saml2p = saml2pOptionsMonitor.CurrentValue; + _optionsChangeToken = saml2pOptionsMonitor.OnChange((options, _) => _saml2p = options); + } +#endif + + protected override Task InitializeHandlerAsync() { diff --git a/src/Solid.Identity.Protocols.Saml2p/Extensions/ClaimsIdentityExtensions.cs b/src/Solid.Identity.Protocols.Saml2p/Extensions/ClaimsIdentityExtensions.cs index b043a46..7c915e4 100644 --- a/src/Solid.Identity.Protocols.Saml2p/Extensions/ClaimsIdentityExtensions.cs +++ b/src/Solid.Identity.Protocols.Saml2p/Extensions/ClaimsIdentityExtensions.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Text; +using Solid.IdentityModel.Xml; namespace System.Security.Claims { @@ -11,5 +13,17 @@ public static bool TryFindFirst(this ClaimsIdentity identity, string type, out C claim = identity.FindFirst(type); return claim != null; } + + public static bool TryParseAuthenticationInstant(this ClaimsIdentity identity, out DateTime? instant) + { + var value = identity.FindFirst(ClaimTypes.AuthenticationInstant)?.Value; + if (string.IsNullOrWhiteSpace(value)) + return Out.False(out instant); + if (!DateTime.TryParse(value, out var parsed)) + return Out.False(out instant); + + instant = parsed; + return instant.HasValue; + } } } diff --git a/src/Solid.Identity.Protocols.Saml2p/Factories/AuthnRequestFactory.cs b/src/Solid.Identity.Protocols.Saml2p/Factories/AuthnRequestFactory.cs index 6ce1451..d445b20 100644 --- a/src/Solid.Identity.Protocols.Saml2p/Factories/AuthnRequestFactory.cs +++ b/src/Solid.Identity.Protocols.Saml2p/Factories/AuthnRequestFactory.cs @@ -18,9 +18,9 @@ namespace Solid.Identity.Protocols.Saml2p.Factories /// public class AuthnRequestFactory { - private ISystemClock _systemClock; - private Saml2pOptions _options; - + private readonly Saml2pOptions _options; +#if NET6_0 + private readonly ISystemClock _systemClock; /// /// Creates an instance of . /// @@ -31,6 +31,19 @@ public AuthnRequestFactory(ISystemClock systemClock, IOptions opt _systemClock = systemClock; _options = options.Value; } +#else + private readonly TimeProvider _time; + /// + /// Creates an instance of . + /// + /// The provider of the current time. + /// The current . + public AuthnRequestFactory(TimeProvider time, IOptions options) + { + _time = time; + _options = options.Value; + } +#endif /// /// Creates an instance of . @@ -46,7 +59,7 @@ public async Task CreateAuthnRequestAsync(HttpContext context, ISa // TODO: have some sort of providername default ProviderName = idp.ExpectedIssuer ?? _options.DefaultIssuer, AssertionConsumerServiceUrl = GetAcsUrl(context.Request), - IssueInstant = _systemClock.UtcNow.UtcDateTime, + IssueInstant = GetUtcNow(), Issuer = idp.ExpectedIssuer ?? _options.DefaultIssuer, Destination = new Uri(idp.BaseUrl, idp.AcceptSsoEndpoint), NameIdPolicy = new NameIdPolicy @@ -82,5 +95,14 @@ private Uri GetAcsUrl(HttpRequest request) var path = request.PathBase.Add(_options.FinishPath); return new Uri(baseUrl, path); } + + private DateTime GetUtcNow() + { +#if NET6_0 + return _systemClock.UtcNow.UtcDateTime; +#else + return _time.GetUtcNow().UtcDateTime; +#endif + } } } diff --git a/src/Solid.Identity.Protocols.Saml2p/Factories/SecurityTokenDescriptorFactory.cs b/src/Solid.Identity.Protocols.Saml2p/Factories/SecurityTokenDescriptorFactory.cs index 92014ab..66a7225 100644 --- a/src/Solid.Identity.Protocols.Saml2p/Factories/SecurityTokenDescriptorFactory.cs +++ b/src/Solid.Identity.Protocols.Saml2p/Factories/SecurityTokenDescriptorFactory.cs @@ -21,9 +21,11 @@ namespace Solid.Identity.Protocols.Saml2p.Factories { internal class SecurityTokenDescriptorFactory : ISecurityTokenDescriptorFactory { - private Saml2pOptions _options; - private IEnumerable _claimsProviders; - private ILogger _logger; + private readonly Saml2pOptions _options; + private readonly IEnumerable _claimsProviders; + private readonly ILogger _logger; + +#if NET6_0 private ISystemClock _systemClock; public SecurityTokenDescriptorFactory( @@ -37,18 +39,36 @@ public SecurityTokenDescriptorFactory( _logger = logger; _systemClock = systemClock; } +#else + private readonly TimeProvider _time; - public async ValueTask CreateSecurityTokenDescriptorAsync(ClaimsIdentity identity, ISaml2pServiceProvider partner) + public SecurityTokenDescriptorFactory( + IOptions options, + IEnumerable claimsProviders, + ILogger logger, + TimeProvider time) { - var instant = identity.FindFirst(ClaimTypes.AuthenticationInstant)?.Value; - var issuedAt = _systemClock.UtcNow.DateTime; - if (instant != null && DateTime.TryParse(instant, out var parsed)) - issuedAt = parsed; + _options = options.Value; + _claimsProviders = claimsProviders; + _logger = logger; + _time = time; + } +#endif - var issuer = partner.ExpectedIssuer ?? _options.DefaultIssuer; + public async ValueTask CreateSecurityTokenDescriptorAsync(ClaimsIdentity identity, ISaml2pServiceProvider partner) + { + var issuedAt = GetUtcNow(); + var instant = issuedAt; + if (identity.TryParseAuthenticationInstant(out var parsed)) + instant = parsed!.Value; var lifetime = partner.TokenLifeTime ?? _options.DefaultTokenLifetime; - var tolerence = partner.MaxClockSkew ?? _options.DefaultMaxClockSkew ?? TimeSpan.Zero; + var tolerance = partner.MaxClockSkew ?? _options.DefaultMaxClockSkew ?? TimeSpan.Zero; + var expires = issuedAt + .Add(lifetime) + .Add(tolerance) + ; + var issuer = partner.ExpectedIssuer ?? _options.DefaultIssuer; var claims = new List(); foreach (var provider in _claimsProviders) { @@ -74,7 +94,7 @@ public async ValueTask CreateSecurityTokenDescriptorAsy claims = claims.Where(c => supported.Contains(c.Type)).ToList(); Trace($"Filtered claims.", claims); - AddRequiredClaims(identity, claims, issuedAt, issuer); + AddRequiredClaims(identity, claims, instant, issuer); var attributes = claims .Where(c => c.Type != ClaimTypes.NameIdentifier) @@ -91,18 +111,13 @@ public async ValueTask CreateSecurityTokenDescriptorAsy attribute.Properties.Add(ClaimProperties.SamlAttributeNameFormat, "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"); } - var expires = issuedAt - .Add(lifetime) - .Add(tolerence) - ; - var descriptor = new SecurityTokenDescriptor { Audience = partner.Id, Subject = new ClaimsIdentity(claims, "SSO"), Issuer = issuer, IssuedAt = issuedAt, - NotBefore = issuedAt.Subtract(tolerence), + NotBefore = issuedAt.Subtract(tolerance), Expires = expires, SigningCredentials = GetSigningCredentials(partner), EncryptingCredentials = GetEncryptingCredentials(partner) @@ -171,5 +186,14 @@ private void Trace(string prefix, object obj) if (!_logger.IsEnabled(LogLevel.Trace)) return; _logger.LogTrace(prefix + Environment.NewLine + "{state}", new WrappedLogMessageState(obj)); } + + private DateTime GetUtcNow() + { +#if NET6_0 + return _systemClock.UtcNow.UtcDateTime; +#else + return _time.GetUtcNow().UtcDateTime; +#endif + } } } diff --git a/src/Solid.Identity.Protocols.Saml2p/Middleware/Idp/CompleteSsoEndpointMiddleware.cs b/src/Solid.Identity.Protocols.Saml2p/Middleware/Idp/CompleteSsoEndpointMiddleware.cs index 323045b..38ab025 100644 --- a/src/Solid.Identity.Protocols.Saml2p/Middleware/Idp/CompleteSsoEndpointMiddleware.cs +++ b/src/Solid.Identity.Protocols.Saml2p/Middleware/Idp/CompleteSsoEndpointMiddleware.cs @@ -23,6 +23,7 @@ using Solid.Identity.Protocols.Saml2p.Services; using Solid.Identity.Protocols.Saml2p.Models; using System.Net; +using Microsoft.AspNetCore.Authentication; namespace Solid.Identity.Protocols.Saml2p.Middleware.Idp { @@ -62,7 +63,7 @@ public override async Task InvokeAsync(HttpContext context) var response = null as SamlResponse; - var user = context.User; + var authentication = await context.AuthenticateAsync(); var request = await Cache.FetchRequestAsync(id); if (request == null) throw new SecurityException($"SAMLRequest not found for id: '{id}'"); @@ -83,9 +84,9 @@ public override async Task InvokeAsync(HttpContext context) Trace("Found cached Status.", request.RelayState, status); response = _responseFactory.Create(partner, status, authnRequestId: request.Id, relayState: request.RelayState); } - else if (user.Identity.IsAuthenticated) + else if (authentication.Succeeded && authentication.Principal?.Identity is ClaimsIdentity identity) { - var descriptor = await _descriptorFactory.CreateSecurityTokenDescriptorAsync(user.Identity as ClaimsIdentity, partner); + var descriptor = await _descriptorFactory.CreateSecurityTokenDescriptorAsync(identity, partner); var createSecurityTokenContext = new CreateSecurityTokenContext { PartnerId = partner.Id, @@ -96,8 +97,8 @@ public override async Task InvokeAsync(HttpContext context) await Events.InvokeAsync(Options, partner, e => e.OnCreatingSecurityToken(context.RequestServices, createSecurityTokenContext)); - if (createSecurityTokenContext.SecurityToken == null) - createSecurityTokenContext.SecurityToken = createSecurityTokenContext.Handler.CreateToken(createSecurityTokenContext.TokenDescriptor) as Saml2SecurityToken; + createSecurityTokenContext.SecurityToken ??= + createSecurityTokenContext.Handler.CreateToken(createSecurityTokenContext.TokenDescriptor) as Saml2SecurityToken; await Events.InvokeAsync(Options, partner, e => e.OnCreatedSecurityToken(context.RequestServices, createSecurityTokenContext)); diff --git a/src/Solid.Identity.Protocols.Saml2p/Middleware/Sp/FinishSsoEndpointMiddleware.cs b/src/Solid.Identity.Protocols.Saml2p/Middleware/Sp/FinishSsoEndpointMiddleware.cs index dc96922..7e66507 100644 --- a/src/Solid.Identity.Protocols.Saml2p/Middleware/Sp/FinishSsoEndpointMiddleware.cs +++ b/src/Solid.Identity.Protocols.Saml2p/Middleware/Sp/FinishSsoEndpointMiddleware.cs @@ -22,9 +22,11 @@ namespace Solid.Identity.Protocols.Saml2p.Middleware.Sp { internal class FinishSsoEndpointMiddleware : Saml2pEndpointMiddleware { - private Saml2SecurityTokenHandler _handler; - private TokenValidationParametersFactory _factory; - private ISystemClock _clock; + private readonly Saml2SecurityTokenHandler _handler; + private readonly TokenValidationParametersFactory _factory; + +#if NET6_0 + private readonly ISystemClock _clock; public FinishSsoEndpointMiddleware( Saml2SecurityTokenHandler handler, @@ -57,6 +59,42 @@ public FinishSsoEndpointMiddleware( _factory = parametersFactory; _clock = clock; } +#else + private readonly TimeProvider _time; + + public FinishSsoEndpointMiddleware( + Saml2SecurityTokenHandler handler, + TokenValidationParametersFactory parametersFactory, + TimeProvider time, + Saml2pSerializer serializer, + Saml2pCache cache, + Saml2pPartnerProvider partners, + Saml2pEncodingService encoder, + IOptionsMonitor monitor, + ILoggerFactory factory, + RequestDelegate _) + : this(handler, parametersFactory, time, serializer, cache, partners, encoder, monitor, factory) + { + } + + public FinishSsoEndpointMiddleware( + Saml2SecurityTokenHandler handler, + TokenValidationParametersFactory parametersFactory, + TimeProvider time, + Saml2pSerializer serializer, + Saml2pCache cache, + Saml2pPartnerProvider partners, + Saml2pEncodingService encoder, + IOptionsMonitor monitor, + ILoggerFactory factory) + : base(serializer, cache, partners, encoder, monitor, factory) + { + _handler = handler; + _factory = parametersFactory; + _time = time; + } + +#endif public override async Task InvokeAsync(HttpContext context) { @@ -154,9 +192,9 @@ public async Task FinishSsoAsync(HttpContext context) Logger.LogInformation("Validating incoming token."); var subject = validateContext.Handler.ValidateToken(validateContext.Response.XmlSecurityToken, validateContext.TokenValidationParameters, out var token); var saml2 = token as Saml2SecurityToken; - var now = _clock.UtcNow.DateTime; + var now = GetUtcNow(); - saml2.ValidateResponseToken(validateContext.Request.Id, now); + saml2.ValidateResponseToken(validateContext.Request?.Id, now); validateContext.Subject = subject; validateContext.SecurityToken = saml2; @@ -182,5 +220,15 @@ public async Task FinishSsoAsync(HttpContext context) return FinishSsoResult.Success(partner.Id, validateContext.Response.XmlSecurityToken, validateContext.SecurityToken, validateContext.Subject, properties); } + + + private DateTime GetUtcNow() + { +#if NET6_0 + return _clock.UtcNow.UtcDateTime; +#else + return _time.GetUtcNow().UtcDateTime; +#endif + } } } diff --git a/src/Solid.Identity.Protocols.Saml2p/Solid.Identity.Protocols.Saml2p.csproj b/src/Solid.Identity.Protocols.Saml2p/Solid.Identity.Protocols.Saml2p.csproj index 2df3bbd..20b5f2a 100644 --- a/src/Solid.Identity.Protocols.Saml2p/Solid.Identity.Protocols.Saml2p.csproj +++ b/src/Solid.Identity.Protocols.Saml2p/Solid.Identity.Protocols.Saml2p.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0 + net6.0;net8.0 Solid.Identity.Protocols.Saml2p Solid.Identity.Protocols.Saml2p true From 174fb1254098671e02883135bb7114e7497bb2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=ADsli=20Konr=C3=A1=C3=B0=20Bj=C3=B6rnsson?= Date: Tue, 5 Nov 2024 15:50:19 +0000 Subject: [PATCH 4/6] Adds logout button to samples --- src/AspNetCore.IdpSample/Pages/Logout.cshtml | 2 ++ src/AspNetCore.IdpSample/Pages/Logout.cshtml.cs | 15 +++++++++++++++ .../Pages/Shared/_Layout.cshtml | 1 + src/AspNetCore.SpSample/Pages/Logout.cshtml | 2 ++ src/AspNetCore.SpSample/Pages/Logout.cshtml.cs | 15 +++++++++++++++ .../Pages/Shared/_Layout.cshtml | 1 + 6 files changed, 36 insertions(+) create mode 100644 src/AspNetCore.IdpSample/Pages/Logout.cshtml create mode 100644 src/AspNetCore.IdpSample/Pages/Logout.cshtml.cs create mode 100644 src/AspNetCore.SpSample/Pages/Logout.cshtml create mode 100644 src/AspNetCore.SpSample/Pages/Logout.cshtml.cs diff --git a/src/AspNetCore.IdpSample/Pages/Logout.cshtml b/src/AspNetCore.IdpSample/Pages/Logout.cshtml new file mode 100644 index 0000000..3ba3359 --- /dev/null +++ b/src/AspNetCore.IdpSample/Pages/Logout.cshtml @@ -0,0 +1,2 @@ +@page +@model AspNetCore.IdpSample.Pages.Logout \ No newline at end of file diff --git a/src/AspNetCore.IdpSample/Pages/Logout.cshtml.cs b/src/AspNetCore.IdpSample/Pages/Logout.cshtml.cs new file mode 100644 index 0000000..4fbad77 --- /dev/null +++ b/src/AspNetCore.IdpSample/Pages/Logout.cshtml.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace AspNetCore.IdpSample.Pages; + +public class Logout : PageModel +{ + public async Task OnGetAsync() + { + await HttpContext.SignOutAsync(); + return Redirect("/"); + } +} \ No newline at end of file diff --git a/src/AspNetCore.IdpSample/Pages/Shared/_Layout.cshtml b/src/AspNetCore.IdpSample/Pages/Shared/_Layout.cshtml index d971eea..680bd2d 100644 --- a/src/AspNetCore.IdpSample/Pages/Shared/_Layout.cshtml +++ b/src/AspNetCore.IdpSample/Pages/Shared/_Layout.cshtml @@ -43,6 +43,7 @@ @(Context.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value ?? "") + Logout } diff --git a/src/AspNetCore.SpSample/Pages/Logout.cshtml b/src/AspNetCore.SpSample/Pages/Logout.cshtml new file mode 100644 index 0000000..9490d6a --- /dev/null +++ b/src/AspNetCore.SpSample/Pages/Logout.cshtml @@ -0,0 +1,2 @@ +@page +@model AspNetCore.SpSample.Pages.Logout diff --git a/src/AspNetCore.SpSample/Pages/Logout.cshtml.cs b/src/AspNetCore.SpSample/Pages/Logout.cshtml.cs new file mode 100644 index 0000000..ccd07ba --- /dev/null +++ b/src/AspNetCore.SpSample/Pages/Logout.cshtml.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace AspNetCore.SpSample.Pages; + +public class Logout : PageModel +{ + public async Task OnGetAsync() + { + await HttpContext.SignOutAsync(); + return Redirect("/"); + } +} \ No newline at end of file diff --git a/src/AspNetCore.SpSample/Pages/Shared/_Layout.cshtml b/src/AspNetCore.SpSample/Pages/Shared/_Layout.cshtml index cae5a1b..fd512e4 100644 --- a/src/AspNetCore.SpSample/Pages/Shared/_Layout.cshtml +++ b/src/AspNetCore.SpSample/Pages/Shared/_Layout.cshtml @@ -43,6 +43,7 @@ @(Context.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value ?? "") + Logout } From 50aa7ef51d8f8144b74b3ab0af6fc6bc7927353a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=ADsli=20Konr=C3=A1=C3=B0=20Bj=C3=B6rnsson?= Date: Tue, 5 Nov 2024 15:50:30 +0000 Subject: [PATCH 5/6] adds cache expiration --- .../Cache/Saml2pCache.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Solid.Identity.Protocols.Saml2p/Cache/Saml2pCache.cs b/src/Solid.Identity.Protocols.Saml2p/Cache/Saml2pCache.cs index 23af5e5..10878a6 100644 --- a/src/Solid.Identity.Protocols.Saml2p/Cache/Saml2pCache.cs +++ b/src/Solid.Identity.Protocols.Saml2p/Cache/Saml2pCache.cs @@ -6,6 +6,7 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; using System.Threading.Tasks; namespace Solid.Identity.Protocols.Saml2p.Cache @@ -22,13 +23,13 @@ public Saml2pCache(IDistributedCache inner) public Task CacheRequestAsync(string key, AuthnRequest request) { var json = JsonSerializer.SerializeToUtf8Bytes(request); - return _inner.SetAsync(key, json); + return _inner.SetAsync(key, json, CreateOptions()); } public Task CacheStatusAsync(string key, Status status) { var json = JsonSerializer.SerializeToUtf8Bytes(status); - return _inner.SetAsync($"{key}_status", json); + return _inner.SetAsync($"{key}_status", json, CreateOptions()); } public async Task FetchRequestAsync(string key) @@ -52,5 +53,14 @@ public async Task RemoveAsync(string key) await _inner.RemoveAsync(key); await _inner.RemoveAsync($"{key}_status"); } + + private DistributedCacheEntryOptions CreateOptions() + { + return new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5) + }; + } + } } From 5ec1606f33bed38b76d59cfbcfdb8cb9112c2372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=ADsli=20Konr=C3=A1=C3=B0=20Bj=C3=B6rnsson?= Date: Tue, 5 Nov 2024 15:52:33 +0000 Subject: [PATCH 6/6] updates workflows for dotnet 8 --- .github/workflows/publish.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ee97897..053866f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -38,7 +38,7 @@ jobs: with: dotnet-version: | 6.0.x - 7.0.x + 8.0.x - name: install_dependencies run: dotnet restore ./src/Solid.Identity.Protocols.Saml2p.sln diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0d223c2..957cd26 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: with: dotnet-version: | 6.0.x - 7.0.x + 8.0.x - name: install_dependencies run: dotnet restore ./src/Solid.Identity.Protocols.Saml2p.sln