To avoid, really just reduce, instances where a person will login to our external site utilizing the Passwordless login block, introduced in v15, with multiple person records attached to their phone number, we took a 2 prong approach:

1.      Prompt users to validate their contact information and “validate” their phone number.

2.      Create an Job that fires workflows to clean up the duplicate phone numbers every night

The goal is to keep clean data, but also to promote a safer environment for our users & our data. While our approach makes some assumptions about the “owner” of the phone numbers, this is all adjustable & configurable to your specific organization & requirements. Some of the assumptions we make may come back to bite us, but our hope is that the assumptions we make are thought out & the safest ones we can make.

In this Recipe I’m only explaining the process & providing the supporting documents & workflow imports at the bottom of this Recipe. This recipe would get to be really long if I walked through all of the steps, but I’m happy to answer any questions y’all have in the comments below or in RocketChat.

So now with way too much ado… let’s get going!


Process Preparations

To follow along with our process, you’ll need to create 2 person attributes & install 2 plugins:

               Contact Information Validation:

-        Contact Info Updated Date: This will store the date when the user last updated/confirmed their information.

-        Contact Info Update – Delay: This will store the date when the person last skipped validating their information.

Duplicate Phone Number Removal:

-        South East Chistian’s - Workflow Launcher

-        Blue Box Moon’s - Workflow Stimpack


Contact Information Validation

In addition to being a tongue twister, Contact Information Validation, is our first line of defense. We’re hoping that users will do some of our work for us. I don’t know about your users, but our users love to update & correct their own data… sometimes too much, so an assumption we’re making is that users will interact with our “pop-up” correction form. In the form we show their data give them multiple “outs” so their not trapped, and try to make the process easy & simple. Here’s our process & how we built it.

The process starts by evaluating the two person attributes we created in the preparation step. We have our process setup so if 4 months have passed since the user validated their information it’s been 7 or more days since they skipped this process, we redirect  their traffic to the form & passing the original destination URL into the workflow for later on in the process. The workflow starts by presenting the Current Person’s data to them & asking if they’d like to Update Info, Confirm the Info, or Skip. I’ll give a brief overview of all the paths, but will start with the shortest & end with the longest.


Upon confirmation of the data, the user is then sent on their way to their original destination. The workflow then in the background updates their Information Confirmation person attribute. (In the near future we’re going to ask these people to validate their number, but in this initial deployed version we’re just moving them on.)


When the user clicks skip they’re moved on their way to the original destination. This process is actually a bit more involved than just a redirect, we actually launch a separate workflow which handles the redirect & updates the Skip Information Confirmation person attribute & then also redirects them.
We created a separate workflow that’s launched when the user clicks skip because we wanted the skip in the top right corner of the page & it’s the easiest way to accomplish that.


This is where the “magic” of this workflow lives. We get going by showing the user editable fields to update their phone and email address, (If they have an email address that contains “” which is our email domain, we route them to a different form that explains they can’t change their email & allow them to update their phone number) Once they’ve completed updating their information we check their phone number to evaluate if the number they entered is anywhere in the PhoneNumber table, if it exists we take them to  the number validation step where we generate a randomized 6 character code, once they validate their number the path is the same as if their number wasn’t updated. After number validation or if their number didn’t require validation according to our process, the data is updated & the user to sent on their way to the original destination.


There’s a few changes I’d like to make, but I currently do not have the time to implement these changes.

-        I’d like to ask the user to validate their number if they confirm the data in step 1, if the number is found more than once in the PhoneNumber table.

-        Upon updating their information, if they don’t change their phone number, I’d like to ask them to validate their number, if there’s a duplicate in the database.

These aren’t hard to do, but require a little bit of reworking this process, since I built it to be as unintrusive as possible, but we’ve since realized we can ask for validation & don’t need to force validation in a few instances.


Duplicate Phone Number Removal

This is where the assumptions start to get a bit risky, but we’ve made the safest ones we can think of. We start by having a job, which I’ll explain at the end of this section, that finds any phone number occurring more than once in the PhoneNumber table & creates a single row for each phone number ordered from oldest to newest. We capture the Phone Number & the Person Id for each of the duplicate numbers. Once created, each row is then passed into a workflow that takes the string & pops the first person off the string. The workflow then passes the remaining string to a Blue Box Moon “For Each” action from the Workflow Stimpack. It splits the remaining Person Id & Number & an Activity is launched for each. The Activity removes the number from the account utilizing the Core Phone Number Update action, to set each instance of the number to ‘Null’. We leave a note on each person that is updated indicating when this change occurred & who is the “owner” of the number.

The job that initiates this whole process is where some of the magic happens. The job is the “Workflow Launch” job type that’s installed from the South East Christian “Workflow Launcher” plug-in. I have it set to run each morning at 1am, it’s utilizing the following SQL Query:

SELECT STRING_AGG(CONCAT(sub1.[PersonId],':',sub1.[NumberTypeValueId]),',') as RawNumberString
SELECT top 1000000 n.*
FROM [PhoneNumber] n
INNER JOIN [Person] p on p.[Id]=n.[PersonId]
ORDER BY n.CreatedDateTime ASC,p.AgeClassification ASC
GROUP BY sub1.[NumberFormatted]
HAVING COUNT(sub1.[NumberFormatted]) > 1

While this section is shorter than the previous, it’s the one that should give you pause & make you think through if this is the right move for your Organization. We’ve evaluated the risks & have deemed them acceptable for the added security, but it might not be the case for your Organiziation. One of the major issues that could arise is at Check-In. If a number gets disassociated from an account, it could cause issues where a family won’t show up if the number is removed. We’ve looked over our data in some quick spot checking & didn’t see any cases where this would happen, but we’re prepared for some instances of it. Before taking this step I highly recommend talking with your teams & staff to make them aware of some changes that may cause issues. We messaged it as “security updates” may cause some changes to phone numbers, since we’re removing duplicate phone numbers.




This process was the right one for us… or at least we hope it is. It might not be perfect for your organization, but hopefully it’s helpful in getting you thinking through ways to improve your Passwordless logins!

Again, if you have any questions please feel free to comment under this recipe or message me in RocketChat! I’m always happy to help.


Shared Assets & Files: