SSO Integration between Salesforce Orgs

There is very good blog which explains steps-by-step about how Salesforce will be acting as both Identity Provider (IdP) and Service Provider (SP).

Requirement: Lets implement integration between IdP and SP. So, that whenever the User is Active/In-Active in IdP, the same thing should be reflected in the SP.

Solution: We will implement a batch job in IdP which makes a REST based callout to SP in order to create or update the users.

Step 1: Create connected App in Destination (in our case it is SP)

connectedAppforSSO

Step 2: Configure Client Secret, Consumer Key and the URL instance from Destination Org (SP) in Source Org (IdP)

Client Secret, Consumer Key should be configured in Custom Setting but in this example I will be directing using this in code. And the URL instance must be configured in Remote Site Settings.

Setup -> Security Controls -> Remote Site Settings

RemoteSiteSetting.jpg

Step 3: Create a seperate Integration user in SP org and mark its profile as Password Never Expires. But in this case, we will be using admin user credentials instead of creating new integration user as we have a limit on number of licences.

Step 4:Create a custom REST based webservice in SP

@RestResource(urlMapping='/upsertuser/*')
global class UserRestService {
@HttpPost
global static void doPatch(){
List<User> ulist = (List<User>)JSON.deserialize(RestContext.request.requestBody.toString(), List<User>.class);
Database.UpsertResult[] uResult = Database.upsert(ulist, User.Fields.FederationIdentifier, true);
}
}

Step 5: Create a Service class which will send user data from IdP to SP

public class IntegrationService {
private final String spClientId = '';
private final String spClientSecret = '';
private final String spIntegrationUName = '';
private final String spIntegrationPwd = '';
private final String spInstanceURL = 'https://playwithsf-dev-ed.my.salesforce.com'; // replace
private final String spProfileId = '00e24000000zKLr'; // Chatter-free ProfileId
private final String spNamespace = 'singhcloud'; //replace, if namespace is set

// connecting SP from IdP
public String establishConnection(){
String sessionId = '';
String reqBody = 'grant_type=password&client_id=' + spClientId + '&client_secret=' + spClientSecret +
'&username=' + spIntegrationUName + '&password=' + spIntegrationPwd;

Http h = new Http();
HttpRequest request = new HttpRequest();
request.setBody(reqBody);
request.setMethod('POST');
request.setEndpoint(spInstanceURL + '/services/oauth2/token');

HttpResponse response = h.send(request);
sessionId = fetchSessionId(response.getBody());

return sessionId;
}

private String fetchSessionId(String responseBody){
OAuth2 objAuthenticationInfo = (OAuth2)JSON.deserialize(responseBody, OAuth2.class);
return objAuthenticationInfo.access_token;
}

private List<User> buildJSON(){
User usr;
List<User> ulist = new List<User>();
for(User u : [SELECT Id, LastName, Username, City, PostalCode, Country, Email,
IsActive, ProfileId, FederationIdentifier, Alias, TimeZoneSidKey,
LocaleSidKey, EmailEncodingKey, LanguageLocaleKey
FROM User where LastModifiedDate =: Date.today()
]){
usr = new User();

usr = u.clone(false, true, false, false);
usr.Username = u.Username + '.sso';
usr.ProfileId = spProfileId;
// This will deactivate the User from SP when it is deactivated from IdP
if(!u.isActive){
usr.IsActive = false;
}
ulist.add(usr);
}
return ulist;
}

public void pushUsersIntoSP(){
String sessionId = establishConnection();

if(!String.isEmpty(sessionId)){
Http h = new Http();
HttpRequest req = new HttpRequest();

req.setHeader('Authorization','Bearer '+ sessionId);
req.setHeader('Content-Type','application/json');
req.setHeader('accept','application/json');

String jsonBody = JSON.serialize((buildJSON()));
system.debug('json body ' + jsonBody);

req.setBody(jsonBody);
req.setMethod('POST');
req.setEndpoint(spInstanceURL + '/services/apexrest/' + spNamespace + '/upsertuser/');
HttpResponse response = h.send(req);
}
}

public class OAuth2{
public String id{get;set;}
public String issued_at{get;set;}
public String instance_url{get;set;}
public String signature{get;set;}
public String access_token{get;set;}
}
}

Step 6: Test the service

IntegrationService conn = new IntegrationService();
conn.pushUsersIntoSP();

Do share your thoughts and happy coding!!!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s