baguus
1 year ago

web and api authentication middleware

Posted 1 year ago by baguus

Hi everyone. sorry for the "undefined" title. I don't know how to phrase is correctly. I have a view in my app that is accessible to authenticated users.

web.php

Route::get('/orders/complete', [
    'as' => 'completeOrders', 'uses' => '[email protected]']);

OrdersController.php

    public function completeOrders(Request $request)
    {
        if (!Auth::check()) {
            return redirect('/');
        }
        $request->user()->authorizeRoles(['admin']);

        $orders = Order::CompleteOrders(AppHelper::instance()->getCurrentSeason())->get();
        return view('orders.complete', compact('orders'));
    }

View

<meta name="csrf-token" content="{{ csrf_token() }}"/>

<table id="completeorders">
    <thead>
            <tr>
                    <th>Order ID</th>
            <th>Country</th>
            <th>Company name</th>
            <th class="check">Confirmed</th>
            <th>View</th>
        </tr>
    </thead>
    <tbody>
    @foreach ($orders as $order)
        <tr>
            <td>{{ $order->id}}</td>
            <td>{{ $order->country }}</td>
            <td>{{ $order->name }}</td>
            <td>{{ Form::checkbox($order->id, $order->id, $order->confirmed, ['class' => 'checkbox fa-fw', 'id' => $order->id]) }} </td>
            <td><a href="{{ url('orders/cartcomplete/' . $order->id) }}"><i
                                                class="fa fa-search fa-fw"></i></a></td>
        </tr>
    @endforeach 
    </tbody>
</table>

my.js

$(document).ready(function () {

$('#completeorders').on('click', 'input[type="checkbox"]', function (e) {

        var isChecked = $(this).is(':checked');
        e.preventDefault();
        
        var checked = '';
        var dataId = $(this).val();
        var myid = "#" + dataId;

        var url = window.location.protocol + "//" + window.location.host + "/" + 'api/orders/complete';
        var token = $('meta[name="csrf-token"]').attr('content');
        
    $('html, body').css("cursor", "wait");
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });

        $.ajax({
            type: 'POST',
            url: url,
            dataType: 'JSON',
            data: {
                "_method": 'POST',
                "_token": token,
                "id": dataId,
                "isChecked": isChecked
            },
            context: this,
            success: function (response) {
                console.log('success');
        console.log(response[0].successful);
        $(this).prop("checked", isChecked);
                $('html, body').css("cursor", "auto");
            },
            error: function (e) {
              //  console.log(e.responseText);
                $(this).prop("checked", !isChecked);
        $('html, body').css("cursor", "auto");
            }
        });
    });

});

Kernel.php

 protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
        //    \Illuminate\Session\Middleware\AuthenticateSession::class,
        //    \App\Http\Middleware\VerifyCsrfToken::class,
            'throttle:60,1',
            'bindings',

        ],
    ];


    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'admin' => \App\Http\Middleware\Admin::class, 
        'ajax' => \App\Http\Middleware\AllowOnlyAjaxRequests::class,
    ];

VerifyCsrfToken.php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        //   'ajax/*',
    ];

    protected function tokensMatch($request)
    {
        $token = $request->ajax() ? $request->header('X-CSRF-Token') : $request->input('_token');
        return $request->session()->token() == $token;
    }
}

api.php

Route::post('orders/complete', '[email protected]');

ConfirmatonController.php

 public function confirm(Request $request) {

return response()->json(array(['successful' => 'Response ok!']));

So up to here the api call works but is not verified.

How do I verify/authenticate this api call?

If I change my api.php to

Route::group(['middleware' => ['web']], function () {
    Route::post('orders/complete', '[email protected]');
});

i get 408 TokenMismatchException

How can I verify this correctly. I want to allow the post call only if the user is logged in.

Please sign in or create an account to participate in this conversation.