Social Sign-on in Salesforce and Experience Sites

Social Login

The Social Login provides users an option that they can click to log in to a third-party account, such as Google or Facebook or LinkedIn or Twitter etc. Set these Social Logins for each authentication provider that you configure for the org. 

Some users prefer to use an existing account with a service such as Google or Facebook to log in to the site instead of setting up a new account and password. The third-party service is an authentication provider that verifies user identification. Use the Social Login component to add an icon for each supported authentication provider. The user clicks the icon and logs in using the associated account’s username and password. To enable customers to log in to Salesforce with their social credentials, you configure an authentication (auth) provider for the social account. Here’s what your customer experiences when you do.

  • A customer encounters a Salesforce login page with options to log in via Google, Facebook, Twitter, as well as username and password. (1)
  • The customer chooses to log in via Facebook credentials. (2)
  • Salesforce redirects the customer to Facebook. (3)
  • The customer logs in to Facebook. (4)
  • Facebook logs in the customer to Salesforce automatically because Salesforce trusts Facebook’s verification. (5)

Salesforce has several auth providers to choose from—more, if you count those auth providers that your developers can configure using the OpenID Connect protocol. And even more—if your developers want to create their own authentication provider, they can use Salesforce APIs to do so.

Steps to Enable Social Sign-on

For the detailed steps, please see the demo provided at the start and end of this blog.
  1. Create Registration Handler Class:
    SSORegistrationHandler.cls
    global class SSORegistrationHandler implements Auth.RegistrationHandler {
        private static final String ORG_SUFFIX = '.sso.badge.org';
        private static final String DEFAULT_ACCOUNTNAME = 'Partners';
        private static final String EXTERNAL_USER_PROFILE = 'Partners';
        private static final String INTERNAL_USER_PROFILE = 'Standard User';  
        private static final String TZSID = [SELECT timezonesidkey from User where profile.name = 'System Administrator' LIMIT 1].timezonesidkey;
    
        global boolean canCreateUser(Auth.UserData data) {
            Boolean retVal = (data != null && data.email != null && data.lastName != null && data.firstName != null);
            return retVal;
        }
    
        global User createUser(Id portalId, Auth.UserData data){
            if(!canCreateUser(data)) {
                return null;
            }
            
            // Is this a Community Context?
            if(data.attributeMap.containsKey('sfdc_networkid')) {
                Id contactId;
                List<Contact> existingContacts = [SELECT Id, Email FROM Contact WHERE Email = :data.email];
                if (existingContacts.size() > 0){
                    Contact existingContact = existingContacts[0];
                    contactId = existingContact.Id;
                    List<User> existingUsers = [SELECT Id FROM User WHERE ContactId = :contactId];
                    if (existingUsers.size() == 1){
                        return existingUsers[0];
                    }
                } else {
                    contactId = createContact(data);
                }
                
                Profile p = [SELECT Id FROM Profile WHERE Name = :EXTERNAL_USER_PROFILE];
                User u = createUser(data, p);
                u.contactId = contactId;
                return u;
            } else {
                //This is not a community, so we Assign an internal profile
                List<User> listOfExistingUsers = [
                    SELECT Id, Name 
                    FROM User 
                    WHERE Email = :data.email AND IsActive = true AND UserType = 'Standard'
                        AND FirstName = :getValue(data.firstName)
                        AND LastName = :getValue(data.lastName)
                ];
                Profile p = [SELECT Id FROM profile WHERE Name = :INTERNAL_USER_PROFILE];
                User newUser = createUser(data, p);
                return !listOfExistingUsers.isEmpty() ? listOfExistingUsers[0] : newUser;
            }
        }
        
        global String getValue(String attributeValue){
            return String.valueOf(attributeValue?.replaceAll('[^A-Za-z0-9]', ''));
        }
           
        global void updateUser(Id userId, Id portalId, Auth.UserData data){
            User updateUser = new User(Id=userId);
            updateUser.email = data.email;
            updateUser.lastName = getValue(data.lastName);
            updateUser.firstName = getValue(data.firstName);
            update(updateUser);
        }
        
        private Id createContact(Auth.UserData data){
            Contact contact = new Contact();
            contact.LastName = data.lastName;
            contact.FirstName = data.firstName;
            contact.Email = data.email;
            
            // set Account Id
            if (data.attributemap.get('accountId') != null){
                contact.accountId = data.attributemap.get('accountId');
            } else {
                List<Account> accounts = [SELECT Id FROM Account WHERE Name = :DEFAULT_ACCOUNTNAME];            
                contact.accountId = accounts[0].Id;            
            }
            insert contact;
            return contact.id; 
        }
    
        private User createUser(Auth.UserData data, Profile p) {
            User u = new User();
            u.username = data.email + ORG_SUFFIX;
            u.email = data.email;
            u.lastName = data.lastName;
            u.firstName = data.firstName;
            String alias = data.firstName + data.lastName;
            
            //Alias must be 8 characters or less
            if(alias.length() > 8) {
                alias = alias.substring(0, 8);
            }
            u.alias = alias;
            u.languagelocalekey = UserInfo.getLanguage();
            u.localesidkey = UserInfo.getLocale();
            u.emailEncodingKey = 'UTF-8';
            u.timeZoneSidKey = TZSID;
            u.profileId = p.Id;
            return u;
        }
    }
  2. Create an Authentication Provider: Use the above Registration Handler class for SSO Auth provider.
  3. Enable My Domain and add options for Social Sign-on: Enable the My Domain and add Social Sign-on options based on the auth provider that you have created in Step 2. This option is only for Internal users.
  4. Enable Digital Experience and options for Social Sign-on for Experience Sites: This option is for External Users who wish to login to your company's Experience Site using their Social Accounts for different providers(Google or Facebook or LinkedIn) as set up in the Experience Site's login & registration page. For more details, please see the demo provided in this blog.

Demo:

Comments

  1. Great insights on Salesforce Platform Events! Clear and helpful breakdown. Excited to apply these tips in my projects. Thanks for sharing


    salesforce time tracking

    salesforce timesheet

    Salesforce Time Tracking Integration

    ReplyDelete

Post a Comment