Skip to content

Commit

Permalink
feat: wsfederation provider
Browse files Browse the repository at this point in the history
closes #403
  • Loading branch information
github-actions committed Apr 1, 2021
1 parent f5cd52e commit 0295b1f
Show file tree
Hide file tree
Showing 18 changed files with 315 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aguacongas.AspNetCore.Authentication" Version="4.0.0" />
<PackageReference Include="Aguacongas.AspNetCore.Authentication" Version="4.0.2" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 3 additions & 1 deletion src/Aguacongas.TheIdServer/Aguacongas.TheIdServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
<None Include="compilerconfig.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aguacongas.AspNetCore.Authentication.RavenDb" Version="4.0.0" />
<PackageReference Include="Azure.Extensions.AspNetCore.DataProtection.Blobs" Version="1.2.0" />
<PackageReference Include="Azure.Extensions.AspNetCore.DataProtection.Keys" Version="1.0.2" />
<PackageReference Include="Azure.Identity" Version="1.3.0" />
Expand Down Expand Up @@ -89,6 +88,9 @@
<None Update="cluster.admin.client.certificate.pfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="TheIdServer.crt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="theidserver.pfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
4 changes: 2 additions & 2 deletions src/Aguacongas.TheIdServer/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"https://c.ravendb.local"
],
"Database": "TheIdServer",
"CertificatePath": "cluster.admin.client.certificate.pfx",
"CertificatePassword": "p@$$w0rd"
"CertificatePath": "TheIdServer.pfx",
"CertificatePassword": "TheIdServer"
},
"SiteOptions": {
"Name": "TheIdServer"
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aguacongas.AspNetCore.Authentication" Version="4.0.0" />
<PackageReference Include="Aguacongas.AspNetCore.Authentication" Version="4.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="5.0.4" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
@inherits ProviderOptionsBase<WsFederationOptions>

<div class="form-group row">
<label class="col col-form-label" for="metadataAddress">
@Localizer["metadata address"]
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeText Id="metadataAddress" Placeholder="https://<ADFS FQDN or AAD tenant>/FederationMetadata/2007-06/FederationMetadata.xml" @bind-Value="@Model.Options.MetadataAddress" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="wtrealm">
@Localizer["wtrealm "]
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeText Id="wtrealm" Placeholder="https://<Application ID URI>" @bind-Value="@Model.Options.Wtrealm" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="wreply">
@Localizer["wreply "]
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeText Id="wreply" @bind-Value="@Model.Options.Wreply" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="signOutWreply">
@Localizer["sign-out wreply "]
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeText Id="signOutWreply" @bind-Value="@Model.Options.SignOutWreply" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="signOutScheme">
@Localizer["sign-out scheme "]
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeText Id="signOutScheme" @bind-Value="@Model.Options.SignOutScheme" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="remoteSignOutPath">
@Localizer["remote sign-out path "]
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeText Id="remoteSignOutPath" Placeholder="/sign-out" @bind-Value="@Model.Options.RemoteSignOutPath" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="requireHttpsMetadata">
</label>
<div id="require-https" class="col-lg-10 col-sm-12">
<AuthorizeCheckbox Name="requireHttpsMetadata" Label="@Localizer["require https metadata"]" @bind-Value="@RequireHttpsMetadata" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="saveTokens">
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeCheckbox Name="saveTokens" Label="@Localizer["save tokens"]" @bind-Value="@Model.Options.SaveTokens" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="useTokenLifetime">
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeCheckbox Name="useTokenLifetime" Label="@Localizer["use token lifetime"]" @bind-Value="@Model.Options.UseTokenLifetime" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="skipUnrecognizedRequests">
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeCheckbox Name="skipUnrecognizedRequests" Label="@Localizer["skip unrecognized requests"]" @bind-Value="@Model.Options.SkipUnrecognizedRequests" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="refreshOnIssuerKeyNotFound">
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeCheckbox Name="refreshOnIssuerKeyNotFound" Label="@Localizer["refresh on issuer key not found"]" @bind-Value="@Model.Options.RefreshOnIssuerKeyNotFound" />
</div>
</div>
<div class="form-group row">
<label class="col col-form-label" for="allowUnsolicitedLogins">
</label>
<div class="col-lg-10 col-sm-12">
<AuthorizeCheckbox Name="allowUnsolicitedLogins" Label="@Localizer["allow unsolicited logins"]" @bind-Value="@Model.Options.AllowUnsolicitedLogins" />
</div>
</div>


Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Project: Aguafrommars/TheIdServer
// Copyright (c) 2021 @Olivier Lefebvre
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;

namespace Aguacongas.TheIdServer.BlazorApp.Pages.ExternalProvider.Components
{
public partial class WsFederationOptionsComponent
{
[CascadingParameter]
public EditContext EditContext { get; set; }

public bool RequireHttpsMetadata {
get => Model.Options.RequireHttpsMetadata;
set
{
Model.Options.RequireHttpsMetadata = value;
EditContext.NotifyFieldChanged(new FieldIdentifier(Model.Options, nameof(Model.Options.MetadataAddress)));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ else
case "Twitter":
<TwitterOptionsComponent @ref="_optionsComponent" />
break;
case "WsFederation":
<WsFederationOptionsComponent @ref="_optionsComponent" />
break;
}
<div class="form-group row">
<label class="col col-form-label" for="storeClaims">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Project: Aguafrommars/TheIdServer
// Copyright (c) 2021 @Olivier Lefebvre

namespace Aguacongas.TheIdServer.BlazorApp.Models
{

/// <summary>
/// WS-Federation options
/// </summary>
/// <seealso cref="RemoteAuthenticationOptions" />
public class WsFederationOptions : RemoteAuthenticationOptions
{
/// <summary>
/// Requests received on this path will cause the handler to invoke SignOut using
/// the SignOutScheme.
/// </summary>
/// <value>
/// The remote sign out path.
/// </value>
public string RemoteSignOutPath { get; set; }

/// <summary>
/// The Ws-Federation protocol allows the user to initiate logins without contacting
/// the application for a Challenge first. However, that flow is susceptible to XSRF
/// and other attacks so it is disabled here by default.
/// </summary>
/// <value>
/// <c>true</c> if [allow unsolicited logins]; otherwise, <c>false</c>.
/// </value>
public bool AllowUnsolicitedLogins { get; set; }

/// <summary>
/// Gets or sets if HTTPS is required for the metadata address or authority. The
/// default is true. This should be disabled only in development environments.
/// </summary>
/// <value>
/// <c>true</c> if [require HTTPS metadata]; otherwise, <c>false</c>.
/// </value>
public bool RequireHttpsMetadata { get; set; }

/// <summary>
/// Indicates that the authentication session lifetime (e.g. cookies) should match
/// that of the authentication token. If the token does not provide lifetime information
/// then normal session lifetimes will be used. This is enabled by default.
/// </summary>
/// <value>
/// <c>true</c> if [use token lifetime]; otherwise, <c>false</c>.
/// </value>
public bool UseTokenLifetime { get; set; }
/// <summary>
/// Gets or sets the 'wtrealm'.
/// </summary>
/// <value>
/// The wtrealm.
/// </value>
public string Wtrealm { get; set; }

/// <summary>
/// Gets or sets the 'wreply' value used during sign-out. If none is specified then
/// the value from the Wreply field is used.
/// </summary>
/// <value>
/// The sign out wreply.
/// </value>
public string SignOutWreply { get; set; }

/// <summary>
/// Gets or sets the 'wreply'. CallbackPath must be set to match or cleared so it
/// can be generated dynamically. This field is optional. If not set then it will
/// be generated from the current request and the CallbackPath.
/// </summary>
/// <value>
/// The wreply.
/// </value>
public string Wreply { get; set; }


/// <summary>
/// Indicates if requests to the CallbackPath may also be for other components. If
/// enabled the handler will pass requests through that do not contain WsFederation
/// authentication responses. Disabling this and setting the CallbackPath to a dedicated
/// endpoint may provide better error handling. This is disabled by default.
/// </summary>
/// <value>
/// <c>true</c> if [skip unrecognized requests]; otherwise, <c>false</c>.
/// </value>
public bool SkipUnrecognizedRequests { get; set; }
/// <summary>
/// Gets or sets if a metadata refresh should be attempted after a SecurityTokenSignatureKeyNotFoundException.
/// This allows for automatic recovery in the event of a signature key rollover.
/// This is enabled by default.
/// </summary>
/// <value>
/// <c>true</c> if [refresh on issuer key not found]; otherwise, <c>false</c>.
/// </value>
public bool RefreshOnIssuerKeyNotFound { get; set; }

/// <summary>
/// Gets or sets the address to retrieve the wsFederation metadata
/// </summary>
/// <value>
/// The metadata address.
/// </value>
public string MetadataAddress { get; set; }

/// <summary>
/// The Authentication Scheme to use with SignOutAsync from RemoteSignOutPath. SignInScheme
/// will be used if this is not set.
/// </summary>
/// <value>
/// The sign out scheme.
/// </value>
public string SignOutScheme { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public override ValidationResult Validate(ValidationContext<RemoteAuthentication
nameof(OAuthOptions) => new OAuthOptionsValidator(_provider, _localizer).Validate(options as OAuthOptions),
nameof(MicrosoftAccountOptions) => new OAuthOptionsValidator(_provider, _localizer).Validate(options as OAuthOptions),
nameof(OpenIdConnectOptions) => new OpenIdConnectOptionsValidator(_provider, _localizer).Validate(options as OpenIdConnectOptions),
nameof(WsFederationOptions) => new WsFederationOptionsValidator(_provider, _localizer).Validate(options as WsFederationOptions),
nameof(TwitterOptions) => new TwitterOptionsValidator(_provider, _localizer).Validate(options as TwitterOptions),
_ => base.Validate(context),
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Project: Aguafrommars/TheIdServer
// Copyright (c) 2021 @Olivier Lefebvre
using Aguacongas.TheIdServer.BlazorApp.Models;
using FluentValidation;
using Microsoft.Extensions.Localization;

namespace Aguacongas.TheIdServer.BlazorApp.Validators
{
public class WsFederationOptionsValidator : AbstractValidator<WsFederationOptions>
{
public WsFederationOptionsValidator(ExternalProvider _, IStringLocalizer localizer)
{
RuleFor(m => m.MetadataAddress).NotEmpty().WithMessage(localizer["Metadata address is required."]);
RuleFor(m => m.MetadataAddress).Uri().WithMessage(localizer["Metadata address must be a valid uri."]);
RuleFor(m => m.MetadataAddress).Must((options, value) => !options.RequireHttpsMetadata || value.ToUpperInvariant().StartsWith("HTTPS"))
.WithMessage(localizer["Metadata address must be a valid HTTPS url when 'required https metadata is true'."]);
RuleFor(m => m.Wtrealm).NotEmpty().WithMessage(localizer["Wtrealm is required."]);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.OAuth" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Twitter" Version="5.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.WsFederation" Version="5.0.4" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="5.0.4" />
<PackageReference Include="SendGrid" Version="9.22.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authentication.Twitter;
using Microsoft.AspNetCore.Authentication.WsFederation;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal;
Expand Down Expand Up @@ -198,6 +199,13 @@ private static DynamicAuthenticationBuilder CreateDynamicAuthenticationBuilder<T
context.RunClaimActions(doc.RootElement);
}
};
})
.AddWsFederation(options =>
{
options.Events = new WsFederationEvents
{
OnTicketReceived = OnTicketReceived<TUser>()
};
});

return dynamicBuilder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aguacongas.AspNetCore.Authentication.EntityFramework" Version="4.0.0" />
<PackageReference Include="Aguacongas.AspNetCore.Authentication.EntityFramework" Version="4.0.2" />
<PackageReference Include="Community.OData.Linq" Version="1.4.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.4" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aguacongas.AspNetCore.Authentication.RavenDb" Version="4.0.0" />
<PackageReference Include="Aguacongas.AspNetCore.Authentication.RavenDb" Version="4.0.2" />
<PackageReference Include="Community.OData.Linq" Version="1.4.2" />
<PackageReference Include="Aguacongas.Identity.RavenDb" Version="2.0.0-preview0008" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aguacongas.AspNetCore.Authentication" Version="4.0.0" />
<PackageReference Include="Aguacongas.AspNetCore.Authentication" Version="4.0.2" />
<PackageReference Include="Community.OData.Linq" Version="1.4.2" />
<PackageReference Include="IdentityServer4.EntityFramework.Storage" Version="4.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Aguacongas.AspNetCore.Authentication.TestBase" Version="4.0.0" />
<PackageReference Include="Aguacongas.AspNetCore.Authentication.TestBase" Version="4.0.2" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
<PackageReference Include="xunit" Version="2.4.1" />
Expand Down
Loading

0 comments on commit 0295b1f

Please sign in to comment.