Add 2-Factor Authentication in 10 min to your Laravel PHP App

Implementing Laravel 2 Factor Authentication

Implementing TypingDNA with Laravel is easy. Just follow these 5 simple steps:

  1. Laravel Setup

  2. TypingDNA Verify Setup

  3. Laravel Backend

  4. Laravel Frontend

  5. Verification Process

Laravel Setup

For more information about Laravel please follow this Laravel Tutorial: The ultimate guide 2021.

Let’s get started by creating our first laravel project using the following command:

composer create-project laravel/laravel typingdna-verify-2fa

Navigate to the typingdna-verify-2fa directory and start your development server.

cd typingdna-verify-2fa && php artisan serve

You can now test your setup by accessing link:

Implement Laravel Second Factor of Authentication

Next we will set up the TypingDNA Verify settings.

  1. Create an account on The Verify 2FA dashboard will provide you with the clientID, secret and applicationID.

  2. Setup ngrok. Ngrok creates a public url that will link to your localhost environment. For security purposes, TypingDNA Verify 2FA will only run on a public url. Ngrok can be downloaded from the following link:

Navigate to the folder where you have downloaded ngrok and run the command:

ngrok.exe http 8000

A bridge will be created that will forward to our localhost.

Now we can test that our solution runs by running the ngrok link, in our case: (make sure to always use the https version).

Laravel Backend

Now we will set up the backend of TypingDNA Verify. We will navigate to the app folder and create another folder called “Services”. Inside we will create the TypingDNA.php file.

We will create our first function getDataAtributes that will help us generate the TypingDNA Verify button.

public function getDataAttributes() {
    $typingDNAVerifyClient = new TypingDNAVerifyClient(env('TYPINGDNA_CLIENID'), env('TYPINGDNA_APPID'), env('TYPINGDNA_SECRET'));
    $typingDNADataAttributes = $typingDNAVerifyClient->getDataAttributes([
        "email" => env('TYPINGDNA_EMAIL'),
        "language" => "EN",
        "flow" => "STANDARD",
    return  $typingDNADataAttributes;

We will set up the private and public keys in the .env environment.

Make sure to add in in the App\Services folder the file TypingDNAVerifyClient.php that can be found in our repository:

To generate the ApplicationID navigate to the Verify 2FA settings and add a new integration:

Now that we have generated the function that will generate the button we need to validate if the OTP that we receive back is correct.

public function getResult($otp) {

    $typingDNAVerifyClient = new TypingDNAVerifyClient(env('TYPINGDNA_CLIENID'), env('TYPINGDNA_APPID'), env('TYPINGDNA_SECRET'));

    $response = $typingDNAVerifyClient->validateOTP([
        'email' =>env('TYPINGDNA_EMAIL'),
    ], $otp);

    if ($response['success'] == 1)
        return "Authentication Successful";
        return "Authentication Failed";

Laravel Frontend

Next, we will add the TypingDNA Verify 2FA button on our frontend. We will use the dashboard for the simplicity of the implementation.

First we will import the following javascript in order to generate the TypingDNA Verify pop-up. We will place it under the head tag:

<script src = ""></script>            

Next we will add the TypingDNA Verify button that will use the attributes that we will generate in the backend.

    class = 'typingDNA-verify'
    data-typingdna-client-id='{{ $clientId }}'
    data-typingdna-application-id='{{ $applicationId }}'
    data-typingdna-payload='{{ $payload }}'
    data-typingdna-callback-fn= 'callbackFn'> Verify with TypingDNA

The button will call a callback function once the process is completed. This function will also contain the OTP generated.

We will handle this function by redirecting the user to another page with the OTP as one of the parameters. We will do with the following javascript function that we will add in the header.

    function callbackFn({otp}) {
        window.location.href = `/result?otp=${otp}`;

Next we will create the result page:

Under routes/web.php we will add the following code that will read the OTP parameter.

Route::get('/', function () {
    return view('welcome', [ 'clientId' => app('App\Services\TypingDNA')->getDataAttributes()['clientId'],
    'applicationId' => app('App\Services\TypingDNA')->getDataAttributes()['applicationId'],
    'payload' => app('App\Services\TypingDNA')->getDataAttributes()['payload']]  );
Route::get('/result', function(Request $request) {
    $otp = $request->input('otp');
    return view('result', ['result' => app('App\Services\TypingDNA')->getResult($otp) ]);

We will create a copy of the welcome.blade.php and rename it to result.blade.php.

Replace the code of the button with the following code that will print if the authentication is successful or not:

{{ $result }}

Verification Process

Let’s test our application:

Access your ngrok link:

Select the button and type the 4 words that are presented on the screen:

Next you will be redirected to the result page with the success message:

If you have more questions about TypingDNA Verify 2FA feel free to contact us at

Tell your team there’s a better way to 2FA

Share this message across Slack, email, etc. We even jotted down some of the highlights to make it easier.

Check this out! 🚀 Found a cool way to 2FA our users: TypingDNA Verify 2FA. It authenticates people based on how they type — replacing authenticator apps and OTP codes. Awesome user experience! 🙌 Quick integration too (under 10 mins). And we can try it free with 1,000 users. What do you think?