0
votes

Is it even possible to have multiple middleware in one route. Right now i have my web app making ajax requests with the middleware of auth, which is defaulted at auth:web

Route::post('/user/postAuthUserInfoAjax', [
  'uses' => 'UserController@postAuthUserInfoAjax',
  'middleware' => ['auth'],
]);

I also want my mobile app, which has an API Access token(using laravel passport) to authenticate a user to be able to access those same routes. In order to do that I just specify 'auth:api' in my middleware.

Route::post('/user/postAuthUserInfoAjax', [
  'uses' => 'UserController@postAuthUserInfoAjax',
  'middleware' => ['auth:api'],
]);

The only problem is I cant specify multiple middlewares. I can either use 'auth:api' or 'auth:web' but not both. I guess I could just have two routes for each ajax request one for the web app and another for the api requests, but it would be so much better if I could just use one route.

I have tried, but it doesnt work. Does anyone know how to do this? is it even possible

 Route::post('/user/postAuthUserInfoAjax', [
  'uses' => 'UserController@postAuthUserInfoAjax',
  'middleware' => ['auth:web','auth:api'],
]);
1

1 Answers

0
votes

This won't work because you're saying the following:

Before processing this request, validate that the user is authenticated through the web provider, however, they also must be authenticated through my api provider as well.

One way that you could approach this is to just have two controllers, but extend a base controller with the functionality already baked in:

App
|
---- Http
     |
     ---- Controllers
          |
          ---- UserController (this will be our base)
          ---- API
               |
               ---- UserController (will extend the base)
          ---- Web
               |
               ---- UserController (will extend the base)

Then you should set up route groups accordingly:

//Your "web provider" authenticated routes
Route::group(['middleware' => ['auth:web'] 'namespace' => 'Web', function(){

});

Then for your API requests:

//your "api provider" authenticated routes
Route::group(['middleware' => ['auth:api'], 'namespace' => 'API', function(){

});

This is the route we'll put inside both of our groups:

Route::post('user/info', 'UserController@info');

Then the base controller should look something like this:

class UserController extends App\Http\Controller {

   /**
    * Update the specified User Resource
    *
    * @param Illuminate\Http\Request $request
    * @param App\User $user
    * 
    * @returns mixed
    */
    public function update(Illuminate\Http\Request $request, App\User $user)
    {
        if ($request->ajax()) {
            try {
                DB::transaction(function() use ($request, $user) {
                    $user->update($request->only($user->getFillable()));
                });

                DB::commit();
            } catch (\Exception $e){
                DB::rollback();
                return response()->json($e->getMessage(), 422);
            }
        }
    }
}

Note I'm typing this without access to real code, so the $user->getFillable() may return a collection requiring you to convert it to an array. if that's the case, just chain $user->getFillable()->toArray() on to the end.

The magic in this is that if the process requests successfully, you can capture that with .done() on the promise object. If it fails, then you'll get a 422 Unprocessable Entity in Request message back which will trigger your .fail() on the promise object.

Now, simply extend this base UserController from both of your API/Web UserControllers:

<?php

namespace App\Http\Controllers\Api;

class UserController extends App\Http\Controllers\UserController {

}

While you have to do some duplication of logic, it's important to maintain that level of separation throughout your application stack for clarity. This method will still allow you a level of granular control if you still need to alter things for either of the routes, but gives you a base to work from.

Hopefully this helps.