Created
December 5, 2014 13:34
-
-
Save michaelkc/53bc2e897b3acbcdce8b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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