Salesforce Environment Hub

Environment Hub was announced back in August 2012 and was initially made available as a Pilot feature of the Winter ’13 release. This post follows up (some 2 years later) on my initial interest in understanding the utility Environment Hub delivers in the context of environment/user management.

Environment Hub – What is it?
In simple terms Environment Hub is an org administration tool that enables multiple orgs (of any type) to be associated and accessed from a central location. Each connected org is a termed a Hub Member, with an imposed constraint that each Hub Member org can only be parented by one Hub org. It is therefore imperative that Hub Members are only added where there is no contention over the appropriateness of the parent Hub. Commonality of target production org or packaging org is a good starting point for this consideration, as is the rule that client orgs should never be parented by an ISV or Consultancy Hub org. The parent Hub org should always be the most-accessed org, the credentials for which will become those by which all org access is made.

For larger programmes of work Environment Hub provides a highly useful means to catalogue the org estate and to provide SSO between the constituent orgs. This latter point enables reduced password maintenance, simplified access and centralised user administration in terms of deactivating a user account in one place only and ability to view login history in once place.

Environment Hub Tab

Environment Hub is enabled by Salesforce support who will require confirmation to proceed with the change. From experience, the enablement process can take a few days.

Key Features

Connect Organisation
Connecting Hub Members to the Environment Hub occurs via the entry of an administrator username for the target org and subsequent OAuth authentication and authorisation flow. The User Permission “Connect Organisation to Environment Hub” is required.

Connect Organisation 1

Connect Organisation 2

Connect Organisation 3 - OAuth

Connected Organisation Detail Page

Once an org is connected to the Environment Hub interesting detail such as the Edition, Org Status and Org Expiry date is revealed. It is also possible to add custom name and description attributes to the Hub Member, which I really like, each org in the estate should be justifiable and have a specific purpose – here we can capture this plus accountable contact etc. A very useful means of cataloguing and tracking the org estate.

The Company Detail page in the connected org will now show the Environment Hub Org Id value as below.

Company Information Page

In addition to the “User Added” origin, Hub Members are also auto-discovered using existing org-to-org relationships as below.

Auto-discovery types; sandbox to production, patch orgs to release org, trialforce source org to trialforce management org, release org to LMO

Create Organisation
New development/test/demo orgs can be created directly within the Environment Hub – this replaces the functionality previously exposed via the Salesforce Partner Portal, for partners at least. I’m unclear how the types of org offered are affected by partnership status etc. or perhaps whether the Environment Hub itself is available only to partners.

Create Organisation

Create Organisation 2

Org types offered;
Development = PDE org.
Test/Demo = Pick Edition for a 30 day time expired org.

Useful information of the distinction between different org types can be found here.

Single Sign-on
SSO can be enabled between each Hub Member and the Hub org; in implementation terms this means the Hub org is configured as an Identity Provider with a Service Provider being configured (automatically via the SSO enablement process) in both the Hub Member org and the Hub org. Both IdP initiated (via the Environment Hub tab) and SPI-initiated (via enablement of the Service Provider as a Login Page Authentication Service) SAML flows are supported. The latter point meaning SSO could be enforced as the only authentication means – thereby switching off standard Salesforce authentication entirely. Each Hub Member Org must have a My Domain configured for SSO to function.

Note, enabling SSO creates a Service Provider in the Hub org, default permissions are provided to the Standard User and System Administrator profiles only. It is therefore a requirement to ensure relevant permissions (Profile or Permission Set) are provided.

Connected Organisation Detail Page SSO

Within the Identity Provider, the Hub Member specific Service Provider configuration is set with “Subject Type=User’s ID determined by Environment Hub”, this setting delegates the user mapping to the Environment Hub settings, defined as below.

3 types of SSO User Mapping;
Method 1. Mapped Users – 1 to 1 mapping of user names – per-user.
Method 2. Federation Id – boolean state, yes = attempt to map users on common Federation Identifier values.
Method 3. User Name Formula – formula expression = attempt to map users via formula result.

Where multiple mapping types are enabled the precedence order above applies. For SSO between a sandbox and production org, user mapping is implicit and not configured as above.

Customisation
Enabling Environment Hub adds the EnvironmentHubMember standard object which is open to the declarative build model; custom fields, page layouts. validation rules, workflow rules, approvals etc.. In addition Apex Triggers can be defined on this object, use cases for which may include notifications relating to status changes etc.

A second standard object EnvironmentHubInvitation is also added, however this object is inaccessible from the Setup menu (although it can be reached via /p/setup/layout/LayoutFieldList?type=EnvironmentHubInvitation&setupid=EnvironmentHubInvitationFields). I’m assuming this object to be either forward looking or a legacy of an invitation-based connection model (as per Salesforce to Salesforce). Regardless, records do seem to be added to this object, the logic for which is unclear.

Related Permissions
Hub Org –
Manage Environment Hub
Environment Hub App and Tab access
EnvironmentHubMember standard object access permissions
Environment Hub Connected App
SSO Service Providers e.g. [00_____0000Cj__] Service Provider Access for SSO (by Profile or Permission Set)

Hub Member Org –
Connect Organisation to Environment Hub

Environment Hub in Practice
For consulting projects Environment Hub offers significant value in terms of management and tracking of the org-estate and centralisation of user administration. In practice this would require all project contributors to access production (Hub) as the primary org and SSO into secondary (Hub Member) orgs as required. In this model, production could be utilised for project collaboration, bug-tracking, project management etc. which is a common approach. The obvious downside being the requirement to license the project team in production – a big challenge on many projects where user licenses aren’t provisioned until a late stage or business use runs parallel to project activity. In such examples, project contributors could be provisioned with low-end user licenses on a temporary basis. Ideally we could do this with a Chatter Plus license as users would only require Chatter, Custom Objects (10 or less) and Environment Hub access.

For ISV projects, the utility of Environment Hub relates more specifically to the ability to catalogue the multitude of environments required for development, test, i11n, packing, release and patch purposes, not to mention TrialForce. Efficiency of access across this estate is also a key factor.

References
Environment Hub Online Help

Salesforce OpenID Connect

In addition to the proprietary Authentication Provider types (Facebook, Janrain, Salesforce) Winter ’14 (v29.0) added support for the OpenID Connect protocol, enabling off-platform authentication via any compatible OpenID Provider (Google, PayPal, Amazon and others). This post provides a basic implementation overview.

OpenID Connect what is it?
OpenID Connect is a lightweight authentication (identity verification) protocol built on top of modern web standards (OAuth 2.0, REST and JSON). OpenID Connect supersedes OpenID 2.0 and amongst other goals is intended to promote interoperability, be accessible to developers and to provide greater support for mobile use cases.

The OpenID Connect standard was recently ratified by members of the OpenID foundation and announced publicly at the Mobile World Congress in Barcelona on 26th February 2014. The standard is supported by Google, Microsoft, Salesforce, AOL, Ping and others.

The protocol works on the principal of an “Authorization Server” or OpenID Provider (OP) (e.g. Google), authenticating users on behalf of a “Client” or Relying Party (RP) (e.g. Salesforce). With the current implementation Salesforce can be configured as a RP but not an OP. In this context an Authentication Provider is configured in Salesforce with the type set to OpenID Connect. Note OP is also referred to as IDP, confusingly we have 3 seemingly interchangeable terms – however the OP term is the one defined in the standard.

Please refer to the excellent OpenID website for more details in regard to specifications, implementations, useful FAQs etc..

Identity Use Cases
In simple terms, users can single sign-on (SSO) into Salesforce using external web application credentials. A Salesforce user record can be created just-in-time on the first authentication event, subsequent events for the user map to this user record. Note, usefully it’s also possible to map existing users via the [Existing User Linking URL].

A key use case here is B2C portals and communities, however internal users and partners can also use this authentication approach. For internal users SSO via a Google Account could make sense where an enterprise has adopted Google Apps for Business.

What’s important to understand is that Salesforce supports external Authentication Providers for all user types (with the exception of Chatter External) with SAML, OAuth and OpenID Connect protocol support. This provides a high degree of flexibility in the terms of how identity management is implemented.

Implementation Steps
The Salesforce help providers a detailed series of steps to follow. The following high-level example shows a basic implementation of a Google Accounts Authentication Provider.

1. Register an OpenID Connect Application.
As per Salesforce Connected Apps, within your Google account an application is required, within which OAuth is configured. Applications are created via the Google developers console. The Redirect URI won’t be known until the Authentication Provider is configured in Salesforce.

7. Google Developers Console

2. Create an Authentication Provider.
Consumer Key = Client ID
Consumer Secret = Client secret
Scope = profile email openid

8. Salesforce Auth Provider Detail Page

3. Update OpenID Connect Application.
Copy the Salesforce [Callback URL] to the Google [Redirect URI] field and save.

4. Add Authentication Provider to Login Page (Standard App or Community).
This step requires a My Domain where the internal app login page is customised.

9. Salesforce Login Page Customisation

5. Configure a Registration Handler class.
Within the Authentication Provider configuration a Registration Handler class can be specified, this class implements the Auth.RegistrationHandler interface and is invoked to create new users or map to existing users in response to authentication events.


global class GoogleAccountsRegistrationHandler implements Auth.RegistrationHandler{
  global Boolean canCreateUser(Auth.UserData data) {
      //Check whether we want to allow creation of a user?
      return true;
  }

  global User createUser(Id portalId, Auth.UserData data){
      if(!canCreateUser(data)) {
          //Returning null or throwing an exception fails the SSO flow
          return null;
      }
      if(data.attributeMap.containsKey('sfdc_networkid')) {
          //We have a community id, so create a user with community access.
          //.. create community user.
      } else {
          //.. create standard user.
          return u;
      }
  }

  global void updateUser(Id userId, Id portalId, Auth.UserData data){
      User u = new User(id=userId);
      //.. update fields if required.
      update(u);
  }
}

Testing
1. Initialisation
The [Test-Only Initialization URL] provided on the Authentication Provider detail page can be pasted into a browser address bar and used to examine the raw output provided back from the Authorization Server.

1. Test Initialisation Output

2. Authentication
The following screenshots show the basic authentication flow. Note, as with SAML based SSO, errors are appended to the URL querystring.

Customised login page showing the Google Account Authentication Provider.

2. Login Page With Auth Providers

Clicking the button redirects the browser to the Google Service Login page to authenticate (unless a Google Accounts session exists).

3. Google Service Login Page

For new users the user consent page is displayed. This page can be customised via the Google Developer console.

10. User Consent page

Authentication errors are appended to the URL, as-per SAML authentication errors.

4. Error Page 1

5. Error Page 2

Finally, a Salesforce session is established. New users can be provisioned automatically, script within the Registration Handler class controls the configuration of such User records.

6. Auto-provisioned User Detail Page

Implementation Notes
1. Google Developer Console. Remember to turn ON – Google+ API access. This is required.

2. The auto-created Registration Handler class template must be modified as the default code will fail in many cases.
canCreateUser is false by default – in most cases this must be changed to true.

The Combination of values below don’t work if the user isn’t configured with US locale.
u.languagelocalekey = UserInfo.getLocale();
u.localesidkey = UserInfo.getLocale();
u.emailEncodingKey = ‘UTF-8’;
u.timeZoneSidKey = ‘America/Los_Angeles’;

3. Activation code entry appears to fail within an Internal Server error, but the code has been successful so subsequent attempts will succeed. This may be specific to my context.

4. As a best practice map the user Id from the OpenID Provider (Google Account Id in the example) into a custom field on the User record. This provides a robust mapping between the 2 system identifiers that can be used by the Registration Handler script.

5. Access can be revoked via the Third Party Account Link related list on the User detail page.

6. Make the OpenID Connect Application name meaningful to the end-users, the Google user consent page will display this in a “[AppName] is requesting access” format, anything weird or meaningless may cause concern.

Protocol Flow
Please treat the diagram below as indicative only, I put this together from a combination of browser profiling and assumptions made on the basis of reading the OpenID Connect specification.

As always, corrections would be appreciated.

OpenID Connect - SF Process Flow

Final Thoughts
OpenID Connect support is a highly useful extension to the Authentication Provider platform capability. For B2C portals and communities it makes sense to offer as many sign-in-via options as possible (Facebook, Google etc.) removing as much friction to user adoption as possible. As a personal opinion, over time I’m becoming less tolerant to having to register a new user account on each and every authenticated web site I interact with, particularly where I view the interaction as transient. Some users may have concerns around data security, i.e. by signing-in with a Google account are they implicitly giving Google access to the data held in the portal? In the majority case however, users will appreciate the improved user experience. For internal users OpenID Connect makes single sign-on via one or more of a multitude of current and future web platforms incredibly straightforward to implement. In the Salesforce context the key challenge will ultimately relate to reconciliation and rationalisation of identities (i.e. User records).

References
http://openid.net/connect/
http://openid.net/developers/specs/
https://developers.google.com/accounts/docs/OAuth2Login
https://console.developers.google.com/project

Salesforce Identity Connect

Over the recent years I’ve spent focused on the Salesforce architecture domain I’ve designed and implemented federated single sign-on (SSO) schemes many times (and the proprietary Delegated Authentication on rare occasions). Whilst each implementation has its nuances in terms of specific access use cases (mobile, composite app, public internet versus corporate network only etc.) and infrastructure deployment topology, there is typically a high degree of commonality. For instance, most corporate environments utilise Active Directory as the primary enterprise identity store, this is inarguable. Equally common in such environments, at least in my experience, is the absence of Active Directory Federation Services (ADFS), or any federated identity service (Ping Identity, Okta etc.). As such the introduction of SSO for Salesforce typically means introducing the infrastructure to support federated SSO as a generic service. Notable exceptions to this are corporates that have transitioned to the Office365 cloud productivity suite, where federated SSO is highly desirable for the same good reasons as those for Salesforce SSO, namely security, support and end-user experience.

Following the idea that Active Directory is pervasive in today’s corporate infrastructure environments and that Salesforce SSO implementations typically conform to a set of patterns and related technology solutions, implementing SSO becomes a question of mapping a specific set of identity management requirements appropriately.

Example patterns (illustrative and not exhaustive)

SAML Service Provider initiated flow with optional automated user provisioning.
Solution Option – ADFS (possible with AD groups and conditional custom claims rules) with SAML based JIT user provisioning.
Rationale – Simple, cost-effective solution using standardised technology. If the IT department supports AD, ADFS shouldn’t cause any alarm.

SAML Service Provider initiated flow with bi-directional identity synchronisation.
Solution Options – ADFS with middleware-based data synchronisation between Salesforce User records and AD User Principals. Or, 3rd party identity management service offering user synchronisation capability. For a simple one app, point solution Okta Cloud Connect is a free service to be evaluated alongside equivalent competitor offerings.
Rationale – ADFS has no native identity synchronisation capability. Users can be provisioned into Salesforce, and updates applied to certain fields, via SAML JIT provisioning at the time of access, however there are no background updates and perhaps most crucially there is not automated de-activation of users.

SAML Identity Provider initiated flow with bi-directional identity synchronisation.
Solution Option – 3rd party identity management service.
Rationale – ADFS offers no native user-facing IdP capability, 3rd party services offer great flexibility in this area. Salesforce itself can be used as an IdP – a subject beyond the scope of this post.

As the example patterns show, there are a number of factors to consider and a multitude of enabling technologies, each with different levels of capability (at a reflective price point). Given the complexity of a federated SSO solution, and accepting that an enterprise-wide solution should be considered over a point solution, it is key to understand the solution options available and to consider some degree of future proofing.

A relatively recent arrival in the market is Salesforce Identity Connect (October 2013), an add-on component to Salesforce Identity, providing connection to on-premise identity directories, namely Active Directory. The rest of this post outlines the result of a high-level investigation into the capabilities of Salesforce Identity connect.

Salesforce Identity Connect
Salesforce Identity Connect, hereafter referred to as SIC, is built on the ForgeRock Bridge Service Provider Edition (SPE) technology and falls into the category of 3rd identity service.

What is it?
Informal notes in no order.

On-premise identity service with a browser-based admin UI.
Supports Windows, OSX and Linux hosts.
Can be installed on Windows as a service.
Install, configure, run service. Quick to get up and running.
No ADFS proxy equivalent.
An org must be activated for Salesforce identity, this adds a download link to the setup menu and feature licenses.
One SIC instance can support multiple orgs (with different configurations). Sandboxes are supported.
Setup steps; create connections (SF and AD, define mappings, set schedule, configure SSO)
No local storage of users and passwords, user associations are held in a local MySQL db.
Connects to a SF org via OAuth 2.0
Multiple direct AD Domain Controller connections are not supported, instead a connection should be made to the Global Catalogue where multiple domains must be spanned. Note this approach requires manual modification of the AD schema.
User licenses are managed via Permission Set Licensing, not feature licensing.
Org must have Multiple SAML Configurations enabled.

What does it do?

User Authentication – Federated user authentication is supported via SAML 2.0 Service Provider Initiated and Identity Provider Initiated flows. SPI is the common case, where users access the SF My Domain and are redirected to the IdP (SIC, Identity Connect) for either seamless integrated authentication (IWA) or prompted AD login. For IWA to work there are a number of complex Kerberos authentication related setup steps to be applied to the SIC host, this can be a challenge as technical expertise in this subject area is limited. There are also end-user browser configuration changes to be applied, for IE users a GPO would cover this, for Firefox a manual configuration would be necessary. Not ideal.

User Synchronisation – Automated background synchronisation, not JIT. Mapping can be attribute-based (AD User attribute to Salesforce User field), AD Group membership to User Profile or AD Group membership to Permission Set. In the attribute case, direct mappings, transformations via JavaScript or default static values can be applied. Where transformations are applied ternary expressions are a useful convention where only populated field values are transformed to provide the target value. In the Group to Profile case, a list of AD groups are mapped to specific profiles, such mappings are defined with a precedence order such that the result is always a single profile, regardless of how many groups a user is a member of. A default profile must be defined as a catch-all. Tracking of users provisioned into Salesforce occurs via Permission Set Licenses for the Identity Connect Permission Set. User associations established by the SIC Reconciliation Report can be manually edited via the web interface. The applied association rules can also be modified where necessary. Synchronisation can be configured to run in Live Update or Scheduled Update mode. The former being more timely, but more prone to inconsistency the latter being more comprehensive approach with the typical periodic scheduling frequencies. It would be nice to have the option to combine live updates with a scheduled daily synchronisation – this doesn’t appear to be possible.

Licensing?
Salesforce Identity Connect is licensed as an add-on to Salesforce Identity at £1 per-user, per-month regardless of Edition. Current pricing can be found via this link.

Conclusions
Salesforce Identity Connect provides a capable user authentication and synchronisation service. Good points being the ease of configuration of the Salesforce side of things plus the multiple org support, the attribute and group mapping functionality is also very nice. The two downsides being the cost, although it’s an expensive area of technology, and the complexity of configuring Integrated Windows Authentication (IWA). The SSO aspect to the service is only meaningful if the SSO is seamless. Coming back to the cost, ADFS is free-of-charge but provides no user synchronisation (other than via SAML JIT). I believe many people will take this route regardless, simply to avoid any cost whatsoever, although £1 per user/month does represent a significant outlay for larger installs and could be hard to justify for performance edition customers particularly. In addition to the run cost there is also the technical complexity of establishing IWA to consider; many IT departments will look nervously at the long list of Kerberos configuration tasks and may resist the approach in terms of the effort, expertise and deployment cost involved.

To be compelling services such as SIC need to be simple and reasonably non-technical to install and run. SIC achieves this nicely for the run aspect, for the install aspect there’s some room for improvement. For many organisations the installation experience will not be an issue, the focus will be on the end-user experience and the administrative functionality, in these areas Salesforce Identity Connect looks a solid offering.

Links
Really good, short walk through video on YouTube

Implementation Guide PDF

Multi-Provider Single Sign-On

The Summer ’13 release brought an interesting new feature in the area of identity management – Multi-Provider Single Sign-On. The general principle being (to my initial reading of the release notes) that a single Salesforce org can perform federated authentication to multiple identity providers. Useful indeed where SSO is desirable but the Salesforce implementation spans multiple IT environments within a single enterprise. For example a subset of the user base may have their identities managed by Active Directory whilst the remainder are Google Apps users and have no AD user principal. Prior to Summer ’13 an org could only be configured as a service provider in relation to a single identity provider (IdP), therefore in the example the Salesforce SSO settings could be configured to point to an ADFS endpoint, enabling authentication by AD but what about the Google Apps users?

So, Summer ’13 seemingly addressed this limitation enabling multiple service provider-to-identity provider relationships to be configured. All this made great sense and appeared to improve the flexibility of a native Salesforce solution. In reality this issue has historically been resolved externally to Salesforce using tools such as Ping, Okta, Janrain etc. which additionally provide extension functionality such as multi-factor authentication, finer grained access control, device access policies, user data replication etc..

The main question I’ve had with Multi-Provider Single Sign-on, since the release notes were published earlier this year, is how the authentication interaction would inform the Salesforce org which IdP to use. Would this be a querystring parameter on the My Domain, additional sub-domain or an additional My Domain perhaps? Note, the SSO process is initially anonymous, accessing a My Domain (e.g. force365blog.my.salesforce.com) allows Salesforce to check for an active SSO configuration and initiate the SSO sequence with the configured IdP. Unfortunately, it would appear that the answer to this question is straightforward, the Multi-Provider SSO functionality is limited to the new Communities functionality. In this context each active SSO configuration can be optionally enabled within a Community, the result of this being an additional button appearing on the Community login page as below.

Communities Login

It therefore becomes possible for Communities users to authenticate against multiple identity providers, internal app users remain limited to a single provider, selected from the active SSO configurations using the Authentication Service field on the My Domain page. Hopefully a future release will extend this functionality to internal app users. In the meantime the SSO documentation needs to clearly define the context of this functionality, i.e. Communities only. If I’ve missed something here, I’d appreciate a correction..

Winter ’14 Update (thanks to Leon de Beer)
With Winter ’14 it is now possible to enable multiple Authentication Services for a My Domain via Login Page branding. In doing so Service Provider Initiated SSO (SPI) no longer functions in a seamless manner, instead an Authentication Service selection page is displayed. If the “Login Page” Authentication Serivice is enabled then the login page is shown with buttons for each additional enabled service, if not then just the buttons are displayed on an otherwise empty page. So Winter ’14 opens up Multi-Provider SSO to internal users, however I don’t currently see a way to drive the automated selection of a specific Authentication Service such that SPI SSO can work in the case where multiple services are enabled.

Salesforce SSO with ADFS 2.0

In this post I’ll share some recent practical experiences implementing Federated SSO between Salesforce and Active Directory Federation Services 2.0 (ADFS 2.0 for brevity). For detailed configuration and theoretical information on this subject please refer to the excellent resources below.

http://blog.rhysgoodwin.com/cloud/salesforce-sso-with-adfs-2-0-everything-you-need-to-know/
http://wiki.developerforce.com/page/Single_Sign-On_with_Force.com_and_Microsoft_Active_Directory_Federation_Services

To set the scene – the “deployment view” schematic below shows the building blocks of a complex implementation covering most if not all possible access scenarios including portals, public web access, mobile user agents etc.

SSO ADFS

Deployment Considerations

– Salesforce
Two points to make here, firstly to emphasise the fact that all communication is routed through the browser running on the local machine (SAML 2.0 Browser Post Profile), there is no direct communication between Salesforce and ADFS proxy etc.. The second point being the importance of the introduction of a My Domain to the org, this is required for service provider initiated SSO and is necessary for mobile apps, Chatter desktop, Salesforce for Outlook and deep-links to function correctly with SSO.

– ADFS 2.0 Deployment Topology
Ideally, the ADFS configuration database should be deployed on a fault-tolerant, load-balanced SQL Server cluster – avoid the Windows internal database if you’re looking at a high-availability design. This is particularly advisable if your organisation has this SQL Server infrastructure in place. The ADFS 2.0 server role can also be deployed in a Federation Server Farm configuration, with active servers load balanced on a single virtual IP and connected to the shared configuration database. There is huge flexibility here in terms of redundancy and load-balancing configurations. The ADFS servers and configuration database host should be deployed within the corporate network, not the DMZ.

In a multi-org deployment, to workaround the unique service provider certificate limitation preventing more than one Salesforce org as a service provider in ADFS follow the instructions here.

http://help.salesforce.com/apex/HTViewSolution?id=000163471&language=en_US

– ADFS Proxy
There are other options in terms of routing inbound traffic through the DMZ, however ADFS proxy is a popular, free and secure option. A farm configuration should be deployed, with multiple (at least 2) load balanced servers behind a virrtual IP.

– Public DNS
In SAML terms a Salesforce org can be Service Provider to one (and only one) Identity Provider. In defining the single set of settings, the Identity Provider login URL must be entered. This url has to be accessible from the local machine of all prospective users, those who are connected to the corporate network and potentially those who aren’t. In order to support external users the Identity Provider host name must be resolvable by the public DNS to a secure server presenting a certificate signed by a root CA. An internal CA signed certificate is acceptable if there are no external access scenarios to consider and all SSO attempts will be made by users connected to the corporate network via cable or VPN.

– Internal DNS
Internal users must resolve the ADFS url (Identity Provider login URL) directly to the internal ADFS server host, whilst external users will resolve via public DNS registry. The internal override is key, this is necessary to ensure that Windows Integrated Authentication takes place, plus avoids an expensive routing via the public internet. Ideally this can be achieved simply via the internal DNS. In cases where internal users connect externally from the same machine (outside of a VPN connection), a localhost file entry would be problematic.

– ADFS Claim Rules (Transform)
Defined rules can (and should) be exported to a file, as a backup and convenience when recreating Relying Party Trusts within ADFS). The link below provides the Powershell instructions for this.

http://social.technet.microsoft.com/wiki/contents/articles/4869.aspx

Example rules below. Where possible use the claim rule templates (attribute population from AD, comditional static attribute population based on security group membership etc. the claim rule language is seemingly undocumented.

@RuleTemplate = "LdapClaims"
@RuleName = "Send UPN as Name ID"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"), query = ";userPrincipalName;{0}", param = c.Value);

@RuleTemplate = "LdapClaims"
@RuleName = "Send Email Addresses as User.Email"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory", types = ("User.Email"), query = ";mail;{0}", param = c.Value);

@RuleTemplate = "LdapClaims"
@RuleName = "Send Surname as User.LastName"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory", types = ("User.LastName"), query = ";sn;{0}", param = c.Value);

@RuleTemplate = "LdapClaims"
@RuleName = "Send UPN as User.Username"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory", types = ("User.username"), query = ";userPrincipalName;{0}", param = c.Value);

@RuleTemplate = "EmitGroupClaims"
@RuleName = "Send User.ProfileId for Salesforce Standard Users"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value == "S-1-5-21-1591777566-3669593721-1616705233-599", Issuer == "AD AUTHORITY"]
 => issue(Type = "User.ProfileId", Value = "00fE0000000ryDa", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, ValueType = c.ValueType);

@RuleTemplate = "EmitGroupClaims"
@RuleName = "Send User.ProfileId for Salesforce Chatter Users"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value == "S-1-5-21-1591777566-3669593721-1616705233-1999", Issuer == "AD AUTHORITY"]
 => issue(Type = "User.ProfileId", Value = "00fE0000000EeCs", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, ValueType = c.ValueType);

@RuleTemplate = "EmitGroupClaims"
@RuleName = "Send 809 as User.Department"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value == "S-1-5-21-1591777566-3669593721-1616705299-9115", Issuer == "AD AUTHORITY"]
 => issue(Type = "User.Department", Value = "809", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, ValueType = c.ValueType);

@RuleTemplate = "LdapClaims"
@RuleName = "Send co as User.Country"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory", types = ("User.Country"), query = ";co;{0}", param = c.Value);

– ADFS Claim Rules (Authorisation)
Particularly in just-in-time (JIT) user provisioning scenarios having control over who can access Salesforce via ADFS SSO can be important. In such cases one approach can be to create an AD securtity group [Salesforce Users] and add all valid AD principles. An authorisation claim rule can be added (after removing the permit all default) to restrict access to the just the group members. Note with service provider initiated SSO, i.e. the user hits the my domain first, for non-privileged users the end result will be the display of the SAML login error page, this may not be the ideal experience. For identity provider initiated SSO, i.e. the user hits ADFS first, then an ADFS error page is displayed.

– JIT provisioning
Salesforce mandates that users provisioned via a SAML assertion must have an initial user profile Id specified in an attribute within the assertion. One approach to this requirement is to use Active Directory security groups to group subsets of the user population where the initial user profile assignment is common, i.e. [Salesforce Standard Users], [Salesforce Chatter Users] etc. A best practice with this approach is to keep the assigned profile as restricted as is feasible until an Administrator can refine the assignment with more intelligence. It would be feasible to use a custom attribute store, complex custom claim rules etc. to achieve a smarter initial profile assignment however I’ve yet to experiment too much with either.

As neither Active Directory or ADFS has any knowledge whether the user has been provisioned or not in Salesforce, it must send user-provisioning related attributes in all cases. There is an issue with this in respect to user profile. For example, user is a member of the [Salesforce Standard Users] group and is initially created with a standard user profile, subsequently another user updates the profile to system administrator – so far so good – however the next time the user accessess Salesforce via SSO, the user profile id in the SAML assertion is used to update the user back to the standard user profile – far from ideal. One approach to avoiding this is to add an Apex Trigger to the User object whch suppresses the attempted profile update, example below.

    private void processSSOUpdate(User[] updatedRecords, Map<Id, User> oldMap){
    	/*    	    	
    	ADFS has no knowledge of whether a user exists in Salesforce or not and as such must send the user profile id in all cases. 
    	The user profile must only be used in the insert case, this trigger prevents reset of user profile changes made in Salesforce.
    	
    	Note.The SSO process invokes an update on the User record on every login. 
    	*/
    	if (UserInfo.getName()=='Automated Process' || (Test.isRunningTest() && UserTestHelper.isSSOTest)){    	
			for (User u : updatedRecords){
				if(u.ProfileId!=oldMap.get(u.Id).ProfileId){
	            	u.ProfileId=oldMap.get(u.Id).ProfileId; //& override any attempt to reset the user profile.
				}
			}
    	}
	}

Apex Trigger script can also be used to add default Chatter group membership, translate locale settings etc.

– JIT de-provisioning
In cases where SSO is enforced via login policy, deactivating the AD account prevents access to Salesforce. However in a mixed-mode scheme where users can also login using Salesforce authentication, the leavers process must involve manual deactivation of the Salesforce user. Alternatively, an integration tool could be used to query the Active Directory via an LDAP connector and apply User record deactivations to Salesforce. It may be the case that the automated logic must be two-phased, first attempt deactivation if this fails (active assignment rules associated with the user etc..) then update the user to a No Access user profile, with login hours set in a way to lock-out access.

– Browser Compatibility (seamless SSO authentication)
Browser compatibility with Windows Integration Authentication is mixed:

Firefox – not ok (requires this configuration change: http://markmonica.com/2007/11/20/firefox-and-integrated-windows-authentication/)
Chrome – ok
IE – requires the ADFS host to be added to the Trusted Site Zone. This can be achieved via System Management Tools and pushed out across the enterprise.

– Portals
Although the Single Sign-on Implementation Guide states otherwise, I have noticed that service-provider initiated SSO does work for portals users, i.e. portal user hits the my domain, is redirected to ADFS to log in and then is returned to portal in an authenticated state via the site url. This may be an anomaly.

– Login Policy
It is possible to enforce SSO at the org level, seemingly preventing standard Salesforce authentication to take place. A very good thing where appropriate, in security terms. I have noticed that you can still log in with Salesforce credentials using links as below.

https://force365.my.salesforce.com/login.jsp?un=myuser%40force365.com&pw=mypassword

– Chatter Emails
If a My Domain is introduced to the Salesforce org to support service-provider initiated SSO, it should be noted that links embedded within automated email messages will incorporate the my domain. This could be a real problem where Customers are collaborating in Chatter Customer Groups – clicking on the links (in a pre-authenticated state) will take the customer (or partner) to the identity provider login page.

Update – Troubleshooting
1) CRL check issue. If your ADFS server can’t connect to the internet you may get errors (check the event log) relating to Certificate Revocation List checks failing. To address this open Powershell (as Administrator), then use the commands below.

Add-PSSnapin Microsoft.Adfs.PowerShell
Set-ADFSRelyingPartyTrust -TargetName "YourRelyingPartyDisplayName" -SigningCertificateRevocationCheck None

2) Error MSIS7004. Make sure the ADFS service account (Network Service by default) has permissions to the ADFS certificate (right-click certificate in the certificates MMC snapin, find Manage Private Keys option, check permissions).

Update 2 – Sandbox suffixes in Claim Rules
The second Claim Rule below shows how you can handle sandbox suffixes for usernames where you’re not using a dedicated test AD.

@RuleTemplate = “LdapClaims”
@RuleName = “Send Email addresses as Email”
c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname&#8221;, Issuer == “AD AUTHORITY”]
=> issue(store = “Active Directory”, types = (“User.Email”), query = “;mail;{0}”, param = c.Value);

@RuleName = “Send Email address with suffix as User.Username”
c:[Type == “User.Email”]
=> issue(Type = “User.Username”, Value = c.Value + “.test”);

Mixed Authentication Schemes

In certain cases it may be desirable to have some users authenticate in the standard Salesforce manner, whilst another user population authenticates via single sign-on (SSO). This mixed authentication scheme scenario may result from rollouts to new departments etc. What are the considerations?

The first concern is whether Delegated or Federated Authentication will be used for the SSO population.

With Delegated Authentication (DA), a mixed scheme is straightforward as the SSO configuration is applied through a User Profile setting, enabling a subset of users to have their authentication request routed to the DA on-premise authentication web service. The remaining users will simply login in the standard Salesforce manner.

With Federated Authentication (FA) via SAML 2.0, a mixed scheme is not so trivial. There is no User Profile setting or indeed any user-level setting controlling whether a user is SSO-enabled or not. Instead SSO is inferred from the manner by which the authentication is approached. If the user accesses https://login.salesforce.com and attempts to sign-in they will be authenticated as a Salesforce user, no SSO. With the identity provider initiated SAML flow, the user is handed-across from the IdP in a pseudo-authenticated state, if the service provider (i.e. Salesforce) can validate the SAML assertion and map the user to an active Salesforce user (via username or Federation Id) then authentication takes place. So the IdP initiated flow poses no problems in a mixed scheme, standard Salesforce users authenticate as normal, SSO users authenticate via the IdP (intranet link etc.).

So far so good. But what if the client also needs to support the service provider initiated SAML flow in a mixed scheme? Perhaps Chatter Desktop or Mobile is being rolled out.

The service provider initiated flow requires a My Domain to be configured in the Salesforce org e.g. https://force365.my.salesforce.com, this enables anonymous authentication attempts using the My Domain to be mapped to the correct SSO configuration and routed to the IdP. Which works perfectly for SAML enabled clients and deep-links. For the standard users in the org we now have a problem – all unauthenticated references to resources based on the My Domain will take the user to the IdP to authenticate. So sharing of links via email etc. will require the standard user to have pre-existing session, otherwise they will be presented with an unfamiliar login challenge (Active Directory Forms Authentication perhaps) or worse a login failure in the integrated case. In theory this could be resolved by ensuring the standard users are correctly configured for authentication both at the IdP and Salesforce, enabling SSO authentication to occur where required.

Salesforce Org Architecture

The figure above shows a complex multiple org architecture (Hub-and-Spoke model). I’ll return to the drivers for multiple-org versus single org in a future post. For now let’s consider some interesting aspects of the above scenario.

SSO : users log in via their Active Directory Credentials. The CORPORATE org being a SAML 2.0 Service Provider to the AD Identity Provider. The CORPORATE org is also aN Identity Provider, enabling SSO across all child-orgs (which are SP).

Managed Packages : versioned baseline functionality. It’s often the case that certain configuration elements are common across orgs in a multi-org architecture. A best practice is to distribute this metadata as a managed package thereby preventing local modification. The business owners of the client org are free to innovate in their org, but the baseline configuration is locked (possibly to ensure compatibility with data sharing processes). Managed packages arenot just for ISV.

Salesforce-to-Salesforce : data sharing (automated or manual). S2S is a very underrated technology, enabling bi-directional, selective sharing of data between orgs. A great fit for multi-org architectures where common data can be shared across all orgs, or partitioned (geographically, business type etc.) and perhaps consolidated at the CORPORATE level.

External Execution Environment : complex, off-platform processing (perhaps legacy components written in Java). Salesforce orgs are subject to execution limits (governor limits etc.), whilst this becomes less restrictive with each release, there are times when an external execution environment can be helpful. For example a payroll calculation engine (written in Java and used within the enterprise) could be deployed to Heroku and called via Apex. Personally, I look to repurpose or buy technology before coding anything – the ability to assemble a solution should not be overlooked.