Thursday, February 28, 2019

Login Flows - Way to Customize User Authentication Flow

Login flows acts as business process which you want to invoke for user after logging. Login flows are assigned at profile level.


How Login Flow works?


Custom 2 Factor Authentication

Login flows can be used to provide custom 2 factor authentication. Below is flow chart that I have prepared to implement this:

Different steps involved:
  • Once user logged in, will be redirected to login flow.
  • From login flow, call apex call which can either perform callout to external system which can send authentication code to user via SMS or email. You can use twilio app to send sms to users. You can store the auth code from callout response in salesforce(may be in some custom field on user object).
  • If you don't want to use external app, then generate random code in apex and store it in custom field in user object and send email to user with code using apex email message methods.
  • Once user receives the code will enter it in input text on login flow. 
  • If user entered code matches with code stored in user object custom field then allow user to navigate to Salesforce. As a best practice clear the code stored in user object once validation completed so that user can not reuse the same code again.
  • If there is mismatch, you can deny user access.

Important considerations while using login flows
  • Login flow can not be used to replace Salesforce authentication but can used as additional set of authentication.
  • Login flow can be used to display some important messages to users once they login. Refer Login Flows to Display Important Messages to User After Login to learn about this in detail.
  • Login flows are only applicable for UI login not for API login.
  • Login flow can be used with SAML JIT. If user doesn't exist then during JIT, first user will be provisioned and then login flow will kick off. If user fails 2 factor authentication from login flow,then deactivate the user again in salesforce.
  • When user login, user login date like type of device, IP address, session id, user agent etc are available in visual workflow designer. This can be used to provide different user experience to user based on login device.
  • As a best practice, do not enable custom 2 factor authentication for system administrators.

Hope this will help!!

Thursday, February 21, 2019

How to update Chatter User Profile Photo using Connect API

The "connectapi" provide classess and static methods to access chatter data which is available through Chatter REST API. This is also referred as "Chatter in Apex". It exposes the data in localized and structured way.

Chatter in apex provides "UserProfiles" class which provides different methods to access information about users profile data.

Before version 35, "Chatterusers" class was there which was used to access information about users, such as activity, followers, subscriptions, files, and groups. Now this class is not available.

We will use UserProfiles class to update chatter user photo. You can either upload the image in documents or at any place. We need blob representation of that image and can be used to update profile photo using blob variable.

Below is sample code:

Document doc=[SELECT id, body FROM Document  WHERE Name='ProfilePhoto' LIMIT 1];
//set the photo on the user's profile
ConnectApi.UserProfiles.setPhoto(null, UserInfo.getUserId(), new ConnectApi.BinaryInput(doc.body,'image/jpg','user.jpg'));

I Have uploaded image in documents and then updating the profile photo on chatter.


setPhoto method require below attributes:
  • communityId (string)- specify the community Id or specify null for internal users
  • userid(string)- 15 digit or 18 digit user recordId 
  • Image details (ConnectApi.Binary​​Input) -  you need to specify the blob(content of file), MIME type of content and file name(string).

If you store profile photo in files, then you can use below syntax to update chatter profile photo:

ConnectApi.UserProfiles.setPhoto(null, UserInfo.getUserId(), '0690I00000D42WT',null);

This method takes 4 parameters
  • communityId (string)- specify the community Id or specify null for internal users.
  • userid(string)- 15 digit or 18 digit user's recordId.
  • fileId(string) - 15 or 18 digit file Id.
  • version number(integer) - Version number of the existing file. Specify either an existing version number, or null to get the latest version.
Hope this will help!!

Saturday, February 16, 2019

How to get User Locale information in Lightning Components

Lightning framework provide $Locale which can be used to get current user preferred locale. For example you can get user preferred timezone, language, currency format etc.

In Spring'19, Salesforce introduces new date-time $Locale attributes for date- time formattingas mentioned below:
  • longDateFormat ("MMMM d, yyyy")                              
  • shortDateFormat ("M/d/yyyy")
  • shortDatetimeFormat ("M/d/yyyy h:mm a")
  • shortTimeFormat ("h:mm a")
You can refer this global variable either directly in lightning component markup or in controller.js  file.

Below is sample code:

Snapshot of lightning component

For detailed information on Locale global variable, please refer below URL:
$Locale in Lightning Component


Hope this will help!!!

Tuesday, February 12, 2019

Way to avoid Callouts during maintenance or site switching activity (during read only mode)

Salesforce maintain each instance in 2 different geographical locations and perform site switching after every 6 months. One location act as "active site" with all transaction and replicate all transaction in second location called as "ready site" in near real time.

Site switching helps Salesforce to perform maintenance activity and to plan for disaster recovery. Ideally this activity takes 1 hour and Salesforce instance will be available in read only mode.

If you have callout to external system and based on response you are trying to update anything inside salesforce then during read only mode Salesforce execute all callout but update on salesforce will be blocked. This may create some inconsistency in your program flow.

To avoid this scenario, first check if system is in read only mode or not then perform write operation in salesforce.

Salesforce provide below method through which you can identify if instance is read only mode or in default mode.

System.getApplicationReadWriteMode(); 

If this method return "ApplicationReadWriteMode.READ_ONLY" enum value, then the org is in read-only mode. If it return "ApplicationReadWriteMode.DEFAULT" then org is available in read/write mode.

Below is sample code which you can use in your apex logic

// check read only status for org
ApplicationReadWriteMode currentMode = System.getApplicationReadWriteMode();
String returnValue = '';

if (currentMode == ApplicationReadWriteMode.READ_ONLY) {
// avoid callout

} else if (currentMode == ApplicationReadWriteMode.DEFAULT) {
//perform callout
// write back in salesforce based on callout response

}

How to test read only mode in sandbox

Contact salesforce to enable read only test mode option for sandbox. Once enabled, you can toggle read only mode test functionality in sandbox.

Hope this will help!!!