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