How to acquire token from ADFS under logged on user

Oct 10, 2013 at 10:47 AM
Edited Oct 10, 2013 at 10:49 AM
Hi,

I'm currently stuck with problem of acquiring token from ADFS 2.0 under logged on domain user.

Here is the code I use:
            using (var factory = new WSTrustChannelFactory(new KerberosWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress(new Uri(internalAdfsEndpoint))))
            {
                factory.TrustVersion = TrustVersion.WSTrust13;
                factory.Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
                WSTrustChannel channel = null;
                factory.ConfigureChannelFactory();

                try
                {
                    var rst = new RequestSecurityToken
                    {
                        RequestType = WSTrust13Constants.RequestTypes.Issue,
                        AppliesTo = new EndpointAddress(apiAdfsEndpoint),
                        KeyType = KeyTypes.Symmetric,
                    };

                    channel = (WSTrustChannel)factory.CreateChannel();

                    RequestSecurityTokenResponse response;
                    var token = channel.Issue(rst, out response);

                    return token;
                }
                finally
                {
                    if (channel != null)
                    {
                        channel.Abort();
                    }

                    factory.Abort();
                }
            }
My scenario is:
  1. Get (symmetric) token from ADFS A (user domain) under logged on account. (Note: From inside a SharePoint Web Part). I use ADFS endpoint: https://adfsServer/adfs/services/trust/13/kerberosmixed.
  2. Get SAML token from ADFS B (Federation Provider) from above token in order to access my service (trusting ADFS B).
  3. Call my service with SAML token
When using UserNameWSTrustBinding, and specify the domain username/password (Step 1), everything works fine.

However, when using KerberosWSTrustBinding, I got two different issues:
  1. If I logged on the a machine in the domain, I got the token for the SharePoint service account instead of my domain account.
  2. If I access SharePoint from external network, and log on with my domain account. I got exception:
System.IdentityModel.Tokens.SecurityTokenValidationException: The NetworkCredentials provided were unable to create a Kerberos credential, see inner execption for details. ---> System.IdentityModel.Tokens.SecurityTokenException: InitializeSecurityContent failed. Ensure the service principal name is correct. ---> System.ComponentModel.Win32Exception: No credentials are available in the security package
Please advise me how to get the valid token for the logged on domain account.

Thanks so much in advance.
Oct 11, 2013 at 4:03 AM
Edited Oct 11, 2013 at 4:05 AM
UPDATED:

I have found out few more things about the first issue: The token was actually issued for the user account I used to log on domain machine, not the account I used to log on SharePoint sites. I was using the SharePoint service account to log on the domain machine, and then logging on SharePoint sites using another account.

Here comes another question: How can I get the token for the account used to log on SharePoint sites? Not the account used to log on domain machine.
Oct 15, 2013 at 3:30 PM
Hello duyph,

The scenario that you are trying to implement seems to be an Identity Delegation scenario. In order to achieve this you would need to get an ActAs token from ADFS for the current user and then make your call to the other service.
In order to request an ActAs token from ADFS you will need to use the bootstrap token of the user. (Tip: Make sure you set this setting in the identityModel section: saveBootstrapTokens="true")

Finally on the ADFS side, in order to enable the ActAs feature for your Relying Party, you will need to create a Delegation Authorization Rule to allow it.

For more information you can refer to the following ADFS Guide:

I hope this helps,
Gabriel Ostrowsky
http://blogs.southworks.net/gostrowsky
Oct 18, 2013 at 8:25 AM
Hi Gabriel,

Thanks for your useful and detailed information.

To be honest, I have never tried to do an ActAs scenario yet. However, I think my case is different: I'm not calling service from a Relying Party, instead I try to get the token from ADFS and send it as a custom authorization header with service call (REST service).

But you are right about the Identity Delegation, which is exactly what I'm looking into right now :). But in my case, it is Identity Delegation in SharePoint.

Best Regards,
Duy Pham.
Oct 18, 2013 at 5:11 PM
Hi Duy,

I am glad that you found the information useful.
Maybe I have not made myself clear before. I did not want to say that you should make a call from the Relying Party (that would not be possible). Instead, you would only allow getting ActAs tokens from it.

Regards,
Gabriel Ostrowsky
https://blogs.southworks.net/gostrowsky
Dec 13, 2013 at 8:04 AM
Hi Gabriel,

Sorry that we have been quite busy to post the result of Delegation configuration.
If I logged on the a machine in the domain, I got the token for the SharePoint service account instead of my domain account.
This turned out to be our ASP.NET cache issue.
If I access SharePoint from external network, and log on with my domain account. I got exception:
We have successfully configured Identity Delegate for SharePoint to get through the issue, and here are how we do:
  1. On SharePoint Server, grant 'Act as part of operating system' permission for the SharePoint Service Account (which is used to run SharePoint AppPool)
  2. Configure Identity Delegation using Kerberos Authentication for SharePoint Service Account as described in http://social.technet.microsoft.com/wiki/contents/articles/5948.sharepoint-2010-configuring-kerberos-authentication.aspx
    • However, we don't configure Kerberos Authentication for SharePoint Web App because we don't need it
    • We configure delegation for specific service and user (in our case it it HOST/adfsServer which is internal ADFS service)
Regards,
Duy Pham.