❏ Users should be able to register and login with a Phone number (they don't have an email and don't use it)
- Assigned to
-
Xoliswa S.
- Notes
-
https://help.okta.com/oie/en-us/content/topics/identity-engine/authenticators/configure-phone.htm#:~:text=End%2Duser%20experience,and%20enter%20a%20phone%20number
we will need to make it possible for users to login without an email address and use a phone number only - it is a requirement for this project as some users do not have or understand emails
Xoliswa
heads up - I will give more details on another channel
Ian
I'll explain how to modify the code to handle account creation with just a phone number in Okta and WordPress. This requires additional handling since WordPress traditionally requires email addresses for accounts.
```php
<?php
/**
* Plugin Name: Okta Authentication with Email/Phone
* Description: Enables Okta authentication with email or phone number sign-in options
*/
// Previous code remains the same until add_registration_options()
class OktaEmailPhoneAuth {
// ... previous properties ...
private $phone_meta_key = 'okta_phone_number';
private $generated_email_domain = 'phone-user.example.com'; // Change this to your domain
public function __construct() {
// ... previous constructor code ...
// Add registration handling
add_action('register_post', array($this, 'validate_registration'), 10, 3);
add_action('user_register', array($this, 'handle_user_registration'));
add_filter('pre_user_login', array($this, 'modify_username_for_phone'));
}
public function add_registration_options() {
?>
<div class="okta-registration-options">
<div class="registration-type">
<input type="radio" name="registration_type" id="email_registration" value="email" checked>
<label for="email_registration">Register with Email</label>
</div>
<div class="registration-type">
<input type="radio" name="registration_type" id="phone_registration" value="phone">
<label for="phone_registration">Register with Phone Number</label>
</div>
<div id="email_fields">
<p>
<label for="user_email">Email Address</label>
<input type="email" name="user_email" id="user_email">
</p>
</div>
<div id="phone_fields" style="display: none;">
<p>
<label for="phone_number">Phone Number</label>
<input type="tel" name="phone_number" id="phone_number"
pattern="[0-9]{10,15}" title="Please enter a valid phone number">
</p>
</div>
</div>
<?php
}
public function validate_registration($login, $email, $errors) {
$registration_type = $_POST['registration_type'] ?? 'email';
$phone_number = $_POST['phone_number'] ?? '';
if ($registration_type === 'phone') {
// Clear email-related errors since we're registering with phone
$errors->remove('empty_email');
$errors->remove('invalid_email');
// Validate phone number
if (empty($phone_number)) {
$errors->add('empty_phone', 'Please enter a phone number.');
} elseif (!preg_match('/^[0-9]{10,15}$/', $phone_number)) {
$errors->add('invalid_phone', 'Please enter a valid phone number.');
}
// Check if phone number is already registered
if ($this->is_phone_number_registered($phone_number)) {
$errors->add('phone_exists', 'This phone number is already registered.');
}
}
return $errors;
}
public function handle_user_registration($user_id) {
$registration_type = $_POST['registration_type'] ?? 'email';
if ($registration_type === 'phone') {
$phone_number = sanitize_text_field($_POST['phone_number']);
// Store phone number in user meta
update_user_meta($user_id, $this->phone_meta_key, $phone_number);
// Create Okta user with phone number
$this->create_okta_user_with_phone($user_id, $phone_number);
}
}
private function create_okta_user_with_phone($user_id, $phone_number) {
// Generate a unique identifier for the user
$username = 'phone_' . preg_replace('/[^0-9]/', '', $phone_number);
$generated_email = $username . '@' . $this->generated_email_domain;
// Prepare user data for Okta
$user_data = array(
'profile' => array(
'firstName' => 'Phone',
'lastName' => 'User',
'email' => $generated_email,
'login' => $username,
'mobilePhone' => $phone_number,
'primaryPhone' => $phone_number,
),
'credentials' => array(
'password' => array(
'value' => wp_generate_password(24, true, true)
)
)
);
// Create user in Okta
$response = wp_remote_post("{$this->okta_domain}/api/v1/users", array(
'headers' => array(
'Authorization' => 'SSWS ' . $this->client_secret,
'Content-Type' => 'application/json'
),
'body' => json_encode($user_data)
));
if (is_wp_error($response)) {
error_log('Okta user creation failed: ' . $response->get_error_message());
return false;
}
// Get Okta user ID from response
$okta_user = json_decode(wp_remote_retrieve_body($response));
if (isset($okta_user->id)) {
// Store Okta user ID in WordPress user meta
update_user_meta($user_id, 'okta_user_id', $okta_user->id);
// Enroll phone factor
$this->enroll_phone_factor($okta_user->id, $phone_number);
}
return true;
}
private function enroll_phone_factor($okta_user_id, $phone_number) {
$factors_api_url = "{$this->okta_domain}/api/v1/users/{$okta_user_id}/factors";
$factor_data = array(
'factorType' => 'sms',
'provider' => 'OKTA',
'profile' => array(
'phoneNumber' => $phone_number
)
);
$response = wp_remote_post($factors_api_url, array(
'headers' => array(
'Authorization' => 'SSWS ' . $this->client_secret,
'Content-Type' => 'application/json'
),
'body' => json_encode($factor_data)
));
if (is_wp_error($response)) {
error_log('Failed to enroll phone factor: ' . $response->get_error_message());
return false;
}
return true;
}
private function is_phone_number_registered($phone_number) {
global $wpdb;
$exists = $wpdb->get_var($wpdb->prepare(
"SELECT user_id FROM {$wpdb->usermeta}
WHERE meta_key = %s AND meta_value = %s LIMIT 1",
$this->phone_meta_key,
$phone_number
));
return !empty($exists);
}
public function modify_username_for_phone($username) {
if (isset($_POST['registration_type']) && $_POST['registration_type'] === 'phone') {
$phone_number = $_POST['phone_number'];
return 'phone_' . preg_replace('/[^0-9]/', '', $phone_number);
}
return $username;
}
}
// Initialize the plugin
new OktaEmailPhoneAuth();
```
Here's how the phone-only registration process works:
1. **User Registration Flow**:
- User selects "Register with Phone Number" option
- Enters their phone number
- The system validates the phone number format and uniqueness
2. **Account Creation Process**:
- When registering with phone only:
- Generates a unique username based on the phone number (e.g., "phone_1234567890")
- Creates a synthetic email address using the configured domain (e.g., "phone_1234567890@phone-user.example.com")
- Stores the phone number in WordPress user meta
- Creates the user in both WordPress and Okta
3. **Okta Integration**:
- Creates an Okta user with:
- Generated username and email
- Phone number stored in both mobilePhone and primaryPhone fields
- Random secure password (since login will be via phone)
- Enrolls the SMS factor for the user automatically
4. **Security Considerations**:
- Validates phone number format and uniqueness
- Stores phone numbers securely in user meta
- Maintains mapping between WordPress and Okta user IDs
- Uses secure communication with Okta API
To implement this:
1. Update your Okta application settings to allow phone number authentication:
```json
{
"settings": {
"factors": {
"sms": {
"enabled": true,
"priority": 1
}
}
}
}
```
2. Add JavaScript to handle the registration form:
```javascript
jQuery(document).ready(function($) {
$('input[name="registration_type"]').on('change', function() {
if ($(this).val() === 'phone') {
$('#email_fields').hide();
$('#phone_fields').show();
} else {
$('#email_fields').show();
$('#phone_fields').hide();
}
});
});
```
3. Change the `generated_email_domain` in the code to match your domain.
The key points to understand:
1. WordPress requires an email address for accounts, so we generate a synthetic one
2. The actual authentication is done via phone number using Okta's SMS factor
3. The user never sees or needs to know the generated email address
4. The phone number becomes the primary identifier for the user
Approach after user signup wordpress user creation with phone number as main login if user email address not present
Approach tried to make phone number main authentication. SA not allowed, will research into requirements.
Notes:
- Log in via Okta using mobile number/email
Okta:
User Mapping for Okta attributes ( phone number) properly mapped to the WordPress user fields.
Created auth0 application : dev-et8c2fihsqi5011w.us.auth0.com
Created Twilio Wordworks account for credentials and sms integration
Configured sms on auth0:
Login setup but currently troubleshooting the login page redirect showing as 404:
Login page with phone number has been successfully configured.
Authentication issues at the moment so I am troubleshooting the errors coming in through the logs
Admin settings on staging:
Issue requires resolution:
- Styling
- Login page has reset to default and not displaying as on the Auth0 application.
Register Creates user in wordpress admin, the redirect to the login form does not display the correct form as on the application, investigated the issue but the form seems to be the default
https://wordworks.storiesandscience.co.za/register
https://wordworks.storiesandscience.co.za/phone-login/