[GH-ISSUE #7] Middleware for L5 #5

Closed
opened 2026-02-25 20:32:07 +03:00 by kerem · 13 comments
Owner

Originally created by @tomschlick on GitHub (May 6, 2015).
Original GitHub issue: https://github.com/antonioribeiro/google2fa/issues/7

If this package had middleware you could require 2fa for certain routes (like /admin & /settings) or all routes.

It would redirect to a screen to enter that info then redirect back to the intended resource just like login.

Originally created by @tomschlick on GitHub (May 6, 2015). Original GitHub issue: https://github.com/antonioribeiro/google2fa/issues/7 If this package had middleware you could require 2fa for certain routes (like /admin & /settings) or all routes. It would redirect to a screen to enter that info then redirect back to the intended resource just like login.
kerem closed this issue 2026-02-25 20:32:07 +03:00
Author
Owner

@ghost commented on GitHub (Jun 8, 2015):

@tomschlick Great idea. +1

<!-- gh-comment-id:109997533 --> @ghost commented on GitHub (Jun 8, 2015): @tomschlick Great idea. +1
Author
Owner

@antonioribeiro commented on GitHub (Nov 7, 2015):

Cool! Anyone feeling like helping with this?

<!-- gh-comment-id:154707625 --> @antonioribeiro commented on GitHub (Nov 7, 2015): Cool! Anyone feeling like helping with this?
Author
Owner

@arleslie commented on GitHub (Dec 28, 2015):

        if ($this->auth->User()->has2fa() && !$request->session()->has('2faAuthed')) {
            if ($request->ajax()) {
                return response('Unauthorized.', 401);
            } else {
                return redirect()->guest('auth/2fa');
            }
        }

I just added that into the Authenticate middleware.
has2fa() is a function I added to just return true or false if the user has activated 2fa.
When the user completes 2fa, it'll push to the session 2faAuthed => true.

If you are using the RedirectIfAuthenticated middleware you'll need to change:
if ($this->auth->check()) {
to:
if ($this->auth->check() && $this->auth->User()->has2fa() && $request->session()->has('2faAuthed')) {

<!-- gh-comment-id:167600612 --> @arleslie commented on GitHub (Dec 28, 2015): ``` if ($this->auth->User()->has2fa() && !$request->session()->has('2faAuthed')) { if ($request->ajax()) { return response('Unauthorized.', 401); } else { return redirect()->guest('auth/2fa'); } } ``` I just added that into the Authenticate middleware. `has2fa()` is a function I added to just return true or false if the user has activated 2fa. When the user completes 2fa, it'll push to the session `2faAuthed => true`. If you are using the RedirectIfAuthenticated middleware you'll need to change: `if ($this->auth->check()) {` to: `if ($this->auth->check() && $this->auth->User()->has2fa() && $request->session()->has('2faAuthed')) {`
Author
Owner

@rdev5 commented on GitHub (Jul 26, 2016):

@tomschlick @michelecurletta @antonioribeiro @arleslie

Let me know if this works for you guys: https://gist.github.com/rdev5/e7f68dcfab8452bb5c65070a60422638

Feedback, suggestions, etc. are welcomed, or if it looks good as-is I can submit a PR.

<!-- gh-comment-id:235187316 --> @rdev5 commented on GitHub (Jul 26, 2016): @tomschlick @michelecurletta @antonioribeiro @arleslie Let me know if this works for you guys: https://gist.github.com/rdev5/e7f68dcfab8452bb5c65070a60422638 Feedback, suggestions, etc. are welcomed, or if it looks good as-is I can submit a PR.
Author
Owner

@antonioribeiro commented on GitHub (Jul 28, 2016):

I like the idea of a middleware here, but I think we should first extract the main Google2FA classes to a framework agnostic package (I have just created it: https://github.com/antonioribeiro/google2fa-php), require that package here, refactor it to remove those classes, reestructure folders to bring facade e service provider to the root, and free it to be framework centric, where we could add all sort of things.

What do you think?

/cc @GrahamCampbell @barryvdh

<!-- gh-comment-id:235766753 --> @antonioribeiro commented on GitHub (Jul 28, 2016): I like the idea of a middleware here, but I think we should first extract the main Google2FA classes to a framework agnostic package (I have just created it: https://github.com/antonioribeiro/google2fa-php), require that package here, refactor it to remove those classes, reestructure folders to bring facade e service provider to the root, and free it to be framework centric, where we could add all sort of things. What do you think? /cc @GrahamCampbell @barryvdh
Author
Owner

@aik099 commented on GitHub (Jul 28, 2016):

@antonioribeiro , isn't antonioribeiro/google2fa already framework agnostic? If that is so, then new repo will add middleware and require this package. Is is the opposite of what you're proposing.

<!-- gh-comment-id:235818839 --> @aik099 commented on GitHub (Jul 28, 2016): @antonioribeiro , isn't `antonioribeiro/google2fa` already framework agnostic? If that is so, then new repo will add middleware and require this package. Is is the opposite of what you're proposing.
Author
Owner

@barryvdh commented on GitHub (Jul 28, 2016):

Yeah I think this was mostly already agnostic, except for the ServiceProvider which only registers the interface and Facade.

Imho, you don't even need the interface in it's current state, because the interface is pretty specific and there are not really any other implementations, right? So the public methods from the Google2FA class already serve as a 'interface' you cannot break in minor versions. Then there is 0 reason for this current package to be called 'Laravel centric'.

In that view, it makes more sense to create a google2fa-laravel package, if you want to add Laravel specific stuff, like a middleware, validator etc.

<!-- gh-comment-id:235819645 --> @barryvdh commented on GitHub (Jul 28, 2016): Yeah I think this was mostly already agnostic, except for the ServiceProvider which only registers the interface and Facade. Imho, you don't even need the interface in it's current state, because the interface is pretty specific and there are not really any other implementations, right? So the public methods from the Google2FA class already serve as a 'interface' you cannot break in minor versions. Then there is 0 reason for this current package to be called 'Laravel centric'. In that view, it makes more sense to create a google2fa-laravel package, if you want to add Laravel specific stuff, like a middleware, validator etc.
Author
Owner

@aik099 commented on GitHub (Jul 28, 2016):

@barryvdh , completely agree with you. The same idea, that I've wrote in https://github.com/antonioribeiro/google2fa/issues/7#issuecomment-235818839, but more detailed explanation.

<!-- gh-comment-id:235820377 --> @aik099 commented on GitHub (Jul 28, 2016): @barryvdh , completely agree with you. The same idea, that I've wrote in https://github.com/antonioribeiro/google2fa/issues/7#issuecomment-235818839, but more detailed explanation.
Author
Owner

@antonioribeiro commented on GitHub (Jul 28, 2016):

I agree it's agnostic, in the sense you don't need Laravel to use it, but, still, it is used as a Laravel package all around, and there are a lot of Laravel developers relying on it today, in this sense it may not be centric, but it is a framework enabled package.

By doing the opposite and creating a google2fa-laravel package, we would have to move Service Provider and Façade to this new package, and that would be a huge a breaking change. People currently using this one, as a Laravel package, would have to move to the new one. This package is still very small in usage and will not get to this point, but there are already 8 packages depending on it. Cachet, for instance, is using the Façade.

So the options are now:

  1. Keep it the way it is, and free people to add more Laravel stuff like a middleware and validator. Note that the middleware discussion, reason of this issue, has not yet begun, because that's completely different problem :)

  2. Move Laravel things to a google2fa-laravel, tagging a new major version.

  3. Move the core to a PHP only package and just tag a minor.

<!-- gh-comment-id:235960868 --> @antonioribeiro commented on GitHub (Jul 28, 2016): I agree it's agnostic, in the sense you don't need Laravel to use it, but, still, it is used as a Laravel package all around, and there are a lot of Laravel developers relying on it today, in this sense it may not be centric, but it is a framework enabled package. By doing the opposite and creating a google2fa-laravel package, we would have to move Service Provider and Façade to this new package, and that would be a huge a breaking change. People currently using this one, as a Laravel package, would have to move to the new one. This package is still very small in usage and will not get to [this](http://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/) point, but there are already [8 packages](https://packagist.org/packages/pragmarx/google2fa/dependents) depending on it. [Cachet](https://github.com/CachetHQ/Cachet/blob/master/app/Http/Controllers/AuthController.php#L22), for instance, is using the Façade. So the options are now: 1) Keep it the way it is, and free people to add more Laravel stuff like a middleware and validator. Note that the middleware discussion, reason of this issue, has not yet begun, because that's completely different problem :) 2) Move Laravel things to a google2fa-laravel, [tagging a new major version](http://semver.org/). 3) Move the core to a PHP only package and just tag a minor.
Author
Owner

@Rndwiga commented on GitHub (Feb 22, 2017):

@antonioribeiro I do agree with you, repackaging would be a huge breaking change. I have just started using the package in my project and its simplicity is key. On the Laravel aspect of the package i am submitting a PR to fix i bug I encountered.

<!-- gh-comment-id:281778292 --> @Rndwiga commented on GitHub (Feb 22, 2017): @antonioribeiro I do agree with you, repackaging would be a huge breaking change. I have just started using the package in my project and its simplicity is key. On the Laravel aspect of the package i am submitting a PR to fix i bug I encountered.
Author
Owner

@antonioribeiro commented on GitHub (Feb 22, 2017):

Fantastic, @Rndwiga, I'll wait for it. Thank you

<!-- gh-comment-id:281816094 --> @antonioribeiro commented on GitHub (Feb 22, 2017): Fantastic, @Rndwiga, I'll wait for it. Thank you
Author
Owner

@ghost commented on GitHub (Jun 17, 2017):

Here's an updated version of a middleware running fine on latest laravel (5.4)::

OTPLoginMiddleware.php

<?php

namespace App\Http\Middleware;

use Closure;
use Auth;
use App\User;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Mail;
use App\Mail\sendLoginOTP;

class OTPLoginMiddleware
{
    public function handle($request, Closure $next)
    {
        $user = Auth::user();

        // Skip if unauthenticated (not needed, when middleware is attached only to "protected" routes)
        if (!$user)
        {
            return $next($request);
        }

        // Skip if G2FA enabled and authorized in current session
        if ($request->session()->get('otp_authorized', false))
        {
            return $next($request);
        }
        
        // Add g2fa_authorized to session (be sure to clear out on logout, i.e. App\Listeners\LogSuccessfulLogout.php)
        if ($user->login_token == $request->input('otp'))
        {
            $request->session()->put('otp_authorized', true);
            return $next($request);
        }

        //generate new token
        $user->update([
            'login_token' => str_random(6),
            ]);

        //send new login token
        Mail::to($user->email)->send(new sendLoginOTP($user));

        return new Response(view('user.loginOTP'));

    }
}

Just create this middleware, register it (Kernel.php) and attach it when needed.

<!-- gh-comment-id:309196216 --> @ghost commented on GitHub (Jun 17, 2017): Here's an updated version of a middleware running fine on latest laravel (5.4):: OTPLoginMiddleware.php ``` <?php namespace App\Http\Middleware; use Closure; use Auth; use App\User; use Illuminate\Http\Response; use Illuminate\Support\Facades\Mail; use App\Mail\sendLoginOTP; class OTPLoginMiddleware { public function handle($request, Closure $next) { $user = Auth::user(); // Skip if unauthenticated (not needed, when middleware is attached only to "protected" routes) if (!$user) { return $next($request); } // Skip if G2FA enabled and authorized in current session if ($request->session()->get('otp_authorized', false)) { return $next($request); } // Add g2fa_authorized to session (be sure to clear out on logout, i.e. App\Listeners\LogSuccessfulLogout.php) if ($user->login_token == $request->input('otp')) { $request->session()->put('otp_authorized', true); return $next($request); } //generate new token $user->update([ 'login_token' => str_random(6), ]); //send new login token Mail::to($user->email)->send(new sendLoginOTP($user)); return new Response(view('user.loginOTP')); } } ``` Just create this middleware, register it (Kernel.php) and attach it when needed.
Author
Owner

@antonioribeiro commented on GitHub (Jun 20, 2017):

Tagged 2.0 just now. It's now only PHP. But we now have a Laravel bridge package: https://github.com/antonioribeiro/google2fa-laravel

Since some people were having trouble to understand it, I made this too:

Google2FA Playground: https://pragmarx.com/google2fa

<!-- gh-comment-id:309888944 --> @antonioribeiro commented on GitHub (Jun 20, 2017): Tagged 2.0 just now. It's now only PHP. But we now have a Laravel bridge package: https://github.com/antonioribeiro/google2fa-laravel Since some people were having trouble to understand it, I made this too: Google2FA Playground: https://pragmarx.com/google2fa
Sign in to join this conversation.
No labels
bug
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/google2fa#5
No description provided.