Skip to content

Commit

Permalink
Bump Microsoft.IdentityModel.* to 7.7.1
Browse files Browse the repository at this point in the history
Added Duende.IdentityServer 7.* support
  • Loading branch information
Juris Gekiss authored and Juris Gekiss committed Oct 10, 2024
1 parent 7643b16 commit 60c8bec
Show file tree
Hide file tree
Showing 22 changed files with 356 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</ItemGroup>

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<PreserveCompilationContext>true</PreserveCompilationContext>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<DefineConstants>$(DefineConstants);DUENDE</DefineConstants>
Expand All @@ -17,10 +17,21 @@
<PackageTags>$(PackageTags);duende</PackageTags>
</PropertyGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
<PackageReference Include="Duende.IdentityServer" Version="6.*" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
<PackageReference Include="Duende.IdentityServer" Version="7.*" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Duende.IdentityServer" Version="5.2.2" />
<PackageReference Include="Abc.IdentityModel.Protocols.EidasLight" Version="2.1.0-dev03" />
<PackageReference Include="Microsoft.IdentityModel.Tokens.Saml" Version="7.0.3" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.WsFederation" Version="7.7.1" />
<PackageReference Include="Microsoft.IdentityModel.Logging" Version="7.7.1" />
<PackageReference Include="Microsoft.IdentityModel.Protocols" Version="7.7.1" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.7.1" />
<PackageReference Include="Microsoft.IdentityModel.Tokens.Saml" Version="7.7.1" />
<PackageReference Include="Microsoft.IdentityModel.Xml" Version="7.7.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<PreserveCompilationContext>true</PreserveCompilationContext>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<LangVersion>10.0</LangVersion>
<DefineConstants>$(DefineConstants);IDS4</DefineConstants>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ internal class ErrorPageResult : IEndpointResult
{
private IMessageStore<ErrorMessage> _errorMessageStore;
private IdentityServerOptions _options;
private ISystemClock _clock;
private IServerUrls _urls;
private IClock _clock;

public ErrorPageResult(string error, string errorDescription)
{
Error = error;
ErrorDescription = errorDescription;
}

internal ErrorPageResult(string error, string errorDescription, IdentityServerOptions options, ISystemClock clock, IMessageStore<ErrorMessage> errorMessageStore)
internal ErrorPageResult(string error, string errorDescription, IdentityServerOptions options, IClock clock, IServerUrls urls, IMessageStore<ErrorMessage> errorMessageStore)
: this(error, errorDescription)
{
_options = options;
_clock = clock;
_urls = urls;
_errorMessageStore = errorMessageStore;
}

Expand All @@ -56,14 +58,15 @@ public async Task ExecuteAsync(HttpContext context)
var redirectUrl = _options.UserInteraction.ErrorUrl;
redirectUrl = redirectUrl.AddQueryString(_options.UserInteraction.ErrorIdParameter, id);

context.Response.RedirectToAbsoluteUrl(redirectUrl);
context.Response.Redirect(_urls.GetAbsoluteUrl(redirectUrl));
}

private void Init(HttpContext context)
{
_errorMessageStore ??= context.RequestServices.GetRequiredService<IMessageStore<ErrorMessage>>();
_options ??= context.RequestServices.GetRequiredService<IdentityServerOptions>();
_clock ??= context.RequestServices.GetRequiredService<ISystemClock>();
_urls ??= context.RequestServices.GetRequiredService<IServerUrls>();
_clock ??= context.RequestServices.GetRequiredService<IClock>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using Abc.IdentityModel.Protocols.EidasLight;
using Abc.IdentityServer.EidasLight.Validation;
using Abc.IdentityServer.Extensions;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System;
Expand All @@ -29,7 +28,8 @@ public class LoginPageResult : IEndpointResult
private IdentityServerOptions _options;
private IAuthorizationParametersMessageStore _authorizationParametersMessageStore;
private EidasLightProtocolSerializer _protocolSerializer;
private ISystemClock _clock;
private IServerUrls _urls;
private IClock _clock;

/// <summary>
/// Initializes a new instance of the <see cref="LoginPageResult"/> class.
Expand All @@ -41,11 +41,12 @@ public LoginPageResult(ValidatedEidasLightRequest request)
_request = request ?? throw new ArgumentNullException(nameof(request));
}

internal LoginPageResult(ValidatedEidasLightRequest request, IdentityServerOptions options, ISystemClock clock, EidasLightProtocolSerializer protocolSerializer, IAuthorizationParametersMessageStore authorizationParametersMessageStore)
internal LoginPageResult(ValidatedEidasLightRequest request, IdentityServerOptions options, IClock clock, IServerUrls urls, EidasLightProtocolSerializer protocolSerializer, IAuthorizationParametersMessageStore authorizationParametersMessageStore)
: this(request)
{
_options = options;
_clock = clock;
_urls = urls;
_protocolSerializer = protocolSerializer;
_authorizationParametersMessageStore = authorizationParametersMessageStore;
}
Expand All @@ -55,7 +56,7 @@ public async Task ExecuteAsync(HttpContext context)
{
Init(context);

var returnUrl = context.GetIdentityServerBasePath().EnsureTrailingSlash() + Constants.ProtocolRoutePaths.EidasLightProxyCallback;
var returnUrl = _urls.BasePath.EnsureTrailingSlash() + Constants.ProtocolRoutePaths.EidasLightProxyCallback;

var data = _protocolSerializer.WriteMessageDictionary(_request.Message);
var msg = new Message<IDictionary<string, string[]>>(data, _clock.UtcNow.UtcDateTime);
Expand All @@ -67,19 +68,20 @@ public async Task ExecuteAsync(HttpContext context)
{
// this converts the relative redirect path to an absolute one if we're
// redirecting to a different server
returnUrl = context.GetIdentityServerHost().EnsureTrailingSlash() + returnUrl.RemoveLeadingSlash();
returnUrl = _urls.Origin.EnsureTrailingSlash() + returnUrl.RemoveLeadingSlash();
}

var url = loginUrl.AddQueryString(_options.UserInteraction.LoginReturnUrlParameter, returnUrl);
context.Response.RedirectToAbsoluteUrl(url);
context.Response.Redirect(_urls.GetAbsoluteUrl(url));
}

private void Init(HttpContext context)
{
_options ??= context.RequestServices.GetRequiredService<IdentityServerOptions>();
_protocolSerializer ??= context.RequestServices.GetRequiredService<EidasLightProtocolSerializer>();
_authorizationParametersMessageStore ??= context.RequestServices.GetRequiredService<IAuthorizationParametersMessageStore>();
_clock ??= context.RequestServices.GetRequiredService<ISystemClock>();
_urls ??= context.RequestServices.GetRequiredService<IServerUrls>();
_clock ??= context.RequestServices.GetRequiredService<IClock>();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#if IDS4

using Abc.IdentityServer.Extensions;
using Microsoft.AspNetCore.Http;
using System;
using System.Linq;

namespace IdentityServer4.Extensions;

/// <summary>
/// Extension methods for <see cref="IServerUrls"/>.
/// </summary>
public static class ServerUrlExtensions
{
/// <summary>
/// Returns the origin in unicode, and not in punycode (if we have a unicode hostname).
/// </summary>
public static string GetUnicodeOrigin(this IServerUrls urls)
{
var split = urls.Origin.Split(new[] { "://" }, StringSplitOptions.RemoveEmptyEntries);
var scheme = split.First();
var host = HostString.FromUriComponent(split.Last()).Value;

return scheme + "://" + host;
}

/// <summary>
/// Returns an absolute URL for the URL or path.
/// </summary>
public static string GetAbsoluteUrl(this IServerUrls urls, string urlOrPath)
{
if (urlOrPath.IsLocalUrl())
{
if (urlOrPath.StartsWith("~/"))
{
urlOrPath = urlOrPath.Substring(1);
}

urlOrPath = urls.BaseUrl.EnsureTrailingSlash() + urlOrPath.RemoveLeadingSlash();
}

return urlOrPath;
}

/// <summary>
/// Returns the URL into the server based on the relative path. The path parameter can start with "~/" or "/".
/// </summary>
public static string GetIdentityServerRelativeUrl(this IServerUrls urls, string path)
{
if (!path.IsLocalUrl())
{
return null;
}

if (path.StartsWith("~/"))
{
path = path.Substring(1);
}

path = urls.BaseUrl.EnsureTrailingSlash() + path.RemoveLeadingSlash();
return path;
}
}

#endif
11 changes: 11 additions & 0 deletions src/Abc.IdentityServer.EidasLight/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,16 @@ public static string RemoveLeadingSlash(this string url)

return url;
}

[DebuggerStepThrough]
public static string RemoveTrailingSlash(this string url)
{
if (url != null && url.EndsWith('/'))
{
url = url.Substring(0, url.Length - 1);
}

return url;
}
}
}
6 changes: 6 additions & 0 deletions src/Abc.IdentityServer.EidasLight/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@
global using Ids = IdentityServer4;
global using StatusCodeResult = IdentityServer4.Endpoints.Results.StatusCodeResult;
#endif

#if NET8_0_OR_GREATER
global using IClock = Duende.IdentityServer.IClock;
#else
global using IClock = Microsoft.AspNetCore.Authentication.ISystemClock;
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// ----------------------------------------------------------------------------

using Abc.IdentityServer.EidasLight.Validation;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
Expand All @@ -31,15 +30,15 @@ public class SignInInteractionResponseGenerator : ISignInInteractionResponseGene
/// <summary>
/// The clock.
/// </summary>
protected readonly ISystemClock Clock;
protected readonly IClock Clock;
#pragma warning restore SA1401 // Fields should be private

/// <summary>
/// Initializes a new instance of the <see cref="SignInInteractionResponseGenerator"/> class.
/// </summary>
/// <param name="clock">The clock.</param>
/// <param name="logger">The logger.</param>
public SignInInteractionResponseGenerator(ISystemClock clock, ILogger<SignInInteractionResponseGenerator> logger)
public SignInInteractionResponseGenerator(IClock clock, ILogger<SignInInteractionResponseGenerator> logger)
{
Clock = clock;
Logger = logger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,22 @@ public class SignInResponseGenerator : ISignInResponseGenerator
private readonly IHttpContextAccessor _contextAccessor;
private readonly Services.IClaimsService _claims;
private readonly IResourceStore _resources;
private readonly IIssuerNameService _issuerNameService;
private readonly ILogger _logger;

public SignInResponseGenerator(
IHttpContextAccessor contextAccessor,
EidasLightOptions options,
Services.IClaimsService claimsService,
IResourceStore resources,
IIssuerNameService issuerNameService,
ILogger<SignInResponseGenerator> logger)
{
_contextAccessor = contextAccessor;
_options = options;
_claims = claimsService;
_resources = resources;
_issuerNameService = issuerNameService;
_logger = logger;
}

Expand Down Expand Up @@ -117,15 +120,15 @@ protected virtual async Task<ClaimsIdentity> CreateSubjectAsync(SignInValidation
return new ClaimsIdentity(outboundClaims, "idsrv");
}

private Task<EidasLightResponse> CreateResponseAsync(ValidatedEidasLightRequest validatedRequest, ClaimsIdentity outgoingSubject)
private async Task<EidasLightResponse> CreateResponseAsync(ValidatedEidasLightRequest validatedRequest, ClaimsIdentity outgoingSubject)
{
var eidasLightRequest = validatedRequest.Message;

var eidasLightResponse = new EidasLightResponse()
{
InResponseToId = eidasLightRequest.Id,
IpAddress = _contextAccessor.HttpContext.GetClientIpAddress(),
Issuer = _contextAccessor.HttpContext.GetIdentityServerIssuerUri(),
Issuer = await _issuerNameService.GetCurrentAsync(),
RelayState = eidasLightRequest.RelayState,
Status = new EidasLightResponseStatus()
{
Expand Down Expand Up @@ -176,7 +179,7 @@ private Task<EidasLightResponse> CreateResponseAsync(ValidatedEidasLightRequest
}
}

return Task.FromResult(eidasLightResponse);
return eidasLightResponse;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#if IDS4

using Abc.IdentityServer.Extensions;
using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks;

namespace IdentityServer4.Services;

/// <summary>
/// Abstracts issuer name access.
/// </summary>
public class DefaultIssuerNameService : IIssuerNameService
{
private readonly IdentityServerOptions _options;
private readonly IServerUrls _urls;
private readonly IHttpContextAccessor _httpContextAccessor;

/// <summary>
/// Initializes a new instance of the <see cref="DefaultIssuerNameService"/> class.
/// </summary>
/// <param name="options">The identity server options.</param>
/// <param name="urls">The server uris.</param>
/// <param name="httpContextAccessor">The HTTP context accessor.</param>
public DefaultIssuerNameService(IdentityServerOptions options, IServerUrls urls, IHttpContextAccessor httpContextAccessor)
{
_options = options;
_urls = urls;
_httpContextAccessor = httpContextAccessor;
}

/// <inheritdoc />
public Task<string> GetCurrentAsync()
{
// if they've explicitly configured a URI then use it,
// otherwise dynamically calculate it
var issuer = _options.IssuerUri;
if (issuer.IsMissing())
{
string origin = null;

if (_options.MutualTls.Enabled && _options.MutualTls.DomainName.IsPresent()
&& !_options.MutualTls.DomainName.Contains("."))
{
var request = _httpContextAccessor.HttpContext.Request;
if (request.Host.Value.StartsWith(_options.MutualTls.DomainName, StringComparison.OrdinalIgnoreCase))
{
// if MTLS is configured with domain like "foo", then the request will be for "foo.acme.com",
// so the issuer we use is from the parent domain (e.g. "acme.com")
//
// Host.Value is used to get unicode hostname, instead of ToUriComponent (aka punycode)
origin = request.Scheme + "://" + request.Host.Value.Substring(_options.MutualTls.DomainName.Length + 1);
}
}

if (origin == null)
{
// no MTLS, so use the current origin for the issuer
// this also means we emit the issuer value in unicode
origin = _urls.GetUnicodeOrigin();
}

issuer = origin + _urls.BasePath;

if (_options.LowerCaseIssuerUri)
{
issuer = issuer.ToLowerInvariant();
}
}

return Task.FromResult(issuer);
}
}

#endif
Loading

0 comments on commit 60c8bec

Please sign in to comment.