I'm trying to set up Facebook SSO for a Salesforce customer community, and keep running into this error:
This is the url of the error: https://volunteer.madd.org/_nc_external/identity/sso/ui/AuthorizationError?ErrorCode=NO_ACCESS&ErrorDescription=Unable+to+find+a+user&ProviderId=0SO0G0000008OLi&startURL=%2Fs%2F#=
The customer community does not allow users to self-register, so I've created a customer community user with the same name and email address as the Facebook account, so I'm not clear why the user can't be found.
Here is the SSO handler code I have:
global class SocialRegHandler implements Auth.RegistrationHandler{
private static final String ORG_SUFFIX = '.sso.badge.org';
public static final String DEFAULT_ACCOUNTNAME = 'MADD';
public String communityId = Network.getNetworkId();
global boolean canCreateUser(Auth.UserData data) {
System.debug('canCreateUser was called for ' + (data != null ? data.email : 'null'));
Boolean retVal = (data != null
&& data.email != null
&& data.lastName != null
&& data.firstName != null);
System.debug('data.username='+data.username);
System.debug('data.email='+data.email);
System.debug('data.lastName='+data.lastName);
System.debug('data.firstName='+data.firstName);
return retVal;
}
global User createUser(Id portalId, Auth.UserData data){
if(!canCreateUser(data)) {
if(data.email != null){
User u = [Select Id , username from User where email =: data.email];
return u;
} else {
return null;
}
}
// Is this a Community Context?
if(data.attributeMap.containsKey(communityId)) {
System.debug('Registering Community user: ' + data.email);
// To keep things modular, we're creating the PersonAccount in a separate method
// Id contactId = createPersonAccountContact(data);
Contact c = new Contact();
c.LastName = data.lastName;
c.FirstName = data.FirstName;
c.Email = data.email;
insert c;
// You'd likely use other logic to assign the Profile
Profile p = [SELECT Id FROM profile WHERE name='MADD Customer Community User'];
// Keeping it modular, we initialize the user in another method
User u = createUser(data,p);
u.contactId = c.id;
return u;
} else {
//This is not a community, so we Assign an internal profile
Profile p = [SELECT Id FROM profile WHERE name='Standard User'];
// Keeping it modular, we initialize the user in another method
User u = createUser(data,p);
return u;
}
}
global void updateUser(Id userId, Id portalId, Auth.UserData data){
System.debug('Update User called for: ' + data.email);
User u = new User(id=userId);
u.email = data.email;
u.lastName = data.lastName;
u.firstName = data.firstName;
update(u);
}
private Id createPersonAccountContact(Auth.UserData data) {
Account person = new Account();
person.LastName = data.lastName;
person.FirstName = data.FirstName;
person.personEmail = data.email;
person.RecordTypeId = [Select Id From RecordType
Where SobjectType='Account'
AND isPersonType=true LIMIT 1].id;
insert person;
System.debug('Person Account created for ' + data.email + ' id=' + person.id);
/**
* This next step is necessary to get a valid contact Id,
* it won't exist until the PersonAcct is saved
Account a = [Select PersonContactId From Account Where Id = :person.Id];
return a.PersonContactId;
}
**/
/**
* Create and initialize the User but don't save it yet
*
* @param data - the provided User context from FaceBook
* @param p - the Profile we are going to assign to this user
*
* @return User that has been initialized but not Saved
**/
private User createUser(Auth.UserData data, Profile p) {
User u = new User();
u.username = data.email + ORG_SUFFIX;
u.email = data.email;
u.lastName = data.lastName;
u.firstName = data.firstName;
String alias = data.firstName + data.lastName;
//Alias must be 8 characters or less
if(alias.length() > 8) {
alias = alias.substring(0, 8);
}
u.alias = alias;
u.languagelocalekey = UserInfo.getLocale();
u.localesidkey = UserInfo.getLocale();
u.emailEncodingKey = 'UTF-8';
u.timeZoneSidKey = 'America/Los_Angeles';
u.profileId = p.Id;
return u;
}
}
And here are the settings of the Facebook app:
I've reviewed all the documentation and related posts I could find, and I'm still left with a few questions:
- Is there anything in the above code I need to change in order to make the SSO work with a community? Or is there any reason it wouldn't be able to find a user with the same email address?
- Does the website URL on the Facebook app need to be the community login page (www.community.com/login) or the existing user linking url with the community url as a string append (https://login.salesforce.com/services/auth/link/00DF00000006xCGMAY/Facebook?community=http%3A%2F%2Fwww.community.com)?
- Do I need to configure SAML Single Sign-On to enable SSO for a community?