Tag Archives | sso

ADFS 2.0 – Choose Your Attributes Wisely

If you’ve read my last few posts you’ll be aware that I’m in the middle of implementing ADFS 2.0 for Web SSO. SalesForce for starters, with more to follow.  I’m yet to put it into production but I was thinking today and just having a bit of a sanity check and something occurred to me.  We send LDAP attributes as claims, the attributes are accepted by our service provider as law. They trust our federation service – that’s what federation is all about. Trust.  There are number of mechanisms that make it very difficult for someone to spoof an assertion. On the whole, the SAML protocol can be considered very secure.  What it can’t do is guarantee the validity of the source LDAP attribute.


Consider the scenario above.  We’re going to send the User’s telephone number as a claim.  Maybe unlikely but it could happen, maybe you’ve got a SaS provider and you’ve already got 500 users in the system and telephone number is the only field you know is accurate between you and them. Unlikely? I know.   But that’s not the point.

The issue is this – in Active Directory the attribute telephoneNumber, along with a few other attributes is by default, self writeable.

Once Dave figure’s out that the telephone number is significant he’ll update his phone number in AD to Bob’s phone number, launch the SaS app and will be logged in as Bob.


While there are only a few self writeable attributes in AD and they’re not ones you’d likely use for federation, it’s important to keep the whole picture in mind and the problem could go beyond self writeable attributes.  A couple of other situations I can think of off the top of my head:

  • Active directory self service applications which allows users to update attributes which aren’t normally self writeable
  • Identity management systems which synchronise other systems to Active Directory.  Not a problem in itself but you might be moving the point authorization for a specific application without realising it.

So choose your attributes wisely and make sure you know how, why, when and by whom or what they are written to before you decide to send them as federation claims.


SalesForce SSO with ADFS 2.0 – Everything you need to Know


-14/01/2013 – Workaround for iPads and SSO!
Rohan writes to tell us that:

“If you activate Touch in your Org and set touch to be used for Browser access then an iPad will via Safari use the mobile touch interface.  You’ll need to have http redirect set, and (As below) you are limited to the touch “app” so no chatter app or dashboards app.
That said, dashboards are meant to be coming to touch shortly so perhaps touch via the browser is enough.”

Cheers Rohan!


– 15/10/2012 – ADFS 2.0 / SalesForce + iPad/Safari Working!
SalesForce have added a new option to change the SAML binding method from HTTP POST to HTTP REDIRECT. Using HTTP REDIRECT seems to fix the issue with ipad/Safari and ADFS 2.0. You can find this in the SSO settings.



In my last post I went over the basic concept of federation using SAML 2.0, today I’ll show you how to configure single sign-on for SalesForce using ADFS 2.0.  This is a really nice solution because it’s easy to set up and doesn’t cost you anything except the Windows 2008 OS licence.

ADFS 2.0 is Microsoft’s answer to federation – it includes their own implementation of SAML 2.0.  It runs on Windows Server 2008 [R2] and is installed from a separate downloadable package.  It is not the ADFS ‘role’ which can be enabled in Windows Server 2008 R2, that’s ADFS 1.0 (not cool).

If you don’t feel you have a good grasp of SAML 2.0 I suggest that you set up ADFS 2.0 (as IdP) and Shibboleth (as SP) in a lab environment.  There’s no better way to learn about a particular technology than to interface Microsoft’s implementation with its open source counterpart!  There’s a great MSDN blog post that walks you through the set up.  I really learnt a lot by doing this.




Let’s first take a look at an overview of the process then we’ll dive into the configuration.  The diagram below shows the process for an IdP-initiated login into SalesForce – later we’ll look at SP-initiated login.


  1. The user authenticates to the ADFS server using Kerberos and requests login to SalesForce
  2. ADFS returns a SAML assertion to the user’s browser
  3. The browser automatically submits the assertion to SalesForce who logs the user in




  • Start with Windows Server 2008 [R2] – Domain Joined
  • Create a friendly DNS name for ADFS and point it to your adfs server. e.g adfs.testzone.local
  • Download and install ADFS 2.0. Federation Server role. This will install all pre-requisites
  • In the IIS manager create an SSL certificate for your friendly DNS name or use SelfSSL from the IIS 6.0 resource kit to create a self-signed certificate
  • Run through the ADFS Server configuration wizard
    • Create a new federation Service
    • Stand-alone server
    • Select the certificate that you created for your friendly DNS name
  • Create an SPN for the DNS name so that Kerberos authentication between the browser and the ADFS IIS instance works correctly
setspn -a HOST/adfs.testzone.local testzone\ADFSSVR01
setspn -a HOST/adfs testzone\ADFSSVR01

For more info on Kerberos SPNs see my Active Directory and Kerberos SPNs Made Easy post


To build a federation between two parties we need to establish a trust by exchanging some metadata.  The metadata for our ADFS 2.0 instance is entered manually into the SalesForce configuration.  SalesForce metadata is downloaded as an XML file which ADFS 2.0 can consume.


SalesForce Configuration

In the ADFS 2.0 MMC snap-in select the certificates node and double click the token-signing certificate to view it.


Go to details and “Copy to File”.  Save the certificate in DER format.


On the ADFS server browse to your federation metadata URL which can be found in the ADFS MMC\Endpoints|Metadata|Type:Federation Metadata.  In my case: https://adfs.testzone.local/FederationMetadata/2007-06/FederationMetadata.xml


Copy the entityID.  In my case http://adfs.testzone.local/adfs/services/trust

Go to SalesForce Setup\Security Controls\Single Sign-On Settings\

  • SAML Enabled: Ticked
  • SAML Version: 2.0
  • Identity Provider Certificate: Browse and select the token-signing certificate you exported earlier
  • Issuer: Paste your entityID in here
  • Identity Provider Login URL: This is the URL of your ADFS SAML endpoint where SalesForce will send SAML requests for SP-initiated login.  This can be found in ADFS MMC\Endpoints|Token Issuance|Type:SAML 2.0/WS-Federation (In my case: https://adfs.testzone.local/adfs/ls/ )
  • SAML User ID Type: To log a user on we can either match against their SalesForce username or we can match against their federation ID which would need to be populated in the profile of every user.  For testing select federation ID.  If your users currently use their email address as their SalesForce username then when you come to roll out SSO into production you can switch to sending the username.
  • SAML User ID Location: To log the user on we can either use the NameID in the SAML assertion or we can use some other attribute. NameID should suffice.
  • Entity ID: This is how our ADFS IdP will identify the SalesForce SP.  I just left it as https://saml.salesforce.com.  If you were supporting multiple SalesForce instances from the same ADFS instance then you’d want to use the more unique name.  This is also the identifier we use when we do a IdP-initiated login with ADFS

Save the settings and download the Metadata xml file.


ADFS 2.0 Configuration

Now that we have the metadata for SalesForce we can create the trust on the ADFS side.

Open the ADFS 2.0 MMC snapin and add a new “Relying Party Trust”:

  • Select Data Source: Import data about a relying party from a file. Browse to the XML you downloaded from SalesForce
  • Display Name: Give the trust a display name e.g. ‘SalesForce Sandbox’
  • Choose Issuance Authorization Rules: Permit all users to access this relying party
  • Open Edit Claim Rues Dialog: Ticked

In the claim rules editor select the “Issuance Transform Rules” tab

Add a new rule:

  • Claim Rule Template: Send LDAP Attributes as Claims
  • Claim Rule Name: For testing we’ll send the UPN as NameID so call the rule: “Send UPN as NameID” In production you might send the user’s email address or employee ID *
  • LDAP Attribute: User Principal Name
  • Outgoing Claim Type: Name ID

*Update:See my post on choosing you’re attributes wisely. There’s a potential security pitfall here.


SP-Initiated Login

With IdP-initiated login you would typically set up a link on the company intranet that users would click to get access to SalesForce.  SP-initiated login happens when a user clicks a direct link to SalesForce.  For this to work we need to set the secure hash algorithm to SHA1 instead of the default SHA-256.  This is set in SalesForce relying party trust properties under advanced.

If you don’t set this you’ll get the following message in to the ADFS event log:

Event ID: 378

SAML request is not signed with expected signature algorithm. SAML request is signed with signature algorithm http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 . Expected signature algorithm is http://www.w3.org/2000/09/xmldsig#rsa-sha1



With My Domain

It’s best practice to implement the “My Domain” feature at the same time as implementing SSO if you haven’t already done so. “My Domain” gives you your own subdomain on SalesForce. e.g. MyCompany.my.salesforce.com.  When you click a “My Domain” link SalesForce will know to redirect you to your Idp (ADFS) to be authenticated.


Without My Domain

As long as the user has performed at least one IdP-initated login from a given browser SalesForce will have set a cookie so in future it knows to redirect the browser to the IdP with a SAML request.  The IdP will in turn issue a SAML response for the browser to pass back to SalesForce.

You might find some SalesForce documentation that mentions the ssoStartPage attribute which can be set in the SAML assertion.  I found that this wasn’t necessary, and if you look at the cookie you get after an IdP-initiated login you’ll see that ssoStartPage is set to the IdP login URL you specified in the SalesForce SSO configuration.



You can specify a URL to redirect to when the user logs out by creating a custom claim rule which sends an additional logoutURL attribute.

The custom rule is as follows:

=> issue(Type = "logoutURL", Value = "http://intranet.youcompany.com", Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/attributename"] = "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified");





Alright, so that should be about it.  We can now go and set the Federation ID of a SalesForce user to the UPN our own AD user account and see if it all works.

Point your browser to your ADFS IdP-initiated login URL and specify the loginToRp parameter as the SalesForce SAML entity ID.
E.g. https://adfs.testzone.local/adfs/ls/idpinitiatedsignon.aspx?loginToRp=https://saml.salesforce.com

This should redirect you and sign you into SalesForce.  If you get a SalesForce login error use the SAML assertion validator tool on the SalesForce single sign-on configuration page.  It will display the results of the last failed SAML login.



If you get an error from ADFS then check the ADFS logs in Server Manager\Diagnostics\Applications and Services Logs\ADFS 2.0\Admin.  There is also a very good MSDN blog post on ADFS 2.0 diagnostics.


Once you have IdP-initiated login working try SP-initiated.  Copy a link from deep inside SalesForce then log out.  Reload your browser and paste the in the URL.  You should be seamlessly redirected to your IdP, authenticated and then redirected back to the link you requested.


Portal SSO and JIT Provisioning

There’s plenty of good info in the Force.com literature for portal SSO and just-in-time provisioning but here’s some ADFS 2.0 specific stuff.  I’ve only been playing with this for a couple of weeks but I’ve had requests for the info so here’s what I’ve got so far.  Let me know if I’ve missed something or I’ve got something wrong.


Portal SSO

To do a Portal SSO login you need to send the portal ID and the Org ID as claims using custom claims rules.  There is significant caveat though, if you’re using ADFS to do SSO for both full-License and portal users.  If you send the Portal ID and the Org ID for a full-license user SalesForce will assume you are trying to log into a portal.  This will result in a SAML error because a full-license user can’t also be a portal user.   To overcome this you can use a condition in the custom rule so the portal ID and Org ID are only sent if the user is a member of a given Active Directory group.  The rules below use the AD group SID which you can find using pstool psgetsid.exe.  The advantage of using an SID is that if the group is renamed the SID stays the same.

Send Portal ID

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value =~ "^(?i)S-1-5-21-1458536374-0499464381-951853424-103426$"]
 => issue(Type = "portal_id", Value = "033G00000002a1P");

Send Org ID

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value =~ "^(?i)S-1-5-21-1458536374-0499464381-951853424-103426$"]
 => issue(Type = "organization_id", Value = "01GK00000004ra2");


I haven’t found a way to send send a claim only if a user is not a member of a group, and the ADFS 2.0 claims rules language reference is non-existent!  If someone works this out please let me know.


JIT Provisioning

Just-in-time provisioning allows you to create users on the fly with a SAML assertion as they attempt to login.  All you need to do is enable JIT in your SSO settings and then send the required attributes.  JIT custom claims rules are just like the portal ones above.  The SalesForce Single Sign-On Implementation Guide has all the details on what attrbiutes to need to be sent.  Here’s a few things to keep in mind:

  • You can provision and update users into specific profiles or rolls based on Active Directory groups just like with the portal logins above, but you’ll need to manage the AD groups carefully – you couldn’t have a user in multiple groups which represent different SalesForce profiles or rolls
  • You can provision and update users but you can’t un-provision them. Again you’ll need to use Active directory security groups to determine who can be JIT provisioned and you’ll have to manage your licensees and account De-activations outside JIT
  • JIT can’t be used to provision Portal accounts!
    *Update* It looks like this has changed and it is now supported. Thanks Tim for pointing this out!
  • I found that I couldn’t JIT provision users if chatter wasn’t enabled – still waiting for the word on this from SalesForce


Further Analysis

In case you’re wondering how the browser collects and passes these SAML requests and responses around, we’ll take a closer look at the entire process.

We’ll go over the SP-Initiated login because it has the most steps and really demonstrates SAML and federation at its best.  I’ll use screen shots of Fiddler2 to show you exactly what’s happening at each step.

Note* Fiddler messes with Windows integrated authentication to IIS so you’ll need to turn off extended protection on the /adfs/ls/ virtual directory if you want to try this.  Otherwise your browser won’t authenticate with ADFS and you’ll see event 4625 with error 0xc000035b in the Windows security log on the ADFS server.


Step 1

The user clicks a direct link to a SalesForce page. The browser connects and SalesForce reads the ssoStartPage attribute from the user’s cookie.  SalesForce uses JavaScript to redirect the browser to the SalesForce SAML request generator.  The SAML request generator creates a SAML request for the IdP by sending an invisible HTML form with hidden fields back to the browser.  It then uses JavaScript to automatically submit the form to the IdP SAML endpoint.


Step 2

The browser submits the HTML form which contains the SAML request to the ADFS SAML endpoint.  Since we are using Windows integrated authentication, ADFS redirects the browser to the /auth/ingetrated/ directory at which point a 401 (User must authenticate) is sent.  Finally, the user is authenticated using Kerberos and ADFS serves up a SAML response.  Again, the SAML message is returned to the browser in an HTML form which is then submitted to the SalesForce SAML endpoint using JavaScript.


Step 3

The browser submits the HTML form which contains the SAML response to the SalesForce SAML endpoint which verifies the SAML assertion, logs the user in and redirects the browser to the original requested URL.


Common Issues & Troubleshooting

Here are some of the issues you might com across.  Thanks to everyone who has commented and shared their experience – I’ll keep updating this section.


Federation ID is case sensitive
One thing to watch out for is the Federation ID is case-sensitive. So if this is your organizational email, be sure to enter it exactly as AD FS sends it, or Salesforce won’t be able to find the matching user.

I’ve looked into writing a custom claim rule to normalize the case the lase of the LDAP attribute before sending it but  it looks like it’s not possible the claims language doesn’t seem to have any string manipulation except a basic regex replace.


Assertion Expired
An assertion’s timestamp is more than five minutes old.
Note: Salesforce does make an allowance of three minutes for clock skew. This means, in practice, that an
assertion can be as much as eight minutes passed the timestamp time, or three minutes before it. This amount
of time may be less if the assertion’s validity period is less than five minutes.

So make sure your clock as sync’d to a good internet time source.


Preventing Users Using Their old Username/Password

It doesn’t seem to be possible to prevent users from logging in using the standard method which is a bit of a pain. There is an idea you can promote here to get this feature implemented:



Well that’s it! Everything you need to know about SalesForce WebSSO with ADFS 2.0.

Federation is really cool, so make sure you encourage its use in your organisation instead of older methods involving clunky tightly coupled links and horrible things like allowing your cloud vendor to do LDAP authentication against your domain controllers over VPNs etc!

Thanks for reading and please ask questions, make comments and corrections.  I’ll continue to update this post as we go.




  • Added JIT and Portal SSO info
  • Updated SP-initiated login with “My Domain” info – Thanks to Pat over at SalesForce for helping out this this



SAML WebSSO & Federation Made Easy


This week I found myself on a SalesForce/SAML/Federation journey which turned out to be very enlightening. Until a few days ago I really had no idea how SAML or Federation worked and it took me a few hours to get my head around it, so I’m going to try explain SAML in a way that’s easy to understand.

SAML 2.0 (Security Assertion Markup Language).

2 Companies:
Company A (Service Provider – SP) has a web application
Company B (Identity Provider –  IdP) has a database of people who need to access Company A’s application

We have a few options here:

  1. Company A could create a new database of people with usernames and passwords within the web application
  2. We could synchronise the database of people including their usernames and passwords from Company B to Company A
  3. We could make a link from the web application to Company B’s database of people and do lookups in real-time
  4. We could tell the web application at Company A to trust users who come from Company B

Options 1 through 3 are pretty crappy.  Option 4 is called federation and it’s cool.

Here’s what happens (part analogy, part reality):

Both companies have a pair of keys. A public key and a private key.  Once something is locked with the private key only the corresponding public key can open it.  Company A has a copy of Company B’s public key and vice versa.

A user in Company B tries to access the web application at Company A.  The web application looks for a cookie in the user’s browser to see if he is already authenticated, he is not so the web application (SP) redirects the browser to Company B’s IdP, telling him – “Go and get a ticket!”

The browser goes to Company B’s IdP who authenticates the user against Company B’s database of users. The IdP at Company B locks the user’s employee ID with his private key, gives it to the browser and tells him – “Here’s your ticket now go back to the SP you came from!”

The browser goes back to the web application (SP) at Company A and presents his ticket.  The SP uses Company B’s public key to unlock the ticket.  The web application says to himself –  “It works! This user MUST have come from Company B because otherwise this public key could NOT have unlocked this ticket. And look, the ticket contains an employee ID and I have a rule that says that this employee ID is allowed access!” And so the web application gives the browser a cookie which allows him access.


In SAML the ticket is called an Assertion.  In this case we sent the Employee ID but any other user-unique attribute could be used, it just needs to be agreed between the 2 parties.

In reality the web application might not support SAML directly but instead maybe protected by a federation product which takes care of the SAML SP stuff.  The IdP stuff will also likely be handled by a federation product which is backed by some kind of LDAP directory or maybe SQL.  The browser cookie stuff mentioned above is outside the scope of SAML but I included it for completeness – It’s typical of how these things work.


The neat thing about federation is that you don’t need any links between Company A and Company B. Once the trust is established everything else takes place “browser to SP” and “browser to IdP” through a series or re-directs and http POSTs.


Ok so that’s SAML.  Actually there are a lot more parts to it than that but that’s the way it’s most commonly used today i.e. for WebSSO.  Now that you have the concept, you can dig into the technical details.

I found Google’s explanation useful:

and Wikipedia :



The best way to learn this stuff is to give it a go.  Check out Shibboleth which is an open source SAML SP and IdP implementation.  I’ve got the Shibboleth SP side talking to ADFS 2.0  as the IdP but I haven’t played with the Shibboleth IdP yet.


Next time I’ll show you how to put SAML to use with Active Directory Federation Services 2.0 and cloud provider SalesForce.  In the mean time feel free to ask questions or make corrections.


Citrix Web Interface with ISA Single Sign On

It’s been a long time since my last post!  I’ve been so busy working on the house (but nothing really blog-worthy).  Anyway today a colleague and I went through and set up the Citrix Web Interface (5.x) with single-sign-on using Microsoft ISA 2006.

The Web Interface and Secure Gateway run on the same server but are configured completely independently of each other, they could just as well be on separate servers if the load warranted it.  They both listen on port 443 on separate IP addresses with separate certificates.

On the face of it, it seems quite straight forward – configure the Web Interface for pass-through authentication, create an ISA web publishing rule using our common SSO web listener with forms based authentication and configure an authentication delegation method.  This works just fine as far as getting the user logged in with their list of applications.

Next step – configure the CSG to listen on a separate IP address with a separate certificate and configure a NAT rule so the ICA client can connect directly to the CSG.  Again fairly straight forward.

Here’s the catch. Using pass-through on the web interface doesn’t work with the CSG.  Pass-through mode expects the client to be domain-joined, inside the corporate network and able to authenticate directly with the XenApp Server (as opposed to being pre-authenticated by the XML/STA services).  The result with the above configuration is that when the user launches an application they are presented with a Windows login dialog which defeats the purpose of single-sign-on.

The solution – ASP.Net “jump” page on the web interface.

Configure the Web Interface in “Explicit ” mode rather than pass-through.  This is the standard method where the user is presented with the Citrix Web Interface login form.

Configure the ISA web publishing rule to delegate “basic” credentials. i.e. clear text user-name/password (secured with SSL of course!).

Create an ASP.NET jump page which extracts the user-name and password from the HTTP request, and creates a form with hidden fields then uses java script to POST the form to the Web Interface login page.

This all happens instantly without the user noticing.  Don’t configure the Web Interface as the default IIS page, instead place the jump page in the root of the IIS web site and set the document priority to to serve it up first.  Here’s the code:  (Download link at the end of the post)


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AuthPass.aspx.cs" Inherits="AuthPass" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<body onload="submitlogin()">
		<div id="FormContainer" runat="server">
<script type="text/javascript" language="javascript">
	 function submitlogin()

AuthPass.aspx.cs Note: The domain field needs to be set to your own domain or removed completely depending on how your users login.  The form action needs to point to your Web Interface login.aspx page.

using System;
using System.Net;
using System.Text;
using System.Web;
public partial class AuthPass: System.Web.UI.Page
    protected void Page_Load(object sender, EventArgs e)
		FormContainer.InnerHtml = doLogin(Request.ServerVariables["AUTH_USER"],Request.ServerVariables["AUTH_PASSWORD"]);
	private String doLogin(String strUser, String strPassword)
		StringBuilder strForm = new StringBuilder();
		strForm.Append("&lt;form name=\"CitrixForm\" action=\"https://citrix.corp.com/Citrix/XenApp/auth/login.aspx\" method=\"post\"&gt;");
		strForm.Append("&lt;input type=\"hidden\" name=\"domain\" value=\"MyDomain\"&gt;");
		strForm.Append("&lt;input type=\"hidden\" name=\"user\" value=\"{0}\"&gt;");
		strForm.Append("&lt;input type=\"hidden\" name=\"password\" value=\"{1}\"&gt;");
		strForm.Append("&lt;input type=\"hidden\" name=\"LoginType\" value=\"Explicit\"&gt;");
		return String.Format(strForm.ToString(), strUser, strPassword);

Here are the key points.

ISA 2006

  • Web publishing rule with SSO WebListener using forms based Authentication
  • “Basic” authentication delegation  (SSL end to end!)
  • Published logoff URL is set to /Citrix/XenApp/site/logout.aspx
  • Simple NAT rule for CSG

Web Interface

  • A new XenApp site is created in the Web Interface Management tool with “At Web Interface” configured for the “Where user authentication takes place” setting
  • Authentication Method set to Explicit
  • AuthPass.aspx[.cs] files are placed in the root of the IIS website to handle auto-login
  • XenApp web site is not configured as the default IIS site.  AuthPass.aspx is set as the default page on the IIS web site
  • Secure access mode is set to “Gateway Direct” but this will depend on your environment


  • This CSG is entirely configure using the CSG Management Console
  • A specific certificate for the CSG is selected
  • The CSG is set to listen on specific IP address rather than the default of all IPv4 addresses (an additional address must be added to the server’s TCP config).
  • “Direct” mode is configured for the Web Interface location

There you have it.  Citrix WI/CSG SSO for ISA.  I know it’s a bit of a hack but I spent some time trying to find a way to do this natively with Citrix Web Interface configuration and posted in the Citrix support forums without any success.  If there is a more official way to do it I’d love to hear about it.

On a side note…

I found a long delay during login which was fixed by disabling NetBIOS over TCP/IP on the web interface server

Citrix Web Interface SSO for MS ISA (966 downloads)