Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verification OTP successful but could not redirect to home page #186

Open
nicholas-wcy opened this issue Aug 26, 2023 · 3 comments
Open

Comments

@nicholas-wcy
Copy link

nicholas-wcy commented Aug 26, 2023

I want to implement google authenticator to my app so after user logins, they will be prompt to enter the TOTP.

So far, I have followed the package documentation and install it as well as setting up the middleware,etc.

Here is my login method:

// existing logic above

if ($userInfo["login_attempt"] < 5 || $allowLogin == true) {

                if ($this->attemptLogin($request)) {
                    if ($request->hasSession()) {
                        $request->session()->put('auth.password_confirmed_at', time());
                    }
                    $userInfo->update(array("login_attempt" => 0, "unlock_login_attempt"=> null, "status" => 1));

                    if (!$userInfo->google2fa_secret) {
                        $google2fa = app('pragmarx.google2fa');

                        $google2fa_secret = $google2fa->generateSecretKey();
                        $qrCodeUrl = $google2fa->getQRCodeInline(
                            "app name",
                            $userInfo->email,
                            $google2fa_secret
                        );

                        $userInfo->update([
                            'google2fa_secret' => $google2fa_secret
                        ]);

                        session()->put('qrCodeUrl', $qrCodeUrl); // Store $test in the session


                        return redirect()->route('2fa');
                    }

                    return $this->sendLoginResponse($request);
                }

My auth.google2fa.show.blade.php:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2FA Verification</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>

<body>

    <div class="container mt-5">
        <div class="row justify-content-center">
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">2FA Verification</div>

                    <div class="card-body">
                        <form method="POST" action="/2fa">
                            @csrf
                            <div class="form-group">
                                <label for="one_time_password">Enter 6-digit OTP from your Authenticator App</label>
                                <input id="one_time_password" type="text"
                                    class="form-control @error('one_time_password') is-invalid @enderror"
                                    name="one_time_password" required autofocus>

                                @error('one_time_password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>

                            <div class="form-group">
                                <button type="submit" class="btn btn-primary">
                                    Authenticate
                                </button>
                            </div>
                        </form>
                    </div>
                </div>
                <!-- Add the QR code below the form -->
                @if (session()->has('qrCodeUrl'))
                    <div class="mt-4 text-center">
                        <p>Scan this QR code with your authenticator app:</p>
                        {!! session('qrCodeUrl') !!}
                    </div>
                @endif
            </div>
        </div>
    </div>

</body>

</html>

TwoFactorController.php :

<?php

namespace App\Http\Controllers\Auth;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use PragmaRX\Google2FALaravel\Facade as Google2FA;

class TwoFactorController extends Controller
{
    public function show()
    {
        return view('auth.google2fa.show'); // Use the appropriate view for your 2FA verification page
    }

    public function verify(Request $request)
    {
        $validated = $request->validate([
            'one_time_password' => 'required',
        ]);

        $user = Auth::user();
        $google2fa = app('pragmarx.google2fa');
        $valid = $google2fa->verifyKey($user->google2fa_secret, $request->input('one_time_password'));
        // Verify the 2FA code using the package's functionality
        if ($valid) {
            // 2FA code is valid, proceed with login

            return redirect()->route('admin.dashboard');
        } else {
            // Invalid 2FA code, redirect back with an error message
            return redirect()->route('2fa')->withErrors(['one_time_password' => 'Invalid OTP code']);
        }
    }
}

Config google2fa.php:


<?php

return [

    /*
     * Enable / disable Google2FA.
     */
    'enabled' => env('OTP_ENABLED', true),

    /*
     * Lifetime in minutes.
     *
     * In case you need your users to be asked for a new one time passwords from time to time.
     */
    'lifetime' => env('OTP_LIFETIME', 0), // 0 = eternal

    /*
     * Renew lifetime at every new request.
     */
    'keep_alive' => env('OTP_KEEP_ALIVE', true),

    /*
     * Auth container binding.
     */
    'auth' => 'auth',

    /*
     * Guard.
     */
    'guard' => '',

    /*
     * 2FA verified session var.
     */
    'session_var' => 'google2fa',

    /*
     * One Time Password request input name.
     */
    'otp_input' => 'one_time_password',

    /*
     * One Time Password Window.
     */
    'window' => 1,

    /*
     * Forbid user to reuse One Time Passwords.
     */
    'forbid_old_passwords' => false,

    /*
     * User's table column for google2fa secret.
     */
    'otp_secret_column' => 'google2fa_secret',

    /*
     * One Time Password View.
     */
    'view' => 'auth.google2fa.show',

    /*
     * One Time Password error message.
     */
    'error_messages' => [
        'wrong_otp'       => "The 'One Time Password' typed was wrong.",
        'cannot_be_empty' => 'One Time Password cannot be empty.',
        'unknown'         => 'An unknown error has occurred. Please try again.',
    ],

    /*
     * Throw exceptions or just fire events?
     */
    'throw_exceptions' => env('OTP_THROW_EXCEPTION', true),

    /*
     * Which image backend to use for generating QR codes?
     *
     * Supports imagemagick, svg and eps
     */
    'qrcode_image_backend' => \PragmaRX\Google2FALaravel\Support\Constants::QRCODE_IMAGE_BACKEND_SVG,

];

web.php:

Route::group([
    'middleware' => ['auth'],
], function () {
    Route::get('/2fa', [TwoFactorController::class, 'show'])->name('2fa');
    Route::post('/2fa', [TwoFactorController::class, 'verify'])->name('verify-2fa');
});

Route::group([
    'middleware' => ['auth', '2fa'],
    'as'         => 'admin.',
], function () {
    Route::get('/', [DashboardController::class, 'index'])
        ->name('dashboard');
.......

While the flow and logic works fine up until the verification OTP, when I enter a valid OTP, it verifies successfully but it does not redirect to the home dashboard. It just redirects back to the OTP page. I assumed is because it somehow did not "pass" the 2fa middleware in my routes. I am not sure why is this the case or if I am missing something as i could not find a solution online for my issue.

Does anyone know the issue?

@ghost
Copy link

ghost commented Feb 6, 2024

If you haven't found the solution, you needed to invoke the Google2FA::login() after a successful verification

image

@realtebo
Copy link

I got

Call to undefined method PragmaRX\Google2FA\Google2FA::login()

The login method is from which class?

@arzlo
Copy link

arzlo commented Mar 13, 2024

I got

Call to undefined method PragmaRX\Google2FA\Google2FA::login()

The login method is from which class?

You need to call the class:

use Google2FA;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants