I'm trying to create a WCF service for SAML impersonation. The idea is that the WCF Service uses the WindowsIdentity (Service for User Logon) and Identity Delegation features to create a Delegation SAML Token via ADFS that can be used to authenticate as this user in another service based on IdP-initiated SAML login flow.
This is my first time working with .NET, C# and ASP-Web Apps, so there may be issues within the Code or configuration (ADFS, IIS, certificates etc.)
So far my idea (important code pieces) is as follows:
private static GenericXmlSecurityToken GetServiceTokenForUser(string usernameAtDomain)
{
// Obtain the user Identity token using WindowsIdentityConstructor
WindowsIdentity winId = new WindowsIdentity(usernameAtDomain);
WindowsImpersonationContext ctx = winId.Impersonate();
GenericXmlSecurityToken token = null;
try
{
// via impersonated user,
token = GetServiceTokenForUser();
} finally
{
ctx.Undo();
}
return token;
}
[OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
private static GenericXmlSecurityToken GetServiceTokenForUser()
{
EndpointAddress endpoint;
GenericXmlSecurityToken securityToken;
RequestSecurityToken rst;
RequestSecurityTokenResponse rstr;
WindowsWSTrustBinding binding;
WSTrustChannel channel;
WSTrustChannelFactory factory;
//ignores certificates error
ServicePointManager.ServerCertificateValidationCallback = (x, y, z, w) => true;
// use WindowsWSTrustBinding for credentials -> should be the impersonated user
binding = new WindowsWSTrustBinding(SecurityMode.TransportWithMessageCredential);
endpoint = new EndpointAddress(new Uri(stsEndpoint));
factory = new WSTrustChannelFactory(binding, endpoint);
factory.TrustVersion = TrustVersion.WSTrust13;
rst = new RequestSecurityToken
{
AppliesTo = new EndpointReference(relyingPartyId),
KeyType = KeyTypes.Bearer,
RequestType = RequestTypes.Issue,
TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"
};
channel = (WSTrustChannel)factory.CreateChannel();
// retrieve valid SAML security token
SecurityToken issuedToken = channel.Issue(rst, out rstr);
securityToken = issuedToken as GenericXmlSecurityToken;
return securityToken;
}
When trying to run that in an endpoint that should just return the generated SAML Token (for now), I'm currently running into the following issue:
Unable to load DLL 'security.Dll': Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542)
Server stack trace:
at System.IdentityModel.SafeFreeCredentials.AcquireCredentialsHandle(String package, CredentialUse intent, AuthIdentityEx& authdata, SafeFreeCredentials& outCredential)
at System.IdentityModel.SspiWrapper.AcquireCredentialsHandle(String package, CredentialUse intent, AuthIdentityEx& authdata)
at System.ServiceModel.Security.SecurityUtils.GetCredentialsHandle(String package, NetworkCredential credential, Boolean isServer, String[] additionalPackages)
I arrived at this error after adding various necessary packages to the project, e.g. Microsoft.IdentityModel
.
From my understanding, the service is unable to access the security.dll
. However, the system's security.dll
exists in C:\Windows\System32
.
The Error Either a required impersonation level was not provided, or the provided impersonation level is invalid
suggests that there might be something wrong with the impersonation grant. I found various articles that solve similar issues by adding certain configuration to either the server's Web.config
, or the client's App.config
, but trying to adjust them didn't work in my case (it's very possible however that I didn't adjust the configuration file properly).
Any help with this topic is highly appreciated! Please let me know if you are missing any information in this Question that I should provide additionally.
User contributions licensed under CC BY-SA 3.0