To set up single sign-on, you must create a class that implements Auth.RegistrationHandler. Classes implementing the Auth.RegistrationHandler interface are specified as the Registration Handler in authorization provider definitions, and enable single sign-on into Salesforce portals and organizations from third-party services such as Facebook. Using information from the authentication providers, your class must perform the logic of creating and updating user data as appropriate, including any associated account and contact records.
The following are methods for RegistrationHandler.
public User createUser(ID portalId, Auth.UserData userData)
Type: User
public Void updateUser(ID userId, ID portalId, Auth.UserData userData)
Type: Void
The Auth.UserData class is used to store user information for Auth.RegistrationHandler. The third-party authorization provider can send back a large collection of data about the user, including their username, email address, locale, and so on. Frequently used data is converted into a common format with the Auth.UserData class and sent to the registration handler.
If the registration handler wants to use the rest of the data, the Auth.UserData class has an attributeMap variable. The attribute map is a map of strings (Map<String, String>) for the raw values of all the data from the third party. Because the map is <String, String>, values that the third party returns that are not strings (like an array of URLs or a map) are converted into an appropriate string representation. The map includes everything returned by the third-party authorization provider, including the items automatically converted into the common format.
To learn about Auth.UserData properties, see Auth.UserData Class.
For all authentication providers except Janrain, after a user is authenticated using a provider, the access token associated with that provider for this user can be obtained in Apex using the Auth.AuthToken Apex class. Auth.AuthToken provides two methods to retrieve access tokens. One is getAccessToken, which obtains a single access token. Use this method if the user ID is mapped to a single third-party user. If the user ID is mapped to multiple third-party users, use getAccessTokenMap, which returns a map of access tokens for each third-party user. For more information about authentication providers, see “About External Authentication Providers” in the Salesforce online help.
When using Janrain as an authentication provider, you need to use the Janrain accessCredentials dictionary values to retrieve the access token or its equivalent. Only some providers supported by Janrain provide an access token, while other providers use other fields. The Janrain accessCredentials fields are returned in the attributeMap variable of the Auth.UserData class. See the Janrain auth_info documentation for more information on accessCredentials.
To learn about the Auth.AuthToken methods, see Auth.AuthToken Class.
This example implements the Auth.RegistrationHandler interface that creates as well as updates a standard user based on data provided by the authorization provider. Error checking has been omitted to keep the example simple.
global class StandardUserRegistrationHandler implements Auth.RegistrationHandler{ global User createUser(Id portalId, Auth.UserData data){ User u = new User(); Profile p = [SELECT Id FROM profile WHERE name='Standard User']; u.username = data.username + '@salesforce.com'; u.email = data.email; u.lastName = data.lastName; u.firstName = data.firstName; String alias = data.username; if(alias.length() > 8) { alias = alias.substring(0, 8); } u.alias = alias; u.languagelocalekey = data.attributeMap.get('language'); u.localesidkey = data.locale; u.emailEncodingKey = 'UTF-8'; u.timeZoneSidKey = 'America/Los_Angeles'; u.profileId = p.Id; return u; } global void updateUser(Id userId, Id portalId, Auth.UserData data){ User u = new User(id=userId); u.username = data.username + '@salesforce.com'; u.email = data.email; u.lastName = data.lastName; u.firstName = data.firstName; String alias = data.username; if(alias.length() > 8) { alias = alias.substring(0, 8); } u.alias = alias; u.languagelocalekey = data.attributeMap.get('language'); u.localesidkey = data.locale; update(u); } }
The following example tests the above code.
@isTest private class StandardUserRegistrationHandlerTest { static testMethod void testCreateAndUpdateUser() { StandardUserRegistrationHandler handler = new StandardUserRegistrationHandler(); Auth.UserData sampleData = new Auth.UserData('testId', 'testFirst', 'testLast', 'testFirst testLast', 'testuser@example.org', null, 'testuserlong', 'en_US', 'facebook', null, new Map<String, String>{'language' => 'en_US'}); User u = handler.createUser(null, sampleData); System.assertEquals('testuserlong@salesforce.com', u.userName); System.assertEquals('testuser@example.org', u.email); System.assertEquals('testLast', u.lastName); System.assertEquals('testFirst', u.firstName); System.assertEquals('testuser', u.alias); insert(u); String uid = u.id; sampleData = new Auth.UserData('testNewId', 'testNewFirst', 'testNewLast', 'testNewFirst testNewLast', 'testnewuser@example.org', null, 'testnewuserlong', 'en_US', 'facebook', null, new Map<String, String>{}); handler.updateUser(uid, null, sampleData); User updatedUser = [SELECT userName, email, firstName, lastName, alias FROM user WHERE id=:uid]; System.assertEquals('testnewuserlong@salesforce.com', updatedUser.userName); System.assertEquals('testnewuser@example.org', updatedUser.email); System.assertEquals('testNewLast', updatedUser.lastName); System.assertEquals('testNewFirst', updatedUser.firstName); System.assertEquals('testnewu', updatedUser.alias); } }
To limit this example to the custom exception, some code was omitted.
global class RegHandler implements Auth.RegistrationHandler { class RegHandlerException extends Exception {} global User createUser(Id portalId, Auth.UserData data){ List<Profile> profiles = [SELECT Id, Name, UserType FROM Profile WHERE Name = 'Power User']; Profile profile = profiles.isEmpty() ? null : profiles[0]; if(profile==null) throw new RegHandlerException('Cannot find the profile. For help, contact your administrator.'); ... } global void updateUser(Id userId, Id portalId, Auth.UserData data){ User u = new User(id=userId); u.lastName = data.lastName; u.firstName = data.firstName; update(u); } }