Abstract

Force.com Sites lets you create public web sites and applications that run natively on Force.com, extending the reach of your applications to new users on intranets, external Web sites, and online communities. You may sometimes want to authenticate users on these web sites – for example if you’re building a shopping portal or registering users for a service.

This tutorial shows you how to authenticate users on Force.com Sites. It provides a description of Customer Portal, which is needed for the authentication, and shows you how to set up such a site and process to allow site visitors to become authenticated users.

Guest Users and Profiles

When someone visits your Force.com Site, they may view all the pages that you provide on that site. What's important, however, is the type of activities that they are allowed to perform besides just viewing pages and clicking on navigation links. The type of actions that they can perform are completely controlled by their profile.

Since a new user arriving has no special identity or authority, they are automatically assigned the Guest User profile. The best way to see exactly what a guest can do when they arrive at your site is to review that profile. Log into your environment, and navigate to Setup | Develop | Sites, and then select your Force.com Site detail page. Here you'll find the button called Public Access Settings, as shown in the following figure.

Authsites publicaccess.png

Clicking on Public Access Settings will give you the details for the guest profile. This determines the security profile of each and every site visitor before they authenticate. Here's a screenshot from the guest user profile. The thing that I want to point out here is that all of the standard database objects can be read by the guest user, and many of these objects can be created by the guest user as well. You will notice that none of these standard objects may be edited or deleted by the guest user (nor can you edit the profile to allow that). What does this mean for your site?

Authsites noedit.png

Well for one thing it means that you can easily build a Visualforce page that will show records from these objects, including the Account, Contact and other standard objects, to any guest user on your site. Guest users can also read and update custom objects, if you set the permissions to allow it, which you can configure on this same page. For example, if you create a bug report object, you typically only want authenticated users to be able to edit bug reports. You can ensure that only authenticated users have access by only granting the edit permission on the object to a different profile - that assigned to authenticated users. The platform will then automatically ensure that unauthenticated users can never make edits. This is one of the many security features built into Force.com Sites.

In a typical scenario, you would grant read permissions on objects to the guest profile, but edit permissions to a profile assigned only to authenticated users. In other words, the visitor on the site must upgrade their profile to one of the two profiles which allow edits or updates to standard (or custom) objects. This user then becomes authenticated and falls under the permissions that are exposed by your Customer Portal user license. The process that allows this profile switch is the login process. First let's cover the basics of the Customer Portal, then we can describe the login process.

Customer Portal

The Salesforce Customer Portal is a product that provides a user license for each of your customers. In terms of Force.com Sites development, think of a customer as any person who is not an employee of your orginization, and with whom you would like to share secure data or processes. If you are designing a web application, you can also think of a customer as an authenticated user.

To understand this feature at the highest level, you can think of all of your customers as users in your database. These users have a subset of the normal suite of database objects available to them and a special profile that governs their access to your data. For example, these customer portal users could edit contact records or view accounts and update those bug report records in your database. You specify everything about these users' experience by defining the objects that they can see, their data permissions and even the user interface that they use to view the data. Providing this highly customized user interface is where Visualforce and Force.com Sites comes in.

To bring these two technologies (Customer Portal and Sites) together we will need a bit of code and a few Visualforce pages, but fortunately all of the required code is provided for you so that all you need is a bit of cut and paste to get started. You can then modify these pages to suit your web site and you will end up with a seamless system that allows your visitors to become customer portal users.

So what is a Customer Portal user? If you have never used the customer portal, you can easily get started using a Developer Edition. The latest Developer Edition environments come with Customer Portal licenses. A good way to start is to set up customer portal for your developer edition environment, which I'll cover shortly. The portal provides functionality to log someone in, and assign them a portal profile. Once someone is logged in, the data that they may have access to is the actual data from your environment.

Representation of Authenticated Users

Authenticated users are represented inside your environment as both a Contact record and a User record for each user of the portal. In other words, if someone registers for a login account, you can navigate to Setup | Manage Users | Users and manage them there. You'll notice that you can navigate from each User record to the associated Contact record using a lookup field.

The Contact records are also associated with an Account record. Because they are your "customers", this also allows you to effectively limit the data that they can see using account sharing rules.

While this sounds a little complicated, it's relatively easy to set up - but you will notice these items pop up in the configuration details below.

Customer Portal Setup

Now let's talk about setting up the portal. All of the steps that I'd like to cover here are also documented in the customer portal set up documentation. In fact, you should refer to the online documentation before beginning this process, and if you have any problems following this tutorial. I've assumed that you've already created your Force.com Site on a Developer Edition environment. If not, check out An Introduction to Force.com Sites.

To get customer portal turned on for your environment, you must visit Setup | Customize | Customer Portal | Settings. Click the box to enable portal, and hit save. You can skip the wizard. I have done that in my org and now the page looks like this:

Authsites portalsetup.png

You will notice that I have Login Enabled checked on this customer portal. Be sure to enable this check box as we will need it to be on later when we configure the login from Force.com Sites. Now that you have the portal enabled, you need to do a little setup. Click through to the portal details page. Here you'll see the Login Enabled is already set. However, we also want to enable Self-Registration, which allow new users to be created. In the final section on this page, "Self-Registration Settings", click the checkbox for "Self-Registration Enabled", change the "Default New User License" to "Customer Portal Manager", set the "Default New User" to "User" and the "Default New User Profile" to "Customer Portal Manager". Here's my final configuration:

Authsites selfreg.png

That's all I had to do to get started with portal. What this does is establish the user license associated with new users registered with the portal, and determines their profile.

The Customer Portal Profile

Once the basic portal is set up and the login enabled, you are ready to explore the profile that is created by the portal setup: Click on the name of the customer portal just created Locate the Default New User Profile link at the bottom of the page Click this link to review the default profile (it's probably called "Customer Portal Manager")

Let's take a look at this profile as it is on my org. This is the permission set that will be assigned by customer portal to authenticated users.

Authsites standperm.png

Now in this profile you can see that the customer portal user is able to read, create and edit cases and contacts as well as any custom objects that I may have granted them access to in my organization.

The key difference here is that guest users may not update contact records but portal users who are authenticated users, can update contact records in the system. Please keep these basic object permissions in mind while you are building your application or your Force.com Site.

Compare Guest and Portal Users Profiles

Now that we have looked at what a guest can do and what a portal user can do, let's compare the two. If you're a developer you can easily understand the difference between these two profiles by reviewing their profiles in the application, so we'll just look at this in a summary matrix, a simple table that shows one important difference exists on the Guest user and Standard Objects.

User Read Standard Objects Edit Standard Objects Read & Edit Custom Objects Sites Guest User Yes No Yes Customer Portal User Yes Yes Yes


Based on this restriction, if you want to edit a standard object, you must first authenticate that user. The platform will not allow you to grant permissions for Edit on Standard objects including Contact records. Fortunately for us developers, there is a straight forward way to promote the Guest User to become a Portal User, this process is called Authentication or Login. To achieve the highest security, Force.com offers one single process of authentication, so please don't be tempted to build your own authentication process.

Setting up a Force.com Site to Register and Authenticate Users

Walk through the following section all the way until the end to get basic authentication working.

Now, let's talk a little bit about the authentication process that allows a guests visiting your site to become authenticated and therefore have their profile changed. This is really two different steps since some of your users may not yet have their own login on your site. These processes are: self registration and login.

To begin you'll need a Force.com site. I assume that you will be able to set this up given the documentation that can be found within the application and on the Sites page in the Technical Library.

Next, I may be able to save you the trouble that I ran into while building this sample: I forgot to enable login for my site!

Here is a screen shot to show you just what I mean. In this screen the login feature is enabled for customer portal on my Force.com Site. Be sure that your site has this login enabled or you will see messages in your site indicating that the user is not authenticated, and it may not be clear that your site is not allowing this, even if you have an existing customer portal already configured. Do this by navigating to Setup | Develop | Sites, selecting your site, and then hitting the Login Settings button.

Authsites sitedetail.png

Notice that the login fields indicates that logins are enabled for Customer Portal. Once I turn this on, a number of Visualforce pages are created for you. The most important are:

  • SiteLogin, which allows registered users to log in to your web application
  • SiteRegister, which allows new users to be created for your web application

You can use these right out of the box. The Force.com Sites setup even takes care of adding this new Visualforce page to your list of pages that are enabled for the site For example, if you registered the domain acme, then you could go to these pages right now:

  • http://acme-developer-edition.na1.force.com/developers/SiteLogin
  • http://acme-developer-edition.na1.force.com/developers/SiteRegister

You can of course modify these pages as you see fit.

For customer portal the process of authentication begins in one of two ways; in the first case a valid portal user record already exists in the system (in other words, the user has already registered) and we take this user into the system through a Normal Login form, say from a login link on your Site. In the second case the user is coming to your site for the first time, and must complete the self registration process. This process will create a portal user and then proceed with the normal login method. Let's look at each of these in turn.

Normal Login

Let's take a look at the Visualforce page that allows a user to login - the standard SiteLogin page that's automatically generated. You can create your own, or use a template from your site.

Authsites login.png

Here is the Visualforce markup for this page, in this case the source we are reviewing it is a component that is placed on the login page that you create within your site.

<apex:component controller="SiteLoginController" id="loginComponent">
    <apex:form id="loginForm" forceSSL="true">
        <apex:outputPanel layout="block">
            <apex:pageMessages id="error" />
            <apex:panelGrid columns="2" style="margin-top:1em;">
            
                <apex:outputLabel value="{!$Label.site.username}" for="username" />
                <apex:inputText id="username" value="{!username}" />
                <apex:outputLabel value="{!$Label.site.password}" for="password" />
                <apex:inputSecret id="password" value="{!password}" />
            
                <br />
                <apex:commandButton action="{!login}"
                    value="{!$Label.site.login_button}" id="loginButton" />
                <br />
                <apex:panelGroup id="theLinks">
                    
                    <apex:outputLink value="{!$Page.ForgotPassword}">
                        {!$Label.site.forgot_your_password_q}
                    </apex:outputLink>
                    
                    <apex:outputText value=" | "        
                        rendered="{!$Site.RegistrationEnabled}" />
                    <apex:outputLink value="{!$Page.SiteRegister}"
                        rendered="{!$Site.RegistrationEnabled}">
                        {!$Label.site.new_user_q}
                    </apex:outputLink>
                    
                </apex:panelGroup>
            </apex:panelGrid>
        </apex:outputPanel>
    </apex:form>
</apex:component>

The key aspects to this page are:

  • A simple form (loginForm) that holds the username and password
  • A controller, SiteLoginController, which does the actual work of logging in
  • A link to the registration form for self registration. Note how it uses the Visualforce global variable $Page.RegistrationEnabled to determine if registration has been enabled for your site.

Let's now look at the Apex Code for the controller, SiteLoginController:

public class SiteLoginController {
    public String username {get; set;}
    public String password {get; set;}

    public PageReference login() {
        String startUrl = System.currentPageReference().getParameters().get('startURL');
        return Site.login(username, password, startUrl);
    }
    
       public SiteLoginController () {}
    
    public static testMethod void testSiteLoginController () {
        // Instantiate a new controller with all parameters in the page
        SiteLoginController controller = new SiteLoginController ();
        controller.username = '[email protected]';
        controller.password = '123456';
                
        System.assertEquals(controller.login(),null);                           
    }    
}

It's pretty basic. It simply takes the username and password, and invokes the system method Site.login(). (See all the methods for this class in the docs.) The return value from this call is a PageReference. If the login is successful, the page that will be returned is the one passed in the startUrl. As you can see, you can pretty easily build your own authentication pages around this code.

Self Registration for New Users

Now let's turn to self registration. When setting up the Customer Portal we enabled self-registration. As mentioned above, you can simply make use of the SiteRegister Visualforce page (and accompanying SiteRegisterController Apex Code) to accomplish the task, or write your own code. The default page looks something like this:

Authsites reg.png

As you can see, the critical pieces of data include:

  • A username for the new user
  • A nickname
  • The email address of the user
  • A password

The basic process of registration boils down to the following code snippet:

 User u = new User();
 u.Username = username;
 u.Email = email;
 u.CommunityNickname = communityNickname;
 
 String accountId = PORTAL_ACCOUNT_ID;

 // lastName is a required field on user, but if it isn't specified, 
 // the code uses the username
 String userId = Site.createPortalUser(u, accountId, password);

As you can see, it's a matter of creating a new User, and populating the Username, Email and CommunityNickname fields, and then passing this into the Site.createPortalUser() method.

The only tricky bit is that you need to pass in an accountId as well. In fact, the automatically generated SiteRegister needs this ID set as well before it will work. Recall that the Contact records (which represent portal users, together with User records) are associated with an Account record. Well this association is established in the createPortalUser() call. So for this code to work, you need to find a valid account ID, and ensure that the account owner is in the role hierarchy.

Here's an easy way to do this for our demo purposes on a Developer Edition environment:

  • Select the Sales application from the top right hand side drop down
  • Click on the Accounts tab
  • Select any account. Grab the ID from the URL (eg. 0018000000M4nqV) and paste this in to your code (or the default SiteRegisterController code) as the PORTAL_ACCOUNT_ID
  • Select the same account again, and click through to the Account Owner. You'll be directed to a User record for the owner of the account. Now modify the Role field, assigning it a role (any one will do for this demo) and save.

That's it. By doing this you found the ID of an account that will be associated with all new portal users Contact records, and you ensured that the owner of the account is in a role hierarchy. This role hierarchy gives you more control over the security aspects of the Contacts, which we won't cover in this tutorial.

You can find the complete code for the standard Visualforce page and controller here.

Once the customer portal user is created in this manner, the method returns the id of the new user. If the user ID is not null then we know we have created a new user and we can now proceed with the login process. The login process looks something like this:

 if (userId != null) { 
 if (password != null && password.length() > 1) {
 return Site.login(username, password, null);
 }
 else {
 PageReference page = System.Page.SiteRegisterConfirm;
 page.setRedirect(true);
 return page;
 }
 }

That's it!

Summary

That's the end of the process. Now your guest user is authenticated as a Portal user and you can begin to take them into your site and into your Visualforce application just as you would with a normal user. As an authenticated user they now enjoy the full security privileges that you assigned to that portal user profile; you can share data and business processes with these users by building out your Visualforce application and navigating the authenticated users through those pages.

The portal user session stays alive for the same duration as your normal session does in Salesforce and is controlled by the security settings you have for normal user logins. All of this session management, security, cookies, etc. is the same as a normal platform user, which means you don't have to worry about security, or write any code. See An Overview of Force.com Security for more information.

In a normal Force.com site you would typically have a public set of pages and a login link on the main page, the login link would go the form we discussed above, then into some page of the Force.com application that you have written which is for registered users only. If a guest user attempts to navigate to these pages they would see the Authorization Required page specified in your Sites setup.

Best Practices

Here are a few best practices:

  • Use Portal Authentication - The first best practice that I'd like to mention is to always use portal authentication process when you are tracking users on your site if they will interact with private data. If you're building a private shopping cart you should use customer portal authentication; if you are building a personalization engine that must be secure you should use customer portal authentication.
  • Use Custom Objects for Guest applications - If you would like to invite guests on your site to fill out a form providing information that you have requested you should consider storing that data in custom objects rather than standard objects because you will have full control of the permissions on those objects.
  • Do not prompt for a user or password - You should not prompt the guest user for a username and password and then store that information inside the system. This would be the equivalent of writing your own authentication system and is not in keeping with the terms and conditions for using Force.com.
  • Build Lightweight processes if possible - Use unauthenticated users if your use case allows. Let's say you would like to invite contacts to give you feedback, but do not want to enroll them in a customer portal? You can use an invitation code and send this code to contacts in your database allowing them to update information in a custom object. This is a lightweight process, and it does not involve authentication or portal licenses. The technique for creating an invitation code is described in a blog post, and a Code Share Project on Developer Force.

Finally, if your need is to track an individual user for a browser session you may be able to construct a tracking identifier and direct the user's browser to hold this parameter in a query string. This technique would allow you to match a user session to a custom object, say holding shopping cart contents or bread crumbs for the user.

References