Skip to content

Instantly share code, notes, and snippets.

@michaelkc
Created December 5, 2014 13:34
Show Gist options
  • Save michaelkc/53bc2e897b3acbcdce8b to your computer and use it in GitHub Desktop.
Save michaelkc/53bc2e897b3acbcdce8b to your computer and use it in GitHub Desktop.
using System;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Tokens;
using System.Reflection;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.Text.RegularExpressions;
using System.Threading;
namespace Samples
{
public class WsTrustClient
{
private readonly string _certificateMixedEndpoint;
private readonly string _usernameMixedEndpoint;
public WsTrustClient(string adfsDnsName)
{
if (!Regex.IsMatch(adfsDnsName, @"^[\w-]+(\.[\w-]+)*$", RegexOptions.IgnoreCase))
{
throw new ArgumentException("Supply the DNS-name portion of the ADFS url, e.g. 'idp.dlbr.dk'");
}
const string usernameMixedFormatString = "https://{0}/adfs/services/trust/13/usernamemixed";
const string certificateMixedFormatString = "https://{0}/adfs/services/trust/13/certificatemixed";
_usernameMixedEndpoint = string.Format(usernameMixedFormatString, adfsDnsName);
_certificateMixedEndpoint = string.Format(certificateMixedFormatString, adfsDnsName);
}
public WsTrustClient(string usernameMixedEndpoint, string certificateMixedEndpoint)
{
_usernameMixedEndpoint = usernameMixedEndpoint;
_certificateMixedEndpoint = certificateMixedEndpoint;
}
public Uri ProxyAddress { get; set;}
public virtual SecurityToken GetActAsToken(string realm, string serviceUsername, string servicePassword)
{
var bootstrapToken = ((ClaimsIdentity)Thread.CurrentPrincipal.Identity).BootstrapContext as SecurityToken;
if (bootstrapToken == null)
{
throw new InvalidOperationException("Thread.CurrentPrincipal.Identity.BootstrapContext is null or not a SecurityToken");
}
return GetActAsToken(realm, serviceUsername, servicePassword, bootstrapToken);
}
public virtual SecurityToken GetActAsToken(string realm, string serviceUsername, string servicePassword, SecurityToken bootstrapToken)
{
if (bootstrapToken == null) throw new ArgumentNullException("bootstrapToken");
var factory = CreateUsernameWSTrustChannelFactory();
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
factory.Credentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
factory.Credentials.UserName.UserName = serviceUsername;
factory.Credentials.UserName.Password = servicePassword;
// setup RST
var rst = new RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointReference(realm),
KeyType = KeyTypes.Bearer,
ActAs = new SecurityTokenElement(bootstrapToken)
};
return IssueTokenForRst(factory, rst);
}
public virtual SecurityToken GetActAsToken(string realm, X509Certificate2 serviceCertificate)
{
var bootstrapToken = ((ClaimsIdentity)Thread.CurrentPrincipal.Identity).BootstrapContext as SecurityToken;
return GetActAsToken(realm, serviceCertificate, bootstrapToken);
}
public virtual SecurityToken GetActAsToken(string realm, X509Certificate2 serviceCertificate, SecurityToken bootstrapToken)
{
if (bootstrapToken == null) throw new ArgumentNullException("bootstrapToken");
var factory = CreateCertificateWSTrustChannelFactory();
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
factory.Credentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
factory.Credentials.ClientCertificate.Certificate = serviceCertificate;
// setup RST
var rst = new RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointReference(realm),
KeyType = WSTrust13Constants.KeyTypes.Bearer,
ActAs = new SecurityTokenElement(bootstrapToken)
};
return IssueTokenForRst(factory, rst);
}
public virtual SecurityToken GetSecurityToken(string realm, string username, string password)
{
WSTrustChannelFactory factory = CreateUsernameWSTrustChannelFactory();
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
factory.Credentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
factory.Credentials.UserName.UserName = username;
factory.Credentials.UserName.Password = password;
// setup RST
var rst = new RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointReference(realm),
KeyType = WSTrust13Constants.KeyTypes.Bearer,
};
return IssueTokenForRst(factory, rst);
}
public virtual SecurityToken GetSecurityToken(string realm, X509Certificate2 certificate)
{
// setup ws-trust channel
WSTrustChannelFactory factory = CreateCertificateWSTrustChannelFactory();
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
factory.Credentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
factory.Credentials.ClientCertificate.Certificate = certificate;
// setup RST
var rst = new RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointReference(realm),
KeyType = WSTrust13Constants.KeyTypes.Bearer,
};
return IssueTokenForRst(factory, rst);
}
protected virtual WSTrustChannelFactory CreateUsernameWSTrustChannelFactory()
{
var binding = new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential);
if (ProxyAddress != null)
{
binding.ProxyAddress = ProxyAddress;
}
var factory = new WSTrustChannelFactory(binding, _usernameMixedEndpoint);
return factory;
}
protected virtual WSTrustChannelFactory CreateCertificateWSTrustChannelFactory()
{
var binding = new CertificateWSTrustBinding(SecurityMode.TransportWithMessageCredential);
if (ProxyAddress != null)
{
binding.ProxyAddress = ProxyAddress;
}
var factory = new WSTrustChannelFactory(binding, _certificateMixedEndpoint);
return factory;
}
protected virtual SecurityToken IssueTokenForRst(WSTrustChannelFactory factory, RequestSecurityToken rst)
{
var channel = factory.CreateChannel();
return channel.Issue(rst);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment