Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

JonathanL's avatar

How do I handle login/registration and sessions with vue-router and axios for an SPA

I'm at a brick wall pretty much at the start where I'm setting up user authentication and all that and I've googled these issues and there was something about Auth0 which I do not want to use. I would greatly appreciate it if anyone could link me to an article or resource explaining how to handle authentication in an SPA using vue, vue-router and axios.

here are my main questions:

  1. Sessions
  • How do I create a session when a user is authenticated, what am I supposed to do with a successful login/register response to be able to have something simple like this.user.isAuthenticated that i can access from a vue component kind of like how Auth::user() is used to conditionally render certain elements.
  1. Roles
  • How would i make sure that a user can't just edit the javascript to trick the app into thinking they're an admin? Probably a stupid question but with having most of my app be javascript pretty much I assume it has something to do with my first question with every page transition some sort of check happens to ensure that your an admin and not a user/guest going into an admin only router-view.

3 .Urls and Redirects

  • How do I modify the Auth that comes out of the box with laravel so that it doesn't redirect or return any views and instead have my app control the redirects/views?

  • Going to mysite.com/register takes me to laravel's default register page. How would I make it so that if a visitor goes to that url that they are redirected to my apps home page?

Sorry if this has been asked or covered before, I just can't find much on this specific setup for an SPA.

0 likes
5 replies
thepassenger's avatar
Level 2

Hi, I just recently finished a spa forum so I thought I may give some advice. I am by no means an expert so take my tips with a grain of salt.

1- Sessions

I have created a mixin and all components that need to check the session can run checkIfLogged() method.

var isLoggedMixin = {
  methods: {
    checkIfLogged(){
        var vm = this;
        return new Promise((resolve, reject) => {
          axios.get('/sessionStatus')
             .then(response => {
                resolve(response.data.user);
             })
             .catch(error => {
                reject(error.response.data);
             });
        })
        
    }
  }
}

export default isLoggedMixin;

The mixin performs a get request to the backend. The backend simply answers with a json containing the user if the user is logged else returns null:

Route::get('/sessionStatus', function() {
        return ['user' => Auth::user() ? Auth::user()->load('profile') : null];
    });

This is how I use it in my main app so as soon someone visits the site.

const app = new Vue({
    el: '#app',
    router,
    mixins:[isLoggedMixin],
    data: {
        user: false
    },
    created(){
        this.checkIfLogged()
            .then(response => {
                    this.user = response ? response : false;
                })                    
            .catch(error => console.log(error));
    }

Then based on $root.user you can do conditional rendering.

I just use checkIfLogged when app is created or when the user visits particular views that need user authentication.

1- Roles

Taking from the point 1 I totally understand what you mean. That's why this is just a simple auth to block the random unexperienced user from some views or actions. (In my case a guest shouldn't be able to create new threads). You will still need basic auth in the backend. For instance in my case if a user wants to create a new thread.

methods: {
            sendPost(){
                var vm = this;
                this.form.post('/channels/'+this.channel+'/threads')
                    .then(response => vm.$router.push({path: '/'+this.channel+'/'+response}))
                    .catch(error => {
                        let out = '';
                        Object.keys(error).forEach(field => out += error[field] +'\n' );
                        this.showError(out);
                    });
            }
        },

The form posts to

Route::post('channels/{channel}/threads', 'ThreadsController@store')->middleware('auth');

And in controller method you perform your validation of request and other stuff. For some routes you can make your own middleware.

For instance if a user wants to edit a reply I use policies to assure that the user is the actual creator. Check them here https://laravel.com/docs/5.4/authorization#generating-policies

3-Urls and Redirects

To modify the auth default controller checkout the Illuminate\Routing\Router.php file. There you can see the auth routes and which controller methods are called.

To modify for instance the redirects after login you head to the App\Http\Controllers\Auth\LoginController.php. There you can see

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

So checkout the trait and override inside the controller any method that you want to change. I did override

/**
     * Send the response after the user was authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    protected function sendLoginResponse(Request $request)
    {
        
        $request->session()->regenerate();

        $this->clearLoginAttempts($request);

        return response(['user' => auth()->user()->load('profile')], 200);
    }

to return a simple json instead of redirect. Than on front end you handle the response as you like.

As for your last point in the router file you can see how all routes map to each other controller.

2 likes
syropian's avatar

SPA's really shouldn't use sessions, you should be either using JWT tokens, or a full OAuth implementation (ie with Laravel Passport). The JWT route is usually sufficient though. In simple terms, this is the flow:

  1. User submits username and password to server
  2. Server verified credentials, and generates a JWT token, which it returns to the client.
  3. Client receives JWT token, stores it somewhere (usually localstorage)
  4. Client passes JWT token as an authorization header for all subsequent requests.
  5. Server middleware will detect the auth token in the header and set the current authorized user accordingly.
4 likes
jaec86's avatar

I was playing around with laravel and vue and made a small project to get started with spa auth. You can check it https://bitbucket.org/zeerbyte/laravelvue.

As I said, I was playing around and rewrote the auth process of laravel to use api_token. It does not include jwt, but it shouldn't be a big issue to add it. Hope it helps.

green-raven's avatar

I hope I'm interpreting what you are wanting. I'm assuming you are still using Laravel? If not, you can ignore this.

If so, you should separate front and back end a little more.

I feel like they did a great job with Auth, so I just left those in blade, and when you sign in you go to "home" for your role (manager, admin, etc.)

@section('content')
<Admin></Admin>
@endsection

And Vue takes over from there.

For session, I create a route (/updateSession/{some_number}, and then set session()->put('whatever', $some_number) in the Laravel controller.

To keep Vue aware, you keep a local version of the session number:

axios.post('/updateSession<whatever>/'+num).then(response => {
    this.sessionWhatever = num;
})

I use this to keep my "page" in session, so if I refresh it goes back to that page (check for it on created() with axios.get('/getSessionWhatever').

As for spoofing your role, that doesn't work because you are still calling web.php routes, and your authenticated user is still enforced.

Please or to participate in this conversation.