Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Top 10 Use Cases of Vibe Coding in Large-Scale Node.js Applications

      September 3, 2025

      Cloudsmith launches ML Model Registry to provide a single source of truth for AI models and datasets

      September 3, 2025

      Kong Acquires OpenMeter to Unlock AI and API Monetization for the Agentic Era

      September 3, 2025

      Microsoft Graph CLI to be retired

      September 2, 2025

      ‘Cronos: The New Dawn’ was by far my favorite experience at Gamescom 2025 — Bloober might have cooked an Xbox / PC horror masterpiece

      September 4, 2025

      ASUS built a desktop gaming PC around a mobile CPU — it’s an interesting, if flawed, idea

      September 4, 2025

      Hollow Knight: Silksong arrives on Xbox Game Pass this week — and Xbox’s September 1–7 lineup also packs in the horror. Here’s every new game.

      September 4, 2025

      The Xbox remaster that brought Gears to PlayStation just passed a huge milestone — “ending the console war” and proving the series still has serious pulling power

      September 4, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      Magento (Adobe Commerce) or Optimizely Configured Commerce: Which One to Choose

      September 4, 2025
      Recent

      Magento (Adobe Commerce) or Optimizely Configured Commerce: Which One to Choose

      September 4, 2025

      Updates from N|Solid Runtime: The Best Open-Source Node.js RT Just Got Better

      September 3, 2025

      Scale Your Business with AI-Powered Solutions Built for Singapore’s Digital Economy

      September 3, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      ‘Cronos: The New Dawn’ was by far my favorite experience at Gamescom 2025 — Bloober might have cooked an Xbox / PC horror masterpiece

      September 4, 2025
      Recent

      ‘Cronos: The New Dawn’ was by far my favorite experience at Gamescom 2025 — Bloober might have cooked an Xbox / PC horror masterpiece

      September 4, 2025

      ASUS built a desktop gaming PC around a mobile CPU — it’s an interesting, if flawed, idea

      September 4, 2025

      Hollow Knight: Silksong arrives on Xbox Game Pass this week — and Xbox’s September 1–7 lineup also packs in the horror. Here’s every new game.

      September 4, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»OTP Authentication in Laravel & Vue.js for Secure Transactions

    OTP Authentication in Laravel & Vue.js for Secure Transactions

    April 20, 2025

    Introduction

    In today’s digital world, security is paramount, especially when dealing with sensitive data like user authentication and financial transactions. One of the most effective ways to enhance security is by implementing One-Time Password (OTP) authentication. This article explores how to implement OTP authentication in a Laravel backend with a Vue.js frontend, ensuring secure transactions.

    Why Use OTP Authentication?

    OTP authentication provides an extra layer of security beyond traditional username and password authentication. Some key benefits include:

    • Prevention of Unauthorized Access: Even if login credentials are compromised, an attacker cannot log in without the OTP.
    • Enhanced Security for Transactions: OTPs can be used to confirm high-value transactions, preventing fraud.
    • Temporary Validity: Since OTPs expire after a short period, they reduce the risk of reuse by attackers.

    Prerequisites

    Before getting started, ensure you have the following:

    • Laravel 8 or later installed
    • Vue.js configured in your project
    • A mail or SMS service provider for sending OTPs (e.g., Twilio, Mailtrap)
    • Basic understanding of Laravel and Vue.js

    In this guide, we’ll implement OTP authentication in a Laravel (backend) and Vue.js (frontend) application. We’ll cover:

    • Setting up Laravel and Vue (frontend) from scratch
    • Setting up OTP generation and validation in Laravel
    • Creating a Vue.js component for OTP input
    • Integrating OTP authentication into login workflows
    • Enhancing security with best practices

    By the end, you’ll have a fully functional OTP authentication system ready to enhance the security of your fintech or web application.

    Setting Up Laravel for OTP Authentication

    Step 1: Install Laravel and Required Packages

    If you haven’t already set up a Laravel project, create a new one:

    composer create-project <span class="hljs-string">"laravel/laravel:^10.0"</span> example-app
    

    Next, install the Laravel Breeze package for frontend scaffolding:

    composer <span class="hljs-keyword">require</span> laravel/breeze --dev
    

    After composer has finished installing, run the following command to select the framework you want to use—the Vue configuration:

    php artisan breeze:install
    

    You’ll see a prompt with the available stacks:

    Which Breeze stack would you like to install?
    - Vue with Inertia   
    Would you like any optional features?
    - None   
    Which testing framework do you prefer? 
    - PHPUnit
    

    Breeze will automatically install the necessary packages for your Laravel Vue project. You should see:

    INFO Breeze scaffolding installed successfully.
    

    Now run the npm command to build your frontend assets:

    npm run dev
    

    Then, open another terminal and launch your Laravel app:

    php artisan serve
    

    Step 2: Setting up OTP generation and validation in Laravel

    We’ll use a mail testing platform called Mailtrap to send and receive mail locally. If you don’t have a mail testing service set up, sign up at Mailtrap to get your SMTP credentials and add them to your .env file:

    MAIL_MAILER=smtp
    MAIL_HOST=sandbox.smtp.mailtrap.io
    MAIL_PORT=2525
    MAIL_USERNAME=1780944422200a
    MAIL_PASSWORD=a8250ee453323b
    MAIL_ENCRYPTION=tls
    MAIL_FROM_ADDRESS=hello@example.com
    MAIL_FROM_NAME="${APP_NAME}"
    

    To send OTPs to users, we’ll use Laravel’s built-in mail services. Create a mail class and controller:

    php artisan make:mail OtpMail
    php artisan make:controller OtpController
    

    Then modify the OtpMail class:

    <span class="hljs-meta"><?php</span>
    
    <span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span><span class="hljs-title">Mail</span>;
    
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span><span class="hljs-title">Bus</span><span class="hljs-title">Queueable</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span><span class="hljs-title">Contracts</span><span class="hljs-title">Queue</span><span class="hljs-title">ShouldQueue</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span><span class="hljs-title">Mail</span><span class="hljs-title">Mailable</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span><span class="hljs-title">Mail</span><span class="hljs-title">Mailables</span><span class="hljs-title">Content</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span><span class="hljs-title">Mail</span><span class="hljs-title">Mailables</span><span class="hljs-title">Envelope</span>;
    <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span><span class="hljs-title">Queue</span><span class="hljs-title">SerializesModels</span>;
    
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OtpMail</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mailable</span>
    </span>{
        <span class="hljs-keyword">use</span> <span class="hljs-title">Queueable</span>, <span class="hljs-title">SerializesModels</span>;
    
        <span class="hljs-keyword">public</span> <span class="hljs-variable">$otp</span>;
    
        <span class="hljs-comment">/**
         * Create a new message instance.
         */</span>
        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-variable">$otp</span></span>)
        </span>{
            <span class="hljs-keyword">$this</span>->otp = <span class="hljs-variable">$otp</span>;
        }
    
        <span class="hljs-comment">/**
         * Build the email message.
         */</span>
        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">build</span>(<span class="hljs-params"></span>)
        </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>->subject(<span class="hljs-string">'Your OTP Code'</span>)
                ->view(<span class="hljs-string">'emails.otp'</span>)
                ->with([<span class="hljs-string">'otp'</span> => <span class="hljs-keyword">$this</span>->otp]);
        }
    
        <span class="hljs-comment">/**
         * Get the message envelope.
         */</span>
        <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">envelope</span>(<span class="hljs-params"></span>): <span class="hljs-title">Envelope</span>
        </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Envelope(
                subject: <span class="hljs-string">'OTP Mail'</span>,
            );
        }
    }
    

    Create a Blade view in resources/views/emails/otp.blade.php:

    <span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span>
    <span class="hljs-tag"><<span class="hljs-name">html</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">head</span>></span>
            <span class="hljs-tag"><<span class="hljs-name">title</span>></span>Your OTP Code<span class="hljs-tag"></<span class="hljs-name">title</span>></span>
        <span class="hljs-tag"></<span class="hljs-name">head</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">body</span>></span>
            <span class="hljs-tag"><<span class="hljs-name">p</span>></span>Hello,<span class="hljs-tag"></<span class="hljs-name">p</span>></span>
            <span class="hljs-tag"><<span class="hljs-name">p</span>></span>Your One-Time Password (OTP) is: <span class="hljs-tag"><<span class="hljs-name">strong</span>></span>{{ $otp }}<span class="hljs-tag"></<span class="hljs-name">strong</span>></span><span class="hljs-tag"></<span class="hljs-name">p</span>></span>
            <span class="hljs-tag"><<span class="hljs-name">p</span>></span>This code is valid for 10 minutes. Do not share it with anyone.<span class="hljs-tag"></<span class="hljs-name">p</span>></span>
            <span class="hljs-tag"><<span class="hljs-name">p</span>></span>Thank you!<span class="hljs-tag"></<span class="hljs-name">p</span>></span>
        <span class="hljs-tag"></<span class="hljs-name">body</span>></span>
    <span class="hljs-tag"></<span class="hljs-name">html</span>></span>
    

    Step 3: Creating a Vue.js component for OTP input

    Normally, after login or registration, users are redirected to the dashboard. In this tutorial, we add an extra security step that validates users with an OTP before granting dashboard access.

    Create two Vue files:

    • Request.vue: requests the OTP
    • Verify.vue: inputs the OTP for verification

    Now we create the routes for the purpose of return the View and the functionality of creating OTP codes, storing OTP codes, sending OTP codes through the mail class, we head to our web.php file:

    Route::middleware(<span class="hljs-string">'auth'</span>)->group(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        Route::get(<span class="hljs-string">'/request'</span>, [OtpController::class, <span class="hljs-string">'create'</span>])->name(<span class="hljs-string">'request'</span>);
        Route::post(<span class="hljs-string">'/store-request'</span>, [OtpController::class, <span class="hljs-string">'store'</span>])->name(<span class="hljs-string">'send.otp.request'</span>);
    
        Route::get(<span class="hljs-string">'/verify'</span>, [OtpController::class, <span class="hljs-string">'verify'</span>])->name(<span class="hljs-string">'verify'</span>);
        Route::post(<span class="hljs-string">'/verify-request'</span>, [OtpController::class, <span class="hljs-string">'verify_request'</span>])->name(<span class="hljs-string">'verify.otp.request'</span>);
    });
    

    Putting all of this code in the OTP controller returns the View for our request.vue and verify.vue file and the functionality of creating OTP codes, storing OTP codes, sending OTP codes through the mail class and verifying OTP codes, we head to our web.php file to set up the routes.

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">create</span>(<span class="hljs-params">Request <span class="hljs-variable">$request</span></span>)
    </span>{
        <span class="hljs-keyword">return</span> Inertia::render(<span class="hljs-string">'Request'</span>, [
            <span class="hljs-string">'email'</span> => <span class="hljs-variable">$request</span>->query(<span class="hljs-string">'email'</span>, <span class="hljs-string">''</span>),
        ]);
    }
    
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">store</span>(<span class="hljs-params">Request <span class="hljs-variable">$request</span></span>)
    </span>{
        <span class="hljs-variable">$request</span>->validate([
            <span class="hljs-string">'email'</span> => <span class="hljs-string">'required|email|exists:users,email'</span>,
        ]);
    
        <span class="hljs-variable">$otp</span> = rand(<span class="hljs-number">100000</span>, <span class="hljs-number">999999</span>);
    
        Cache::put(<span class="hljs-string">'otp_'</span> . <span class="hljs-variable">$request</span>->email, <span class="hljs-variable">$otp</span>, now()->addMinutes(<span class="hljs-number">10</span>));
    
        Log::info(<span class="hljs-string">"OTP generated for "</span> . <span class="hljs-variable">$request</span>->email . <span class="hljs-string">": "</span> . <span class="hljs-variable">$otp</span>);
    
        Mail::to(<span class="hljs-variable">$request</span>->email)->send(<span class="hljs-keyword">new</span> OtpMail(<span class="hljs-variable">$otp</span>));
    
        <span class="hljs-keyword">return</span> redirect()->route(<span class="hljs-string">'verify'</span>, [<span class="hljs-string">'email'</span> => <span class="hljs-variable">$request</span>->email]);
    }
    
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">verify</span>(<span class="hljs-params">Request <span class="hljs-variable">$request</span></span>)
    </span>{
        <span class="hljs-keyword">return</span> Inertia::render(<span class="hljs-string">'Verify'</span>, [
            <span class="hljs-string">'email'</span> => <span class="hljs-variable">$request</span>->query(<span class="hljs-string">'email'</span>),
        ]);
    }
    
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">verify_request</span>(<span class="hljs-params">Request <span class="hljs-variable">$request</span></span>)
    </span>{
        <span class="hljs-variable">$request</span>->validate([
            <span class="hljs-string">'email'</span> => <span class="hljs-string">'required|email|exists:users,email'</span>,
            <span class="hljs-string">'otp'</span> => <span class="hljs-string">'required|digits:6'</span>,
        ]);
    
        <span class="hljs-variable">$cachedOtp</span> = Cache::get(<span class="hljs-string">'otp_'</span> . <span class="hljs-variable">$request</span>->email);
    
        Log::info(<span class="hljs-string">"OTP entered: "</span> . <span class="hljs-variable">$request</span>->otp);
        Log::info(<span class="hljs-string">"OTP stored in cache: "</span> . (<span class="hljs-variable">$cachedOtp</span> ?? <span class="hljs-string">'No OTP found'</span>));
    
        <span class="hljs-keyword">if</span> (!<span class="hljs-variable">$cachedOtp</span>) {
            <span class="hljs-keyword">return</span> back()->withErrors([<span class="hljs-string">'otp'</span> => <span class="hljs-string">'OTP has expired. Please request a new one.'</span>]);
        }
    
        <span class="hljs-keyword">if</span> ((<span class="hljs-keyword">string</span>) <span class="hljs-variable">$cachedOtp</span> !== (<span class="hljs-keyword">string</span>) <span class="hljs-variable">$request</span>->otp) {
            <span class="hljs-keyword">return</span> back()->withErrors([<span class="hljs-string">'otp'</span> => <span class="hljs-string">'Invalid OTP. Please try again.'</span>]);
        }
    
        Cache::forget(<span class="hljs-string">'otp_'</span> . <span class="hljs-variable">$request</span>->email);
    
        <span class="hljs-variable">$user</span> = User::where(<span class="hljs-string">'email'</span>, <span class="hljs-variable">$request</span>->email)->first();
        <span class="hljs-keyword">if</span> (<span class="hljs-variable">$user</span>) {
            <span class="hljs-variable">$user</span>->email_verified_at = now();
            <span class="hljs-variable">$user</span>->save();
        }
    
        <span class="hljs-keyword">return</span> redirect()->route(<span class="hljs-string">'dashboard'</span>)->with(<span class="hljs-string">'success'</span>, <span class="hljs-string">'OTP Verified Successfully!'</span>);
    }
    

    Having set all this code, we return to the request.vue file to set it up.

    <script setup>
    <span class="hljs-keyword">import</span> AuthenticatedLayout <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Layouts/AuthenticatedLayout.vue'</span>;
    <span class="hljs-keyword">import</span> InputError <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Components/InputError.vue'</span>;
    <span class="hljs-keyword">import</span> InputLabel <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Components/InputLabel.vue'</span>;
    <span class="hljs-keyword">import</span> PrimaryButton <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Components/PrimaryButton.vue'</span>;
    <span class="hljs-keyword">import</span> TextInput <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Components/TextInput.vue'</span>;
    <span class="hljs-keyword">import</span> { Head, useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">'@inertiajs/vue3'</span>;
    
    <span class="hljs-keyword">const</span> props = defineProps({
        <span class="hljs-attr">email</span>: {
            <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,
            <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,
        },
    });
    
    <span class="hljs-keyword">const</span> form = useForm({
        <span class="hljs-attr">email</span>: props.email,
    });
    
    <span class="hljs-keyword">const</span> submit = <span class="hljs-function">() =></span> {
        form.post(route(<span class="hljs-string">'send.otp.request'</span>), {
            <span class="hljs-attr">onSuccess</span>: <span class="hljs-function">() =></span> {
                alert(<span class="hljs-string">"OTP has been sent to your email!"</span>);
                form.get(route(<span class="hljs-string">'verify'</span>), { <span class="hljs-attr">email</span>: form.email }); <span class="hljs-comment">// Redirecting to OTP verification</span>
            },
        });
    };
    </script>
    
    <span class="xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">Head</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Request OTP"</span> /></span>
    
        <span class="hljs-tag"><<span class="hljs-name">AuthenticatedLayout</span>></span>
            <span class="hljs-tag"><<span class="hljs-name">form</span> @<span class="hljs-attr">submit.prevent</span>=<span class="hljs-string">"submit"</span>></span>
                <span class="hljs-tag"><<span class="hljs-name">div</span>></span>
                    <span class="hljs-tag"><<span class="hljs-name">InputLabel</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Email"</span> /></span>
    
                    <span class="hljs-tag"><<span class="hljs-name">TextInput</span>
                        <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
                        <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-1 block w-full"</span>
                        <span class="hljs-attr">v-model</span>=<span class="hljs-string">"form.email"</span>
                        <span class="hljs-attr">required</span>
                        <span class="hljs-attr">autofocus</span>
                    /></span>
    
                    <span class="hljs-tag"><<span class="hljs-name">InputError</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-2"</span> <span class="hljs-attr">:message</span>=<span class="hljs-string">"form.errors.email"</span> /></span>
                <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
    
                <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-4 flex items-center justify-end"</span>></span>
                    <span class="hljs-tag"><<span class="hljs-name">PrimaryButton</span> <span class="hljs-attr">:class</span>=<span class="hljs-string">"{ 'opacity-25': form.processing }"</span> <span class="hljs-attr">:disabled</span>=<span class="hljs-string">"form.processing"</span>></span>
                        Request OTP
                    <span class="hljs-tag"></<span class="hljs-name">PrimaryButton</span>></span>
                <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
            <span class="hljs-tag"></<span class="hljs-name">form</span>></span>
        <span class="hljs-tag"></<span class="hljs-name">AuthenticatedLayout</span>></span>
    <span class="hljs-tag"></<span class="hljs-name">template</span>></span></span>
    

    Having set all this code, we return to the verify.vue to set it up:

    <script setup>
    <span class="hljs-keyword">import</span> AuthenticatedLayout <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Layouts/AuthenticatedLayout.vue'</span>;
    <span class="hljs-keyword">import</span> InputError <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Components/InputError.vue'</span>;
    <span class="hljs-keyword">import</span> InputLabel <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Components/InputLabel.vue'</span>;
    <span class="hljs-keyword">import</span> PrimaryButton <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Components/PrimaryButton.vue'</span>;
    <span class="hljs-keyword">import</span> TextInput <span class="hljs-keyword">from</span> <span class="hljs-string">'@/Components/TextInput.vue'</span>;
    <span class="hljs-keyword">import</span> { Head, useForm, usePage } <span class="hljs-keyword">from</span> <span class="hljs-string">'@inertiajs/vue3'</span>;
    
    <span class="hljs-keyword">const</span> page = usePage();
    <span class="hljs-comment">// Get the email from the URL query params</span>
    <span class="hljs-keyword">const</span> email = page.props.email || <span class="hljs-string">''</span>;
    
    <span class="hljs-comment">// Initialize form with email and OTP field</span>
    <span class="hljs-keyword">const</span> form = useForm({
        <span class="hljs-attr">email</span>: email,
        <span class="hljs-attr">otp</span>: <span class="hljs-string">''</span>,
    });
    
    <span class="hljs-comment">// Submit function</span>
    <span class="hljs-keyword">const</span> submit = <span class="hljs-function">() =></span> {
        form.post(route(<span class="hljs-string">'verify.otp.request'</span>), {
            <span class="hljs-attr">onSuccess</span>: <span class="hljs-function">() =></span> {
                alert(<span class="hljs-string">"OTP verified successfully! Redirecting..."</span>);
                <span class="hljs-built_in">window</span>.location.href = <span class="hljs-string">'/dashboard'</span>; <span class="hljs-comment">// Change to your desired redirect page</span>
            },
            <span class="hljs-attr">onError</span>: <span class="hljs-function">() =></span> {
                alert(<span class="hljs-string">"Invalid OTP. Please try again."</span>);
            },
        });
    };
    </script>
    
    <span class="xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">Head</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Verify OTP"</span> /></span>
    
        <span class="hljs-tag"><<span class="hljs-name">AuthenticatedLayout</span>></span>
            <span class="hljs-tag"><<span class="hljs-name">form</span> @<span class="hljs-attr">submit.prevent</span>=<span class="hljs-string">"submit"</span>></span>
                <span class="hljs-tag"><<span class="hljs-name">div</span>></span>
                    <span class="hljs-tag"><<span class="hljs-name">InputLabel</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"otp"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Enter OTP"</span> /></span>
    
                    <span class="hljs-tag"><<span class="hljs-name">TextInput</span>
                        <span class="hljs-attr">id</span>=<span class="hljs-string">"otp"</span>
                        <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
                        <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-1 block w-full"</span>
                        <span class="hljs-attr">v-model</span>=<span class="hljs-string">"form.otp"</span>
                        <span class="hljs-attr">required</span>
                    /></span>
    
                    <span class="hljs-tag"><<span class="hljs-name">InputError</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-2"</span> <span class="hljs-attr">:message</span>=<span class="hljs-string">"form.errors.otp"</span> /></span>
                <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
    
                <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-4 flex items-center justify-end"</span>></span>
                    <span class="hljs-tag"><<span class="hljs-name">PrimaryButton</span> <span class="hljs-attr">:disabled</span>=<span class="hljs-string">"form.processing"</span>></span>
                        Verify OTP
                    <span class="hljs-tag"></<span class="hljs-name">PrimaryButton</span>></span>
                <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
            <span class="hljs-tag"></<span class="hljs-name">form</span>></span>
        <span class="hljs-tag"></<span class="hljs-name">AuthenticatedLayout</span>></span>
    <span class="hljs-tag"></<span class="hljs-name">template</span>></span></span>
    

    Step 4: Integrating OTP authentication into login and register workflows

    Update the login controller:

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">store</span>(<span class="hljs-params">LoginRequest <span class="hljs-variable">$request</span></span>): <span class="hljs-title">RedirectResponse</span>
    </span>{
        <span class="hljs-variable">$request</span>->authenticate();
    
        <span class="hljs-variable">$request</span>->session()->regenerate();
    
        <span class="hljs-keyword">return</span> redirect()->intended(route(<span class="hljs-string">'request'</span>, absolute: <span class="hljs-literal">false</span>));
    }
    

    Update the registration controller:

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">store</span>(<span class="hljs-params">Request <span class="hljs-variable">$request</span></span>): <span class="hljs-title">RedirectResponse</span>
    </span>{
        <span class="hljs-variable">$request</span>->validate([
            <span class="hljs-string">'name'</span> => <span class="hljs-string">'required|string|max:255'</span>,
            <span class="hljs-string">'email'</span> => <span class="hljs-string">'required|string|lowercase|email|max:255|unique:'</span> . User::class,
            <span class="hljs-string">'password'</span> => [<span class="hljs-string">'required'</span>, <span class="hljs-string">'confirmed'</span>, RulesPassword::defaults()],
        ]);
    
        <span class="hljs-variable">$user</span> = User::create([
            <span class="hljs-string">'name'</span> => <span class="hljs-variable">$request</span>->name,
            <span class="hljs-string">'email'</span> => <span class="hljs-variable">$request</span>->email,
            <span class="hljs-string">'password'</span> => Hash::make(<span class="hljs-variable">$request</span>->password),
        ]);
    
        event(<span class="hljs-keyword">new</span> Registered(<span class="hljs-variable">$user</span>));
    
        Auth::login(<span class="hljs-variable">$user</span>);
    
        <span class="hljs-keyword">return</span> redirect(route(<span class="hljs-string">'request'</span>, absolute: <span class="hljs-literal">false</span>));
    }
    

    Conclusion

    Implementing OTP authentication in Laravel and Vue.js enhances security for user logins and transactions. By generating, sending, and verifying OTPs, we can add an extra layer of protection against unauthorized access. This method is particularly useful for financial applications and sensitive user data.

    Source: Read More

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleAI Ethics and Privacy: The Human Role in Responsible Tech
    Next Article APT29 Deploys GRAPELOADER Malware Targeting European Diplomats Through Wine-Tasting Lures

    Related Posts

    Development

    How to Make Bluetooth on Android More Reliable

    September 4, 2025
    Development

    Learn Mandarin Chinese for Beginners – Full HSK 1 Level

    September 4, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    Snowflake Proposes ExCoT: A Novel AI Framework that Iteratively Optimizes Open-Source LLMs by Combining CoT Reasoning with off-Policy and on-Policy DPO, Relying Solely on Execution Accuracy as Feedback

    Machine Learning

    Teaching Mistral Agents to Say No: Content Moderation from Prompt to Response

    Machine Learning

    Over 46,000 Grafana instances exposed to account takeover bug

    Security

    CVE-2025-50754 – Unisite CMS Stored XSS

    Common Vulnerabilities and Exposures (CVEs)

    Highlights

    AI-enabled software development: Risk of skill erosion or catalyst for growth?

    July 23, 2025

    As artificial intelligence becomes an integral part of software development, a fundamental question arises: does…

    Smart Failure Handling in HCL Commerce with Circuit Breakers

    August 15, 2025

    CVE-2025-45009 – PHPGurukul Park Ticketing Management System HTML Injection

    April 30, 2025

    Cybercrime Losses Jump 33% in 2024, FBI Report Shows

    April 24, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.