Loading...
+880 1736 699819 Mon - Sat: 9:00 AM - 8:00 PM
Follow us:
Home Blog Article
Blog

One-Time Password (OTP) Verification

One-Time Password (OTP) Verification

Registration

  1. User registers
  2. OTP is generated & sent to email
  3. User verifies OTP
  4. Account becomes verified

Login

  1. Email + password correct
  2. Generate OTP
  3. Send OTP to email
  4. Return requires_2fa = true
  5. Verify OTP → issue token

1️⃣ Database Changes

Add columns to users table

Schema::table('users', function (Blueprint $table) {
    $table->string('otp_code')->nullable();
    $table->timestamp('otp_expires_at')->nullable();
    $table->boolean('is_2fa_verified')->default(false);
});

2️⃣ Helper: Generate OTP

private function generateOtp()
{
    return rand(100000, 999999);
}

3️⃣ Update User Register (Send OTP)

public function user_register(Request $request)
{
    $validated = Validator::make($request->all(), [
        'email' => 'required|email|unique:users',
        'password' => 'required|min:6',
    ]);

    if ($validated->fails()) {
        return response([
            'message' => $validated->errors(),
            'status' => 'error',
        ], 422);
    }

    DB::beginTransaction();
    try {

        $otp = $this->generateOtp();

        $user = User::create([
            'full_name' => $request->input('full_name', ''),
            'user_type' => 1,
            'email' => $request->email,
            'password' => Hash::make($request->password),
            'otp_code' => $otp,
            'otp_expires_at' => now()->addMinutes(5),
        ]);

        // Send OTP via email (simple example)
        Mail::raw("Your OTP is: {$otp}", function ($message) use ($user) {
            $message->to($user->email)
                    ->subject('Verify Your Account');
        });

        DB::commit();

        return response([
            'message' => 'Registration successful. OTP sent to email.',
            'status' => 'success',
        ], 201);

    } catch (\Exception $e) {
        DB::rollback();
        return response([
            'message' => $e->getMessage(),
            'status' => 'error',
        ], 500);
    }
}

4️⃣ Update User Login (Trigger 2FA)

public function user_login(Request $request)
{
    $validated = Validator::make($request->all(), [
        'email' => 'required|email',
        'password' => 'required',
    ]);

    if ($validated->fails()) {
        return response([
            'message' => $validated->errors(),
            'status' => 'error',
        ], 422);
    }

    $user = User::where('email', $request->email)
        ->where('status', 1)
        ->first();

    if (!$user || !Hash::check($request->password, $user->password)) {
        return response([
            'message' => 'Invalid credentials',
            'status' => 'error',
        ], 401);
    }

    // Generate OTP
    $otp = $this->generateOtp();

    $user->update([
        'otp_code' => $otp,
        'otp_expires_at' => now()->addMinutes(5),
        'is_2fa_verified' => false,
    ]);

    // Send OTP
    Mail::raw("Your login OTP is: {$otp}", function ($message) use ($user) {
        $message->to($user->email)
                ->subject('Login Verification OTP');
    });

    return response([
        'message' => 'OTP sent to email',
        'requires_2fa' => true,
        'status' => 'success',
    ], 200);
}

5️⃣ OTP Verification API (FINAL LOGIN)

public function verifyOtp(Request $request)
{
    $request->validate([
        'email' => 'required|email',
        'otp' => 'required',
    ]);

    $user = User::where('email', $request->email)
        ->where('otp_code', $request->otp)
        ->where('otp_expires_at', '>=', now())
        ->first();

    if (!$user) {
        return response([
            'message' => 'Invalid or expired OTP',
            'status' => 'error',
        ], 401);
    }

    $user->update([
        'otp_code' => null,
        'otp_expires_at' => null,
        'is_2fa_verified' => true,
    ]);

    $token = $user->createToken($user->email)->plainTextToken;

    return response([
        'user' => $user,
        'token' => $token,
        'message' => 'Login successful',
        'status' => 'success',
    ], 200);
}

6️⃣ API Flow Summary

POST /register → OTP sent
POST /login → OTP sent
POST /verify-otp → Token issued


Tags: Blog
Share this post

Encoderbase Team

Author

Articles and insights from the Encoderbase editorial team covering web development, software engineering, and digital solutions.

Enjoyed this article?

Get more articles like this delivered to your inbox — no spam, unsubscribe any time.

Link copied to clipboard!