Newer Version Available
ConfigurableSelfRegHandler Interface
Namespace
Usage
You set up community self-registration declaratively on the Login & Registration (L&R) page of the Administration workspace. When combined with a configurable self-registration setup, the handler class can programmatically fill in user fields, including custom fields, and determine how to create a user and log them in.
When you select the Configurable Self-Reg Page registration page, you choose the user fields to collect from the self-registration form, such as last name, first name, username, nickname, mobile, or email. You also determine the verification method that the user identifies themselves with, which can be email, mobile, or neither. Salesforce generates the Auth.ConfigurableSelfRegHandler handler, which contains logic on how to create a community member. Modify the handler to change how users are created, and how collected user information is used.
You might want to add custom logic to ensure that the email or phone number is unique to the external user who's registering. For example, you can add a custom unique field, and write a copy of the email or phone number to it. You can also change how the user is created. By default, the user is created as a contact associated with the account that you select on the L&R page.
The generated ConfigurableSelfRegHandler is located on the Setup Apex Classes page, and begins with AutocreatedConfigSelfReg, for example, AutocreatedConfigSelfReg1532475901849.
For an example, see ConfigurableSelfRegHandler Example Implementation. For more details, see Salesforce External Identity Implementation Guide.
ConfigurableSelfRegHandler Method
The following is the method for ConfigurableSelfRegHandler.
createUser(accountId, profileId, registrationAttributes, password)
Signature
public Id createUser(Id accountId, Id profileId, Map<Schema.SObjectField,String> registrationAttributes, String password)
Parameters
- accountId
- Type: Id
- Default account with which the new user is associated. This value comes from the Account field setting on Login and Registration (L&R) page under Registration Page Configuration.
- profileID
- Type: Id
- Profile to assign the new user. This value comes from the Profile field setting on the L&R page under Registration Page Configuration.
- registrationAttributes
- Type: Map<Schema.sObjectField,String>
- A map of attributes that the registering user entered on the self-registration page. The fields that appear on the self-registration page come from the User Fields selected on the L&R page when the registration type is Configurable Self-Reg Page.
- password
- Type: String
- The password entered by the user if “Include Password” is selected on the L&R page. (If a password isn’t entered, the handler must generate one because a password is required to create a user.)
Return Value
Type: Id
Returns an identifier for the created User object. Auth.ConfigurableSelfRegHandler inserts a user and then returns the ID of that user.
ConfigurableSelfRegHandler Example Implementation
Verification occurs by email if the admin chose Email as the verification method when setting up the Configurable Self-Reg handler on the Login & Registration (L&R) page. When a visitor clicks the sign-up link from the login page, Salesforce prompts for an email address and then sends a one-time password to the specified email address. If the visitor enters the verification code successfully on the verify page, the user is created and logged in. Likewise, if the admin chose Text Message as the verification method on the L&R page, the visitor is prompted to enter a phone number. Salesforce sends a challenge (verification code) via SMS to the user. If successful, the user is created and logged in. Requiring verification before creating a user reduces the number of dummy users cluttering your org.
The Auth.ConfigurableSelfRegHandler class contains logic for generating the user fields required to create a user in case the user doesn’t supply them. The handler generates default values, ensuring that the values are unique by appending a timestamp. You can modify the handler to make sure that the email address and phone number of the external user are also unique.
1global class AutocreatedConfigSelfReg implements Auth.ConfigurableSelfRegHandler {
2
3 private final Long CURRENT_TIME = Datetime.now().getTime();
4 private final String[] UPPERCASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
5 private final String[] LOWERCASE_CHARS = 'abcdefghijklmnopqrstuvwxyz'.split('');
6 private final String[] NUMBER_CHARS = '1234567890'.split('');
7 private final String[] SPECIAL_CHARS = '!#$%-_=+<>'.split('');
8
9 // This method is called once after verification (if any was configured).
10 // This method should create a user and insert it.
11 // Password can be null.
12 // Return null or throw an exception to fail creation.
13 global Id createUser(Id accountId, Id profileId, Map<SObjectField, String> registrationAttributes, String password) {
14 User u = new User();
15 u.ProfileId = profileId;
16 for (SObjectField field : registrationAttributes.keySet()) {
17 String value = registrationAttributes.get(field);
18 u.put(field, value);
19 }
20
21 u = handleUnsetRequiredFields(u);
22 generateContact(u, accountId);
23 if (String.isBlank(password)) {
24 password = generateRandomPassword();
25 }
26 Site.validatePassword(u, password, password);
27 if (u.contactId == null) {
28 return Site.createExternalUser(u, accountId, password);
29 }
30 u.languagelocalekey = UserInfo.getLocale();
31 u.localesidkey = UserInfo.getLocale();
32 u.emailEncodingKey = 'UTF-8';
33 u.timeZoneSidKey = UserInfo.getTimezone().getID();
34 insert u;
35 System.setPassword(u.Id, password);
36 return u.id;
37 }
38 // Method to autogenerate a password if one isn't passed in.
39 // By setting a password for a user, we won't send a
40 // welcome email to set the password.
41 private String generateRandomPassword() {
42 String[] characters = new List<String>(UPPERCASE_CHARS);
43 characters.addAll(LOWERCASE_CHARS);
44 characters.addAll(NUMBER_CHARS);
45 characters.addAll(SPECIAL_CHARS);
46 String newPassword = '';
47 Boolean needsUpper = true, needsLower = true, needsNumber = true, needsSpecial = true;
48 while (newPassword.length() < 50) {
49 Integer randomInt = generateRandomInt(characters.size());
50 String c = characters[randomInt];
51 if (needsUpper && c.isAllUpperCase()) {
52 needsUpper = false;
53 } else if (needsLower && c.isAllLowerCase()) {
54 needsLower = false;
55 } else if (needsNumber && c.isNumeric()) {
56 needsNumber = false;
57 } else if (needsSpecial && !c.isAlphanumeric()) {
58 needsSpecial = false;
59 }
60 newPassword += c;
61 }
62 newPassword = addMissingPasswordRequirements(newPassword, needsLower, needsUpper, needsNumber, needsSpecial);
63 return newPassword;
64 }
65
66 private String addMissingPasswordRequirements(String password, Boolean addLowerCase, Boolean addUpperCase, Boolean addNumber, Boolean addSpecial) {
67 if (addLowerCase) {
68 password += LOWERCASE_CHARS[generateRandomInt(LOWERCASE_CHARS.size())];
69 }
70 if (addUpperCase) {
71 password += UPPERCASE_CHARS[generateRandomInt(UPPERCASE_CHARS.size())];
72 }
73 if (addNumber) {
74 password += NUMBER_CHARS[generateRandomInt(NUMBER_CHARS.size())];
75 }
76 if (addSpecial) {
77 password += SPECIAL_CHARS[generateRandomInt(SPECIAL_CHARS.size())];
78 }
79 return password;
80 }
81 // Generates a random number from 0 up to, but not including, max.
82 private Integer generateRandomInt(Integer max) {
83 return Math.mod(Math.abs(Crypto.getRandomInteger()), max);
84 }
85
86 // Loops over required fields that were not passed in to
87 // set to some default value.
88 private User handleUnsetRequiredFields(User u) {
89 if (String.isBlank(u.LastName)){
90 u.LastName = generateLastName();
91 }
92 if (String.isBlank(u.Username)) {
93 u.Username = generateUsername();
94 }
95 if (String.isBlank(u.Email)) {
96 u.Email = generateEmail();
97 }
98 if (String.isBlank(u.Alias)) {
99 u.Alias = generateAlias();
100 }
101 if (String.isBlank(u.CommunityNickname)) {
102 u.CommunityNickname = generateCommunityNickname();
103 }
104 return u;
105 }
106 // Method to construct a contact for a user.
107 private void generateContact(User u, Id accountId) {
108 // Add logic here if you want to build your own
109 // contact for the use.
110 }
111 // Default implementation to try to provide uniqueness.
112 private String generateAlias() {
113 String timeString = String.valueOf(CURRENT_TIME);
114 return timeString.substring(timeString.length() - 8);
115 }
116 // Default implementation to try to provide uniqueness.
117 private String generateLastName() {
118 return 'ExternalUser' + CURRENT_TIME;
119 }
120 // Default implementation to try to provide uniqueness.
121 private String generateUsername() {
122 return 'externaluser' + CURRENT_TIME + '@company.com';
123 }
124 // Default implementation to try to provide uniqueness.
125 private String generateEmail() {
126 return 'externaluser' + CURRENT_TIME + '@company.com';
127 }
128 // Default implementation to try to provide uniqueness.
129 private String generateCommunityNickname() {
130 return 'ExternalUser' + CURRENT_TIME;
131 }
132}