Skip to content

Commit

Permalink
Add STS and WSFed test endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
mconnew committed Feb 21, 2020
1 parent 0a2990c commit 5fc8a7a
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,16 @@ private static int Main(string[] args)
};
CreateAndInstallMachineCertificate(certificateGenerate, certificateCreationSettings);

//STSMetaData
certificateCreationSettings = new CertificateCreationSettings()
{
FriendlyName = "WCF Bridge - STSMetaData",
ValidityType = CertificateValidityType.Valid,
Subject = "STSMetaData",
EKU = new List<Org.BouncyCastle.Asn1.X509.KeyPurposeID>()
};
CreateAndInstallMachineCertificate(certificateGenerate, certificateCreationSettings);

//Create and install client cert
certificateCreationSettings = new CertificateCreationSettings()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.IdentityModel;
using System.IdentityModel.Configuration;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Tokens;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;

namespace WcfService
{
[TestServiceDefinition(Schema = ServiceSchema.HTTPS, BasePath = FederationSTSServiceHost.BasePath)]
public class FederationSTSServiceHost : WSTrustServiceHost
{
internal const string BasePath = "LocalSTS.svc";
internal const string RelativePath = "transport";

public FederationSTSServiceHost(params Uri[] baseAddresses)
: base(new SecurityTokenServiceConfiguration(), baseAddresses)
{
ConfigureService();
AddServiceEndpoint(typeof(IWSTrust13SyncContract), GetBinding(), RelativePath);
}

private Binding GetBinding()
{
return new WS2007HttpBinding(SecurityMode.Transport);
}

protected void ConfigureService()
{
base.ApplyConfiguration();
var config = ServiceContract.SecurityTokenServiceConfiguration;
config.SigningCredentials = new X509SigningCredentials(TestHost.CertificateFromFriendlyName(StoreName.My, StoreLocation.LocalMachine, "WCF Bridge - STSMetaData"));
config.ServiceCertificate = TestHost.CertificateFromFriendlyName(StoreName.My, StoreLocation.LocalMachine, "WCF Bridge - Machine certificate generated by the CertificateManager");
config.SecurityTokenService = typeof(SelfHostSecurityTokenService);
config.TokenIssuerName = "SelfHostSTS";
config.SecurityTokenHandlerCollectionManager[SecurityTokenHandlerCollectionManager.Usage.ActAs] = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();
config.SecurityTokenHandlerCollectionManager[SecurityTokenHandlerCollectionManager.Usage.OnBehalfOf] = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();
config.CertificateValidationMode = X509CertificateValidationMode.ChainTrust;
config.IssuerNameRegistry = new ReturnX509SubjectNameOrRSAIssuerNameRegistry();

Credentials.ServiceCertificate.Certificate = config.ServiceCertificate;
Credentials.UseIdentityConfiguration = true;
}

public class ReturnX509SubjectNameOrRSAIssuerNameRegistry : IssuerNameRegistry
{
public override string GetIssuerName(SecurityToken securityToken)
{
var x509Token = securityToken as X509SecurityToken;
var rsaToken = securityToken as RsaSecurityToken;
if (x509Token != null)
{
return x509Token.Certificate.SubjectName.Name;
}
else if (rsaToken != null)
{
return string.Format("RSA-token-{0}", rsaToken.Rsa.ToXmlString(false));
}

return null;
}
}

internal class SelfHostSecurityTokenService : SecurityTokenService
{
public SelfHostSecurityTokenService(SecurityTokenServiceConfiguration configuration)
: base(configuration)
{
}

protected override Scope GetScope(ClaimsPrincipal principal, RequestSecurityToken request)
{
if (principal == null)
throw new ArgumentNullException("principal");

if (request == null)
throw new ArgumentNullException("request");

if (request.AppliesTo == null)
throw new FaultException<InvalidProgramException>(new InvalidProgramException("request.AppliesTo cannot be null"), new FaultReason("request.AppliesTo cannot be null"), new FaultCode("AppliesToNull"), "Set Applies To");

if (request.AppliesTo.Uri == null)
throw new InvalidProgramException("request.AppliesTo.Uri cannot be null");

if (string.IsNullOrWhiteSpace(request.AppliesTo.Uri.OriginalString))
throw new InvalidProgramException("request.AppliesTo.Uri.AbsoluteUri cannot be null or only whitespace");

var scope = new Scope(request.AppliesTo.Uri.OriginalString, SecurityTokenServiceConfiguration.SigningCredentials)
{
TokenEncryptionRequired = false
//EncryptingCredentials = new X509EncryptingCredentials(SecurityTokenServiceConfiguration.ServiceCertificate),
//SymmetricKeyEncryptionRequired = true
};

if (string.IsNullOrEmpty(request.ReplyTo))
scope.ReplyToAddress = scope.AppliesToAddress;
else
scope.ReplyToAddress = request.ReplyTo;

return scope;
}

protected override ClaimsIdentity GetOutputClaimsIdentity(ClaimsPrincipal principal, RequestSecurityToken request, Scope scope)
{
if (principal == null)
throw new ArgumentNullException("principal");

if (request == null)
throw new ArgumentNullException("request");

if (scope == null)
throw new ArgumentNullException("scope");

var outputIdentity = principal.Identity as ClaimsIdentity;
if (request.ActAs != null)
{
var currIdentity = outputIdentity;
foreach (var identity in request.ActAs.GetIdentities())
{
currIdentity.Actor = identity;
currIdentity = identity.Actor;
}
}

return outputIdentity;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.IdentityModel.Tokens;

namespace WcfService
{
[TestServiceDefinition(Schema = ServiceSchema.HTTPS, BasePath = Saml2IssuedTokenTestServiceHost.BasePath)]
public class Saml2IssuedTokenTestServiceHost : TestServiceHostBase<IWcfService>
{
private const string BasePath = "Saml2IssuedToken.svc";
private const string Saml20TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0";

protected override string Address { get { return "issued-token-using-tls"; } }

protected override Binding GetBinding()
{
var authorityBinding = new WSHttpBinding(SecurityMode.Transport);
var serviceBinding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
serviceBinding.Security.Message.IssuedTokenType = Saml20TokenType;
var serverBasePathUri = BaseAddresses[0];
var issuerUri = new Uri(serverBasePathUri, FederationSTSServiceHost.BasePath + "/" + FederationSTSServiceHost.RelativePath);
serviceBinding.Security.Message.IssuerAddress = new EndpointAddress(issuerUri);
serviceBinding.Security.Message.IssuerBinding = authorityBinding;
serviceBinding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
serviceBinding.Security.Message.EstablishSecurityContext = false;
return serviceBinding;
}

protected override void ApplyConfiguration()
{
base.ApplyConfiguration();
Credentials.ServiceCertificate.Certificate = TestHost.CertificateFromFriendlyName(StoreName.My, StoreLocation.LocalMachine, "WCF Bridge - Machine certificate generated by the CertificateManager");
Credentials.UseIdentityConfiguration = true;
var serverBasePathUri = BaseAddresses[0];
var audienceUri = new Uri(serverBasePathUri, BasePath + "/" + Address);
Credentials.IdentityConfiguration.AudienceRestriction.AllowedAudienceUris.Add(audienceUri);
Credentials.IdentityConfiguration.CertificateValidationMode = X509CertificateValidationMode.None;
var issuerUri = new Uri(serverBasePathUri, FederationSTSServiceHost.BasePath + "/" + FederationSTSServiceHost.RelativePath);
Credentials.IdentityConfiguration.IssuerNameRegistry = new CustomIssuerNameRegistry(issuerUri.ToString());
}

public Saml2IssuedTokenTestServiceHost(params Uri[] baseAddresses)
: base(typeof(WcfService), baseAddresses)
{
}

class CustomIssuerNameRegistry : IssuerNameRegistry
{
string _issuer;
public CustomIssuerNameRegistry(string issuer)
{
_issuer = issuer;
}

public override string GetIssuerName(SecurityToken securityToken)
{
return _issuer;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\IISHostedWcfService\**\*.cs" />
<Compile Include="..\IISHostedWcfService\**\*.cs">
<Visible>true</Visible>
<Link>IIS/%(RecursiveDir)%(Filename)%(Extension)</Link>
</Compile>
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
Expand Down

0 comments on commit 5fc8a7a

Please sign in to comment.