Enabling Single Sign-On with the Force.com Platform

Source code:

Problem

You want to validate usernames and passwords for Salesforce.com against your corporate user database or another client application rather than having separate user passwords managed by Salesforce.com.

Solution

Salesforce.com offers two ways to use single sign-on:

Delegated Authentication

Use delegated authentication if you have mobile users in your organization, or if you want to enable single-sign on for partner portals or Customer Portals. You must request that this feature be enabled by salesforce.com. This recipe explains delegated authentication in more detail.

Federated Authentication using SAML

Federated authentication uses SAML, an industry standard for secure integrations. Investing in SAML with Salesforce.com can be leveraged with other products or services. If you use SAML, you don't have to expose an internal server to the Internet: the secure integration is done using the browser. In addition, Salesforce.com never handles any passwords used by your organization. For more information, see “Configuring SAML Settings for Single Sign-On” in the Salesforce.com online help.

When delegated authentication is enabled, salesforce.com does not validate a user's password. Instead, salesforce.com makes a Web services call to your organization to establish authentication credentials for the user.

When implementing delegated authentication, select one of the following security modes:

Simple passwords

Users directly provide passwords that the delegated authentication server evaluates. In this mode, users can also use the Salesforce.com login page and all of the Salesforce.com clients without modification or extra infrastructure.

Tokens

Instead of passwords, security tokens are provided, and the delegated authentication server evaluates these. This mode hides all passwords from Salesforce.com. Instead of a user signing onto a Salesforce.com login page, the user signs onto a private login page on your company's web server that may be behind your corporate firewall. In this mode, the user is authenticated on that private login page. When the user has been successfully authenticated, the user is redirected to the Salesforce.com login page and logged in using a single-use token. In this mode, users can't login directly to the Salesforce.com login page (users can't generate tokens), and they can't directly login using a client or mobile app. This recipe uses this mode.

Mixed

Your organization creates a delegated authentication server that can evaluate either tokens or passwords. This enables organizations to mobile and client apps, while still providing their users with a private login page. [note] Contact salesforce.com to enable delegated authentication for your organization if it is not already enabled. [/note]

To enable delegated authentication for your organization, build your delegated authentication Web service, and then configure your Salesforce.com organization to enable the Web service.

First, build your delegated authentication Web service:
  1. In Salesforce.com, click Setup | Develop | API | Download Delegated Authentication WSDL to download the Web Services Description Language (WSDL) file, AuthenticationService.wsdl.

    The WSDL describes the delegated authentication service and can be used to automatically generate a server-side stub to which you can add your specific implementation. For example, in the WSDL2Java tool from Apache Axis, you can use the *--server-side* switch. In the wsdl.exe tool from .NET, you can use the */server* switch.

    A simple C# implementation of delegated authentication is shown below. The sample uses Microsoft .NET v1.1 and works with IIS6 on a Windows 2003 server. See [url http://wiki.developerforce.com/index.php/How_to_Implement_Single_Sign-On_with_Force.com]wiki.developerforce.com/index.php/How_to_Implement_Single_Sign-On_with_Force.com[/url] for a more complex sample that demonstrates a solution using an authentication token. [code visualforce]using System; using System.DirectoryServices; namespace samples.sforce.com { /// <summary>  /// This is a very basic implemention of an  /// authentication service for illustration purposes.  /// This sample should only be used  /// with a HTTPS Delegated Gateway URL.  /// It simply connects to your Active Directory  /// server using the credentials that are passed in.  /// If there is a bad username/password combination,  /// it throws an exception and returns false;  /// otherwise the credentials are ok  /// and it returns true.  /// Note that DirectoryEntry might not connect to  /// Active Directory until we do something  /// that actually requires it.  /// That's why we read a property from the  /// created DirectoryEntry object.  /// </summary>  public class SimpleAdAuth : System.Web.Services.WebService { [System.Web.Services.WebMethodAttribute()] [System.Web.Services.Protocols.SoapDocumentMethodAttribute( "", RequestNamespace = "urn:authentication.soap.sforce.com", ResponseElementName = "AuthenticateResult", ResponseNamespace = "urn:authentication.soap.sforce.com", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] [return: System.Xml.Serialization.XmlElementAttribute("Authenticated")] public bool Authenticate ( string username, string password, string sourceIp, [System.Xml.Serialization.XmlAnyElementAttribute()] System.Xml.XmlElement[] Any) { if(username.IndexOf("@")==-1) return false; // Attempt to bind to an Active Directory entry.  // This will authenticate the username and password.  // TODO: you'll need to change this to match  // your Active Directory name  const string root = "LDAP://DC=sample,DC=org"; try { DirectoryEntry de = new DirectoryEntry(root, username, password); // retrieve a property  string tempName = de.Name; return true; } catch(Exception) { return false; } } } } [/code]As part of the delegated authentication process, a salesforce.com server makes a SOAP 1.1 request to authenticate the user who is passing in the credentials. An example of this type of request is shown below. [code visualforce] <?xml version="1.0" encoding="UTF-8" ?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <Authenticate xmlns="urn:authentication.soap.sforce.com"> <username>sampleuser@sample.org</username> <password>myPassword99</password> <sourceIp>1.2.3.4</sourceIp> </Authenticate> </soapenv:Body> </soapenv:Envelope> [/code] Your delegated authentication service needs to accept this request, process it, and return a *true* or *false* response. A sample response is shown below. [code visualforce] <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <AuthenticateResponse xmlns="urn:authentication.soap.sforce.com"> <Authenticated>true</Authenticated> </AuthenticateResponse> </soapenv:Body> </soapenv:Envelope>[/code]
  2. Add a link to your corporate intranet or other internally-accessible site that takes the authenticated user’s credentials and passes them using an HTTPS POST to the Salesforce.com login page. For security reasons, you should make your service available by SSL only. This ensures that a password, if it is included, is not sent unencrypted. You must use an SSL certificate from a trusted provider, such as Verisign or Thawte.

    Because Salesforce.com does not use the password field other than to pass it back to you, you do not need to send a password in this field. Instead, you could pass another authentication token, such as a Kerberos Ticket, so that your actual corporate passwords are not passed to or from Salesforce.com.

    You can configure the Salesforce.com-delegated authentication authority to allow only tokens, or to accept either tokens or passwords. If the authority only accepts tokens, a Salesforce.com user cannot log in to Salesforce.com directly, because they cannot create a valid token; however, many companies choose to allow both tokens and passwords. In this environment, a user can still log in to Salesforce.com through the login page.

    When the salesforce.com server passes these credentials back to you in the *Authenticate* message, verify them, and the user will gain access to the application.

Next, in Salesforce.com, specify your organization’s delegated authentication gateway URL by clicking Setup | Security Controls | Single Sign-On Settings | Edit. Enter the URL in the Delegated Gateway URL text box. For security reasons, Salesforce.com restricts the outbound ports you may specify to one of the following:[note]For security reasons, you should make your service available by SSL only.[/note]

Finally, modify your user profiles to enable the *Is Single Sign-On Enabled* user permission. In Salesforce.com, click Setup | Manage Users | Profiles to add or edit profiles.

Discussion

The actual implementation of delegated authentication is transparent to users, but involves a number of steps behind the scenes. When you configure Salesforce.com for delegated authentication, you are allowing a delegated authority to control authentication. When a user first logs onto their network environment, they are initially authenticated by this authority. When the user attempts to log on to subsequent protected applications, instead of passing a username and password to the application, the user requests a token from a token generator. (On Windows, this token request can use the NTLM protocol.) The received token is passed to the application, which verifies that the token properly identifies the user, and then allows the user access to the application.

Salesforce.com can use this method, since the password field is simply used to exchange information with the client, rather than specifying a particular data type. This flexibility means that Salesforce.com can accept a token, which is then used with the delegated authentication authority to verify the user. If the verification succeeds, the user is logged on to Salesforce.com. If the verification fails, the user receives an error. The process flow for Salesforce.com delegated authentication is shown in the figure below.

Delegated Authentication Process Flow [img sso_del_auth_process_flow]