Modify 2FA registration forms
Hosted Login v2 introduces a new way of managing the login and registration workflow: although a “regular” flow is still required for configuration purposes, a separate Akamai-managed flow determines such things as when a given screen appears and, if you’re using two-factor authentication, when and how access codes are sent to users.
As a general rule this new system works flawlessly. In fact, there’s really only one spot where your regular flow and the Akamai flow conflict. By default, users who create a new account are sent an email that asks them to verify their email address; this behavior is coded into the workflows for both social registration (the socialRegistrationForm form) and traditional registration (the traditionalRegistrationForm form). In other words, when you create an account one of those two forms automatically sends an email similar to this:
If you’re running Hosted Login v2 but you aren't using two-factor authentication that’s great: after all, this is how users verify their email address. However, if you are* using two-factor authentication the default registration experience is perhaps a little less than ideal. Why? Well, with two-factor authentication the user is sent an email similar to the one just shown. The user can click that email and verify their email address. At the same time, however, the user is also sent an access code and must enter this code before they can complete the registration process and log on:
Ultimately this all works but, for end users, it’s a little confusing, and a little frustrating: they need to verify their email address to complete registration and they need to enter an access code to complete registration. Needless to say, a better user experience would be not to send the click-here-to-verify-your-email-address email and, instead, simply ask users to enter their access code. That reduces confusion, frustration, and the number of steps a user must undertake in order to register.
And guess what? By modifying the properties of the socialRegistrationForm and the traditionalRegistrationForm forms (in your flow, not in the Akamai-managed flow), you can do just that.
Keep in mind that you should only modify these forms if you’re using Hosted Login 2 and two-factor authentication. Don’t make these changes if you’re running Hosted Login 1 or if you aren’t using two-factor authentication.
Modify the traditionalRegistrationForm form
Let's start by modifying the traditionalRegistrationForm form. To do that, use the /config/{appId}/flows/{flow}/forms/{form} operation and the GET method to return the current properties of the form. For example:
curl -X GET \
'https://v1.api.us.janrain.com/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/
traditionalRegistrationForm' \
-H 'Authorization: Basic eTR4Zmc2ZjQ0bXNhYzN2ZXBqanZ4Z2d6dnQzZTNzazk6OTVjY3hrN2N6YnZ1eng2ZHB0ZTV
rOXA2ZGo1Ynpla3U='
That brings back information about the traditionalRegistrationForm form:
{
"action": "traditionalRegistration",
"fields": [
{
"\_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/displayName",
"name": "displayName",
"required": true
},
{
"\_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/emailAddress",
"name": "emailAddress",
"required": true
},
{
"\_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/newPassword",
"name": "newPassword",
"required": true
},
{
"\_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/newPasswordConfirm",
"name": "newPasswordConfirm",
"required": false
}
],
"next": {
"if": {
"compare": "emailVerified",
"to": null,
"withOperator": "=="
},
"then": {
"sendMail": {
"mail": "registrationVerification"
}
},
"type": "server"
},
"\_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/traditionalRegistrationForm"
}
For the moment, these are the only lines we care about:
"next": {
"if": {
"compare": "emailVerified",
"to": null,
"withOperator": "=="
},
"then": {
"sendMail": {
"mail": "registrationVerification"
}
},
"type": "server"
},
Copy all the property and property values for the form (including the "only lines we care about"), and paste that information into the body parameter of a /config/{appId}/flows/{flow}/forms/{form} PUT operation . After that, remove the next property and its value ( the lines we care about). If you’re using Postman, your body parameter will look like this:
If you’re using curl, your API call should look similar to the following:
curl -X PUT \
'https://v1.api.us.janrain.com/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/
traditionalRegistrationForm' \
-H 'Authorization: Basic eTR4Zmc2ZjQ0bXNhYzN2ZXBqanZ4Z2d6dnQzZTNzazk6OTVjY3hrN2N6YnZ1eng2ZHB0ZTV
rOXA2ZGo1Ynpla3U=' \
-H 'Content-Type: application/json' \
--data-raw '{
"action": "traditionalRegistration",
"fields": [
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/displayName",
"name": "displayName",
"required": true
},
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/emailAddress",
"name": "emailAddress",
"required": true
},
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/newPassword",
"name": "newPassword",
"required": true
},
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/newPasswordConfirm",
"name": "newPasswordConfirm",
"required": false
}
],
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/traditionalRegistrationForm"
}'
When you’re ready, make your API call. If the call succeeds, you’ll again get back the following API response:
204 No Content
At this point you can use the GET method to verify that the next property has been removed from the form. After making the GET call you should see a response similar to this:
{
"action": "traditionalRegistration",
"fields": [
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/displayName",
"name": "displayName",
"required": true
},
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/emailAddress",
"name": "emailAddress",
"required": true
},
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/newPassword",
"name": "newPassword",
"required": true
},
{
"\self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/newPasswordConfirm",
"name": "newPasswordConfirm",
"required": false
}
],
"next": null,
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/traditionalRegistrationForm"
}
As you can see, the next property is set to null.
Modify the socialRegistrationForm form
You say you don't use social login in your website? In that case, there's no need to modify the socialRegistrationForm form. Just be sure to update this form if you ever do decide to use social login.
Now we need to modify the socialRegistrationForm form. To do that, we’ll start by using the GET method and the /config/{appId}/flows/{flow}/forms/{form} operation to return the current properties of the socialRegistrationForm form. That’s something we can do by running a curl command similar to this one:
curl -X GET \
'https://v1.api.us.janrain.com/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/
socialRegistrationForm' \
-H 'Authorization: Basic eTR4Zmc2ZjQ0bXNhYzN2ZXBqanZ4Z2d6dnQzZTNzazk6OTVjY3hrN2N6YnZ1eng2ZHB0ZT
VrOXA2ZGo1Ynpla3U='
That API call returns the current properties and property values for the socialRegistrationForm form:
{
"action": "socialRegistration",
"fields": [
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/displayName",
"name": "displayName",
"required": true
},
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/emailAddress",
"name": "emailAddress",
"required": true
}
],
"next": {
"else": {
"sendMail": {
"mail": "registrationConfirmation"
}
},
"if": {
"compare": "emailVerified",
"to": null,
"withOperator": "=="
},
"then": {
"sendMail": {
"mail": "registrationVerification"
}
},
"type": "server"
},
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/socialRegistrationForm"
}
And, just like we with our first form, we're really only interested in a handful of lines:
"next": {
"else": {
"sendMail": {
"mail": "registrationConfirmation"
}
},
"if": {
"compare": "emailVerified",
"to": null,
"withOperator": "=="
},
"then": {
"sendMail": {
"mail": "registrationVerification"
}
},
"type": "server"
},
The best way to remove those lines (which comprise the form’s next property) is to start by copying all the current properties and property values of the form. After those properties and values have been copied, paste the entire selection into the body parameter of a /config/{appId}/flows/{flow}/forms/{form} PUT call. After the properties and property values have been copied over, then go in and remove the next property and its value. For example, if you’re using Postman, that means that your body parameter will end up look something like this:
Yes, you can remove all instances of the _self property. But you don’t have to, so we took the easy way out and just left them in.
By extension, an API call using curl will look like this:
curl -X PUT \
'https://v1.api.us.janrain.com/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/
socialRegistrationForm' \
-H 'Authorization: Basic eTR4Zmc2ZjQ0bXNhYzN2ZXBqanZ4Z2d6dnQzZTNzazk6OTVjY3hrN2N6YnZ1eng2ZHB0ZTV
rOXA2ZGo1Ynpla3U=' \
-H 'Content-Type: application/json' \
--data-raw '{
"action": "socialRegistration",
"fields": [
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/displayName",
"name": "displayName",
"required": true
},
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/emailAddress",
"name": "emailAddress",
"required": true
}
],
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/socialRegistrationForm"
}'
If you run that API call and the call succeeds, you’ll get back the following response:
204 No Content
And if you rerun the GET command and check the up-to-date properties and property values of the socialRegistrationForm form you should see that the next property has been set to null:
{
"action": "socialRegistration",
"fields": [
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/displayName",
"name": "displayName",
"required": true
},
{
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/fields/emailAddress",
"name": "emailAddress",
"required": true
}
],
"next": null,
"_self": "/config/79y4mqf2rt3bxs378kw5479xdu/flows/moreJTL/forms/socialRegistrationForm"
}
Which is exactly what we want it set to.
Updated about 2 years ago