Monday, March 9, 2015

[Salesforce / SSO] Implementing Delegated SSO


Playing with code is cool, but playing with useless stuff is even better :)

Ok, I'm kidding, I just want to say that sometimes you have to get your hands dirty to understand what lies underneath things and try to build useless stuff to see simple "Hello world!" appear!

This is the case of Delegated SSO.

Few weeks ago with Paolo (a colleage of mine), I was checking deeper on Salesforce SSO, trying to figure out from the docs how to implement it.

The first thing that came across my eyes was the difference between Delegated and Federated SSO.
It wans't that clear at that time, that's why Paolo played with the code for some time and did a cool thing that I reproduced in the following Github repo.

Federated SSO is done using well known protocols such as SAML, granting a secure identity provisioning: with Microsoft ADFS you can use your own company domain to log on your Salesforce CRMs as well.

Which is the problem with this kind of SSO?

To implement its bases you don't need a single line of code.


Too bad we are dirty men that like to play with mud!


That's why this post!


With Delegated SSO you need 2 actors:
  • An Identity provider (e.g. your Domain server)
  • The Salesforce ORG in which you want to be logged in without remembering username/password

The first wall you splash into is the fact the you have your ORG to be enabled to Delegated SSO: this should be enabled by Salesforce support, so you need a way to contact support (if you're not using an ORG with built in support).

After your ORG is enabled to Delegated SSO, this is where the config has to be enabled in your "delegated" ORG:

The Delegated Gateway URL contains the URL of the webservice of the "delegating" server.

Then you have to enable the Is Single Sign-On Enabled flag in the Administrative Permissions section of your users' profile.

This is where we got our hands dirty while making out research: why not using a Salesforce ORG as the identity provider?

Challenge accepted!

What happens with delegated SSO? When you try to log in into your delegated ORG, Salesforce at first try to access the "Delegated SSO" webservice: if this accept the request, than you are automatically logged in; if the server gives a KO, than the ORG checks for username/password to be correct.

This is the message that the delegated ORG sends to the identity provider:
<?xml version="1.0" encoding="UTF-8" ?>
<soapenv:Envelope
   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <Authenticate xmlns="urn:authentication.soap.sforce.com">
         <username>sampleuser@sample.org</username>
         <password>myPassword99</password>
         <sourceIp>1.2.3.4</sourceIp>
      </Authenticate>
   </soapenv:Body>
</soapenv:Envelope>

It basically asks for a user/password couple with a source IP, and receives this response:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope 
   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <AuthenticateResult xmlns="urn:authentication.soap.sforce.com">
         <Authenticated>false</Authenticated>
      </AuthenticateResult>
   </soapenv:Body>
</soapenv:Envelope>

The Authenticated field conveys the OK/KO result.

You can use the password field to host a unique and temporary token to make the connection more secure.

To log-in from your identity provider page, use this example page (see the /apex/DelegateLogin page):

Each of this users is a delegated user on another ORG, that is stored in the DelegatedUser__c SObject:

It stores Username and Remote ORG ID, because it is used to create the login URL to make the authentication go smootly for the user:
public PageReference delegateAuthentication(){
 String password = generateGUID();
 insert new DelegatedToken__c(Token__c = password, 
         Username__c = this.usr.DelegatedUsername__c,
         RequestIP__c = getCurrentIP());
 String url = 'https://login.salesforce.com/login.jsp?'
    +'un='+EncodingUtil.urlEncode(this.usr.DelegatedUsername__c, 'utf8')
    +'&orgId='+this.usr.Delegated_ORG_ID__c 
    +'&pw='+EncodingUtil.urlEncode(password, 'utf8')
    +'&rememberUn=0&jse=0';
 //you can also setup a startURL, logoutURL and ssoStartPage parameters to enhance usre experience
 PageReference page = new PageReference(url);
 page.setRedirect(false);
 return page;
}

This way you can request a login action for every user you have stored in your objects (this case has the same ORG but you can have wathever ORG you want, no limits); the token is stored in a DelegatedToken__c SObject that is used to handle temporary tokens, usernames and IPs: this way, when the delegated ORG asks our ORG with this infos, our webservice can succesfully authenticate the requesting user.

This is done through the public webservice exposed by the RESTDelegatedAuthenticator class:
    @HttpPost
    global static void getOpenCases() {
        RestResponse response = RestContext.response;
        response.statusCode = 200;
        response.addHeader('Content-Type', 'application/xml');
        Boolean authResult = false;
        try{
            Dom.Document doc = new DOM.Document(); 
            doc.load(RestContext.request.requestBody.toString());  
            DOM.XMLNode root = doc.getRootElement();
            Map<String,String> requestValues = walkThrough(root);
            
            
            authResult = checkCredentials(requestValues.get('username'), 
                                          requestValues.get('password'),
                                          requestValues.get('sourceIp'));
        }catcH(Exception e){
            insert new Log__c(Description__c = e.getStackTraceString()+'\n'+e.getMessage(), 
                       Request__c = RestContext.request.requestBody.toString());
        }finally{
            insert new Log__c(Description__c = 'Result:'+authResult, 
                       Request__c = RestContext.request.requestBody.toString());
        }
        String soapResp = '<?xml version="1.0" encoding="UTF-8"?>'
            +'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">'
            +'<soapenv:Body>'
            +'<authenticateresult xmlns="urn:authentication.soap.sforce.com">'
            +'<authenticated>'+authResult+'</Authenticated>'
            +'</AuthenticateResult>'
            +'</soapenv:Body>'
            +'</soapenv:Envelope>';
        response.responseBody = Blob.valueOf(soapResp);
    }

This webservice simply checks the incoming SOAP XML request, extracts the fields on the request and tests its values with the checkCredentials() method.

If the token is not expired you'll be succesfully redirected to the new ORG logged as the user you wanted to.

A good practice is to use custom domains: you can thus replace "login.salesforce.com" with your "My Domain" of the corresponding ORG (you can also add a new field on the DelegatedUser__c SObject.

To enable public webservice, you simlpy need to create a new Site:

Then click on your Site, click the button "Public Access Setting" and add the RESTDelegatedAuthenticator to the Apex classes accessible by this public profile.

The comple code is right here in this Github repository.

May the Force.com be with you!

Thursday, February 26, 2015

[Salesforce / RemoteAction] Using Date fields on a RemoteAction (PITA ALERT!)

I've just come through a bug on the Date field handling for Visual Force @RemoteAction.

We want to pass to a remote action a list of SObjects to be handled correctly.

This is the controller that hosts the @RemoteAction method:

public class MyController(){
   @RemoteAction
   public String doAction(List<contact> contacts){
      return 'All is ok!';
   }
}

This is the JS on the VF page:

function action(){
   var contact1 = {"LastName":"Smith",
                   "FirstName":"John",
                   "Phone" : "999-999-999"};
   var contact2 = {"LastName":"Brown",
                   "FirstName":"Mike",
                   "Phone" : "123-456-789"};
   var contactList= [contact1, contact2];
   Visualforce.remoting.Manager.invokeAction(
              '{!$RemoteAction.MyController.doAction}', 
              accList || [],
                function(result, event){
                    if(event.status){
                        alert(result);
                    }else{
                        //generic event error
                        alert(event.message);
                    }
                },{escape: false, timeout: 120000});
}

This runs perfectly.

But let's add a Date field on the JS part:
function action(){
   var contact1 = {"LastName":"Smith",
                   "FirstName":"John",
                   "BirthDate":"1980-01-01",
                   "Phone" : "999-999-999"};
   var contact2 = {"LastName":"Brown",
                   "FirstName":"Mike",
                   "BirthDate":"1982-11-21",
                   "Phone" : "123-456-789"};
   var contactList= [contact1, contact2];
   Visualforce.remoting.Manager.invokeAction(
              '{!$RemoteAction.MyController.doAction}', 
              contactList || [],
                function(result, event){
                    if(event.status){
                        alert(result);
                    }else{
                        //generic event error
                        alert(event.message);
                    }
                },{escape: false, timeout: 120000});
}

And all messes up, stating that you are passing an incorrect type to MyController.doAction(List).

The problem is related to how the Date type serialization is done when invoking the Remote Action (it is apparently a bug not fixed yet).

The solution is to pass a serialized version of the JS array and deserialize it with Apex:

public class MyController(){
   @RemoteAction
   public String doAction(String serializedContacts){
      List<contact> contacts = (List<contact>)JSON.deserialize(objList,List<contact>.class);
      return 'All is ok!';
   }
}


function action(){
   var contact1 = {"LastName":"Smith",
                   "FirstName":"John",
                   "BirthDate":"1980-01-01",
                   "Phone" : "999-999-999"};
   var contact2 = {"LastName":"Brown",
                   "FirstName":"Mike",
                   "BirthDate":"1982-11-21",
                   "Phone" : "123-456-789"};
   var contactList= [contact1, contact2];
   Visualforce.remoting.Manager.invokeAction(
              '{!$RemoteAction.MyController.doAction}', 
              JSON.stringify(contactList || []),
                function(result, event){
                    if(event.status){
                        alert(result);
                    }else{
                        //generic event error
                        alert(event.message);
                    }
                },{escape: false, timeout: 120000});
}

Remember: don't mess with JSON serialization!

Tuesday, February 24, 2015

[NodeJS] My Simple Static Webserver


When developing pure HTML5 mockups I usually don't want to install a webserver or host my static pages on a remote webserver...
More over I sometimes like to create my own tools even if they are already on the net or they are super duper simple.

That's why I created a simple NodeJS static webserver.

You can find that simple app in this Github repo.

To use it just type:

$ git clone https://github.com/enreeco/simple-static-web-server

$ node server

This will create a local webserver @ http://localhost:3000/index.html: all the files must be kept on the root folder.

If you want to specify another port simply type:

$ node server 1234

And the magic will be @ http://localhost:1234/index.html.

Before leaving remember my motto:

Friday, February 13, 2015

[Salesforce / Mobile SDK] Salesforce Mobile SDK 3.1 brings unified app architecture

I left mobile development in the far 2010, when Salesforce development became my actual job.
In the past 6 years I've gradually switched to web dev techs over native development, and this a kind of hurted my feelings, but it was a necessary path (I merged the passion for discovering new techs with learning something usefull for my "giving-money" job).

Few months ago I made up with my team a quick demo for a client using PhoneGap and the Salesforce Mobile SDK: it was really amazing, we created a fully working app (I'm not the wizard of UIs, but it was pretty amazing) in a couple of weeks.

With the new release of the Mobile SDK we have a unique set of interfaces shared between all platforms to link your app, so you don't have to think to which feature you can use and which not, and dedicate your time to develop your awesome app in your preferred platform.


Here it is a link to the Mobile SDK Release Notes.

SmartSync for native and hybrid development is (in my opinion) the coolest utility feature in this release: this grants a common set of complete API to talk to the SmartSync layer, to ptimize data access when storing objects or doing cached queries.

This allow you to develop responsive and high qualities apps that work perfectly is an offline mode as well as online mode, creating a caching layer and a conflict resolution control.

The following is a cool mini-tutorial on how to detect conflicts when managing offline data while the details of the SmartSync usage.

For a complete example jump on this tutorial.

Other important features includes:
  • CocoaPods for iOS: iOS devs can now use CocoaPods to handle the Salesforce Mobile SDK
  • Gradle for Native Android Apps: Gradle is now supported for Android development, and will be available for Cordova Hybrid Dev in the next Cordova release
  • Certificate Based Authentication Pilot: no need for username/password request for your users to log in

This framework is getting new features release after release, and if you haven't join our developer community and start build awesome apps!


Thursday, January 22, 2015

[Salesforce] My favorite Spring '15 features



This is my top 10 list of the Spring '15 Force.com platform update's features.


Make Long-Running Callouts from a Visualforce Page


This is a really important feature. Imagine you have big VisualForce pages in which Apex methods, triggered by buttons / links / rerenders, do one or more callouts to external services.

Imagine hundreds of users use that page and the external services go down, thus causing timeouts on the callouts.

This could lead to heavy problems, because there can be no more than 10 long running Apex processes at the same time: this leads to unexpected and horrible output errors.

Using this new feature we can now "asynchronize" synchronous Apex callouts, using the new Connection Apex class, that is used like a callback when the callout has ended.
Basically you create a method split in 2 parts: the first (invoked by a button / link) has the starting callout code and the last receives the results from the callout.
Even if the callout/callouts (you can trigger up to 3 callout a time) fails / go timed out this call won't count towards the logn running processes.

I'm gonna write down a post to show how this works using HttpRequests and also SOAP requests.


Set Up Test Data for an Entire Test Class


This is an extremely useful feature for large ORGs with hundreds of test classes.

This allow us to write "test setup" methods (new annotation @testSetup) that are called once per test class: when a test method is executed the context has all the objects created in those setup methods (you can have more than one method of this kind, but the execution order is not guaranteed). Each test method execution rollbacks its data at the end, so that the following class's test method will see the values as if they were just been created.


Deploy Your Components in Less Time


Imagine you have the GO for a deploy in your production ORG but you have to do it at saturday midnight (and test methods requires more than an hour to run!!!!)...this is absolutely not cool!

This feature allow you to send a deploy to production before your deadline, test classes are run during this "freezed" deploy and it stays freezed for 4 days: when you are ready you simply click the "Quick Deploy" button and the components are deployed instantly! Whoooaa this is magic!



Create Named Credentials to Define Callout Endpoints and Their Authentication Settings


You can finally leave all the authentication mess to the Force.com platform and just sit on your screen and simply code you business requirement, magically storing sessions, tokens and whatever it is needed on Salesforce.

You can also use a named credential in a simplyfied way to store callout endpoints.


Business Continuity - Promote Business Continuity with Organization Sync


With Organization Sync you can setup a secondary ORG that you can use when your primary ORG needs some maintenance (e.g. a big release of your developments), giving a 24/7 service availability.

Orgs are synched automatically through a data replication mapping.

I haven't already tested this feature, but being available on developer Orgs I'll certainly try it soon.


Visually Automate Your Business Processes


This is the Lightning Process Builder, a cool visual tool that help you automates your business processes, from simple actions to complex combinations.

It seems really awesome but unfortunately it is not available on the pre-release program.
You better see in the next days tens of posts about this new feature!


Lightning Components (BETA)


Lightning components are still in beta and the builder in pilot.
But we have new additions:

  • New Components: brand new base components (such as select input, textarea, ...)
  • Namespace Requirement Removed: finally no need to setup a namespace, easing the creation of packages and the deploy across orgs
  • Support Added for Default Namespace: follows the previous point
  • Extend Lightning Components and Apps: like classes, you can extend components and apps
  • Referential Integrity Validation Added: integrity validation has been boosted


New increased limits


There are some new increased limits:

  • Deploy and Retrieve More Components: limit increased from 5000 to 10000 components
  • Chain More Jobs with Queueable Apex: from 2 chained jobs to infinity (except for Developer and Trial orgs where the limit is 5)
  • Make Apex Callouts with More Data: size per callout (HTTP or SOAP) increased from 3 MB to 6 MB for synchronous APEX and 12 MB for asynchronous


Create or Edit Records Owned by Inactive Users


All users can now edit objects owned by inactive Users, before Spring '15 only administrator could do it!
Believe me, this is really usefull.


Legitimize User Activity using Login Forensics (PILOT)


These are forensics metrics to identify suspicious behavior of users (such as logins from unusual IPs or excessive number of login among the average number).
This is a PILOT program, so you have to explicitly ask Salesforce to be enabled.


As usual, may the FOrce.com be with you guys!

Tuesday, December 9, 2014

[Salesforce / JS] Download automatically files from apex (using href link and base64)

This post is a recap of this Salesforce Developer Forum thread.

We want to trigger a download from an attachment but the running user don't have access to the object (think of Community User for instance).

In the controller read the Attachment's body in a String getter coded in Base64:

public String base64Value{get;set;}
public String contentType{get;set;}
public void loadAttachment(){
   Attachment att = [Select Id, Body, ContentType From Attachment limit 1];
   base64Value = EncodingUtil.base64Encode(att.Body);
   contentType = att.ContentType;
}

In the page:
<a href="data:{!contentType};content-disposition:attachment;base64,{!base64Value}">Download file</a>

Saturday, December 6, 2014

[Chrome Extension] "Pack your link" extension on the store by enree.co (yes, thet's me...)



I'm not a marketing guy, I neither have requested advices from my marketing guys friends...I did it all my way and that's why my brand new Chrome Extension will be forgotten in days!

Let's start from the beginning...

Once upon a time there was a simple Chrome Extension I made at work for WebResults, my Company: you will hear about it in weeks, but not now.

After weeks of testing we decided to put it in the market but I didn't now how to do it (I know, there si plenty of stuff online, but I don't trust myself till I see things done!...that's why because sometimes I behave like Goofy when dealing with simple tasks!!).

So I thought, "How can I do a clean job for my company without making foolish mistakes"?

The answer was "Create your own extension".

That's why I created url.enree.co (I love this domain name), a simple Url packing utility hosted on Heroku, written in NodeJS.


Why not creating a simple chrome extension to use this service?

Here you are Pack your link by url.enree.co.


Publishing a Chrome Extension on the store is really easy.
  1. Create your extension (start here if you don't know what to do, it's easy and fun)
  2. Go to the Chrome Store Developer dashboard: you have to pay 5$ to be able to publish your creations on the store, once in a lifetime! In few minutes you'll be allowed to publish extensions and apps.
  3. ZIP your local extension's folder and upload it: it seems that you cannot remove a product once uploaded (read more details here, but I'm not quite sure about it), but you can still unpublish to hide it.

See ya!