[SalesForce] Salesforce Auth Provider with Facebook SSO

After 3 and a half days of reading through documentation and trial and error, I have come to a point where I am just stuck trying to make it so Community Users and/or normal Users can log into a salesforce org by using their FaceBook login credentials.

Has anybody had success with this where they can help me out?

I thought I had set up the Auth Provider correctly in Salesforce as well a Registration Handler class and also an App in Facebook, but when I try and use it for a fictitious Facebook account that should be tied to a Community User license in Salesforce I get an error along the lines of:

There was a problem with your authentication attempt. Please try
again. If you continue to encounter problems, contact your
administrator.

I notice in the URL it has at the end "AuthorizationError?ErrorCode=NO_ACCESS&ErrorDescription=User+was+a+portal+user".

Something tells me I am missing something really simple, but I am running out of things to try.

Any help would be greatly appreciated!

EDIT: Here is the Registration Handler code:

public class PortalHandler implements Auth.RegistrationHandler
{
    // createUser is called when there is no existing user linked 
    // to the incoming third party account
    public User createUser(Id portalId, Auth.UserData data)
    {
        User u;

        // Use incoming email for username, since we're working with a 
        // portal user
        List<User> l = [SELECT Id,UserName,FirstName,LastName,Email FROM User WHERE UserName = :data.email];
        if (l.size() > 0) 
        {
            u = l[0];
            System.debug('Found existing user record for '+ data.firstName + ' ' + data.lastName + ' ' + data.email);
            System.debug(u.FirstName + ' ' + u.LastName + ' ' + u.Email);

            // Update existing record
            u.Email = data.email;
            u.LastName = data.lastName;
            u.FirstName = data.firstName;
            // Useful to save the Facebook ID in a custom field
            //u.Facebook_ID__c = data.identifier;

            System.debug('Updating user record for '+ data.firstName + ' ' + data.lastName + ' ' + data.email);
            System.debug(u.FirstName + ' ' + u.LastName + ' ' + u.Email);

            update(u);
        } 
        else 
        {
            // Portal users need an associated contact, which, in turn,
            // needs to be associated with an account.
            // For simplicity, just put all contacts on the sForce account
            Account a = [SELECT Id FROM Account WHERE Name='Chapter ABC'];

            Contact c = new Contact();
            c.AccountId = a.Id;
            c.Email = data.email;
            c.FirstName = data.firstName;
            c.LastName = data.lastName;
            insert(c);

            u = new User();
            Profile p = [SELECT Id FROM profile WHERE name='Customer Community User'];

            u.UserName = data.email;
            u.Email = data.email;
            u.LastName = data.lastName;
            u.FirstName = data.firstName;
            //u.Facebook_ID__c = data.identifier;
            u.Alias = (data.username != null) ? data.username : data.identifier;

            if (u.Alias.length() > 8) 
            {
                u.Alias = u.Alias.substring(0, 8);
            }

            u.Languagelocalekey = UserInfo.getLocale();
            u.Localesidkey = UserInfo.getLocale();
            u.EmailEncodingKey = 'UTF-8';
            u.TimeZoneSidKey = 'America/Los_Angeles';
            u.ProfileId = p.Id;
            u.ContactId = c.Id;

            System.debug('Returning new user record for '+ data.firstName + ' ' + data.lastName + ' ' + data.email);

        }

        return u;
    }

    // updateUser is called when there is a match with an existing user
    public void updateUser(Id userId, Id portalId, Auth.UserData data)
    {
        User u = new User(Id=userId);

        u.Email = data.email;
        u.LastName = data.lastName;
        u.FirstName = data.firstName;
        //u.Facebook_ID__c = data.identifier;

        System.debug('Updating user record for '+ data.firstName + ' ' + data.lastName + ' ' + data.email);

        update(u);
    }
}

Best Answer

Metadaddy is on the right track here. It's a bit nuanced, but here we go:

When logging into Salesforce you can really have multiple contexts. The default is logging into the Org. You do this from login.salesforce.com, your My Domain, or perhaps from an enterprise single sign-on service. Here's where you access apps like Sales, Service, or custom apps on Force.com

You can also invite external users into your org. Historically we called this a Portal - these days you do this through a Community. It's a space that external users (customers, partners, etc) can login to and collaborate and be delivered applications, but can have separate authentication and authorization config from the core Org, which is sort of...employee only.

The Auth Provider URL you're using is setup, by default, to target the internal org. So, when you use the SSO url on that page, it is trying to login to the Org, but since your Reg Handler creates a portal style user, they are blocked from logging in.

You can, of course, configure your Community to accept the Auth Provider. This is a simple checkbox on the login configuration for the community, and it will automatically put a button on your Community login page, handle StartUrls, etc.

If you need to build the Auth Provider URL yourself to test manually, it's pretty easy...you just need a special param. Here's an example:

https://login.salesforce.com/services/auth/sso/00D30000000000FOO/Facebook?community=http%3A%2F%2Fcustomerdemo.force.com&startURL=

You just need to add that community param with your URL, plus an optional start url. This will target the authentication to your community, instead of your org.

And once again, the Community login page does this for you automatically.

Hope that helps!

Related Topic