6

For our customers, I'd like to allow them to stay logged in to our customer portal/authenticated site similar to what Amazon does.

Goal is to reduce the number of times they have to "do anything" to access the site and then save authenticate for when they need to so something important (buy something or edit their account, etc).

How can this be done on force.com? How is is done in the non force-com world...assuming some sort of encrypted cookie? Are there any implications of the session length limits on salesforce such that sites users HAVE TO BE subject the same session timeout as our internal users?

6

One approach would be to encrypt the user's username/password and write them to a persistent cookie. So, in a custom login page controller, you would have code like

// Technically, '^' is permitted in an email address, but most systems disallow it
String data = username + '^' + password;

// Base64 encoded key is stored in a custom setting
EncryptionSettings__c settings = EncryptionSettings__c.getOrgDefaults();
Blob key = null;
if (settings.key__c == null) {
    // No key yet - create a random one and save it
    key = Crypto.generateAesKey(256);
    settings.key__c = EncodingUtil.base64Encode(key);
    insert settings;
} else {
    key = EncodingUtil.base64Decode(settings.key__c);
}
String base64blob = EncodingUtil.base64Encode(Crypto.encryptWithManagedIV('AES256', key, Blob.valueOf(data)));

// Set cookieName, maxAge appropriately
ApexPages.currentPage().setCookies(new Cookie[]{new Cookie(cookieName,base64blob,null,maxAge,false)});

In an action method, specified in the action attribute for the page, you could have something like:

if (ApexPages.currentPage().getCookies().get(cookieName) == null) {
    // No cookie
    return null;
}

String base64blob = ApexPages.currentPage().getCookies().get(cookieName).getValue();

EncryptionSettings__c settings = EncryptionSettings__c.getOrgDefaults();
if (settings.key__c == null) {
    throw new MyAppException('Cannot decrypt without a key!');
}
Blob key = EncodingUtil.base64Decode(settings.key__c);
String data = Crypto.decryptWithManagedIV('AES256', key, EncodingUtil.base64Decode(data)).toString();
String parts = data.split('^');
String username = parts[0];
String password = parts[1];
return Site.login(username, password, null); // a PageReference

NOTE - YOU SHOULD CAREFULLY REVIEW THE SECURITY OF THIS APPROACH. THE USER'S CREDENTIALS ARE NOT STORED ANYWHERE EXCEPT ON THEIR OWN MACHINE, ENCRYPTED WITH A KEY THAT RESIDES IN SALESFORCE. THIS LOOKS SECURE TO ME, BUT IT'S CONCEIVABLE THAT THERE MAY BE A SECURITY HOLE SOMEWHERE.

  • Interesting, and very cool. And then where would you put it, assuming that people could randomly show up at several different pages in the public part of the site? OR put it on every page but only execute if they're guest? – Shane McLaughlin Sep 26 '12 at 2:37
  • Set it as the 'Authorization Required Page' in the 'Error Pages' for your Site. The platform will automatically show it if-and-only-if a user without a session tries to view a page for which they require a session. – metadaddy Sep 26 '12 at 4:13
  • You might also find Authenticating Users on Force.com Sites useful. – metadaddy Sep 26 '12 at 4:16
  • Is there any way we can restrict the output encrypted data size here? like say before the encryption the data size of the field is 5 and say blob value of the string is 10. Post encryption the blob values is 55 and the string size will be for sure greater than 5. How to handle this issue. – chops May 5 '15 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.