3

Org has 2 customer portals/sites e.g.

abcd.secure.force.com/xxxx
abcd.secure.force.com/yyyy

Most users have access to both portals, users have same set of credentials for both of the portals.

If user logins into one portal(say xxxx) & clicks on URL of another portals(url of yyyy), he is directed to login page of the 2nd portal(login page of yyyy).

I believe, as both sites are on same domain, have same set of credentials; need of having to enter same credentials once again can be avoided.

How can we ensure that - Login into one force.com site, logins user in 2nd site as well?

1 Answer 1

6

I've created my own login objects, classes, and pages where I keep track of users, and when they log on, I create my own SessionId and store the info in an object + a client side Cookie. Then, I have a method (used in the Action parameter of apex:page) that validates my session for every Portal Site page visited.

I too have multiple sites for a single org with users existing among all of my portals. I differentiate Portal sessions by the unique cookie name for that particular Portal (+ the record where the Session info is stored).

If you'd like to know more about my setup (including some code), let me know, and I can post some details.


Some Details:

We manage multiple orgs, and each org may contain a number of Sites. Additionally, each site generally uses different sObjects as "User records" (e.g. the associated user record is an Account record or Employee__c record). So, after creating a handful of Sites (custom portals for different client needs), each with their own login page & home page & ..., I began to see how to generealize this process.

It's split into a few steps:

Step 0: For security, when a user logs in, a SessionID is created (a long randomly generated string) and is stored in a Cookie (along with the User's username). Then, whenever the user navigates to any of the other site pages, I first call a method in the action attribute of apex:page that verifies the SessionID (along with checking the SessionID isn't "too old").

I had to create code to do this function (obviously), and I realized this process could be generalized. (more to come about this below)

Step 1: Since each "User record" may belong to a different sObject, and I want to use this code across many orgs (not necessarily sharing the same custom sObjects), I needed to dissociate the "User records" from the Username__c, Password__c, Security-Questions, SessionID data. So, I created a custom object called Portal__c to house User-information and Session-data as well as Site-specific data accomplished by creating a number of RecordTypes for Portal__c.

RecordType = Portal: Houses Site parameters. e.g.

  • Session Cookie Name
  • Which Site the record belongs to
  • How long the allowable Session Length should be (before requiring the user to re-login.)
  • Which sObject designates the "User Record" (along with noting what the User-RecordType is.)
  • The name of the lookup-field in the Portal__c:User (i.e. the Portal__c record with the "User" RecordType) [more about the User RecordType in a sec]
  • I have a set of string fields called Login_Page__c, Home_Page__c, Register_Page__c, Error_Page__c, Expiration_Page__c, Forgot_Page__c where I can set the name of the corresponding VF Page. (This allows for easy navigation.)

RecordType = User:

Since each User record could be attached to different sObjects (like Account or Employee__c), we will need a lookup to each of these different sObjects. To make administration easier, I create a different "User"-RecordType for each Site. (Tt is sufficient to have a different RecordType per distinct User-record-sObject.) This is why I allow the Portal__c:User records to have different RecordTypes.

The Portal__c:User records have:

  • Username
  • Password (encrypted)
  • lookup to the associated "User Record"
  • picklist of Security Questions
  • Security Answer (encrypted)

RecordType = Session:

Houses Session Data and has a lookup to the associated Portal__c:User record. Every time a user logs in, a new Portal__c:Session record is created.

There's not much here:

  • SessionID (encrypted)
  • lookup to Portal__c:User record
  • Long Text Area field to house the Session History (an attempt to reduce the # of records created since the cost of each record is independent to how much data is stored within it). I have code that writes the Session History to this field whenever a User navigates through the Site.

Step 2: I created an Apex class called Portal to manage all this Portal and User information in a really easy-to-use way. In fact, it mimics some of the functionality of ApexPages.StandardControllers:

  • I wrote a lot of back end code to manage creating and verifying the Portal Sessions.
  • Whenever a user navigates to a Site page, a new Portal instance is created, and it collects all the relevant data.
  • The instance gives you the associated User-record and id just like a StandardController would.
  • It's very easy to verify the SessionID, and if it is invalid, it redirects to the LOGIN page automatically.
  • There are tools to navigate to different pages.

E.g.:

Portal portal = new Portal('mySiteName');
pageReference goHome = portal.getPage(Portal.Page.HOME);
id myRecordId = portal.getUserId();
pageReference verifySessionResult = portal.getSessionCheck();
pageReference theLoginPage = portal.loginPage();  // an easy escape to the login page

That's essentially it. It's really cool because it's a breeze to create new portal! The only real-work is creating the VF pages.

I'm still tweaking everything, and there is definitely room for improvement.

3
  • We have achieved that by actually opening one portal in another in hidden iframe. This way we manage to receive cookies of both portals in browser. Oct 9, 2013 at 12:45
  • I would like to know our way of doing this. Code may be unnecessary but you can explain this in bit more detail. Oct 9, 2013 at 12:47
  • I added an update :) Oct 9, 2013 at 17:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .