Have you dug into their docs, i.e., https://datatables.net/examples/api/api_in_init.html
API Calls From Datatables Not Authorized
Hello all.
I have some datatables being called via api in some views. They exist from the previous developer.
I just realized that they were outside of any authentication and available to the public, so I moved it inside of the auth:api middleware and now I get a 401.
Route::group(['middleware' => 'auth:api'], function() {
//dd(request()->cookie('laravel_token')); // always produces a valid token
Route::get(
'/datatables/users',
'Builder\UserApiActions@getDataTableData'
);
});
I included the CreateFreshApiToken middleware from Passport and with the commented out dd call I can see that a valid token is being sent on each request.
Why would I be getting a 401?
Does everything work ok when you remove the middleware?
Can you share the route details from php artisan route:list | grep -i datatables
Can you also share the section of you front end code that is trying to consume this end point.
Try changing it to a post route. Lots of info if you google "laravel datatables 401". Also if you're using a FormRequest object for validation, make sure it's returning true in the authorize() method.
It's not a datatables issue, I can't hit anything inside the auth:api middleware, even the default
axios.get('/api/user')
.then(response => {
console.log(response.data);
});
fails using both axios and jquery. Always returns 401 Unathorized with the Unauthenticated message.
And before you ask, I do have passport set as my auth driver for the api routes.
Yes, when I remove the routes from behind the middleware it works perfectly.
Here's the code that's inside the view, not sure how this would help but as requested:
@push('scripts')
<script>
$(document).ready(function() {
$('#datatable-users').DataTable({
'processing': true,
'serverSide': true,
'ajax': '/api/datatables/users',
'pageLength': 25
});
});
</script>
@endpush
Any chance I can get you to weigh in on this?
Why can't I access my own API when it's behind the auth:api middleware? What do I need to do to fix this?
Thanks.
what does the config file look like? Are you using tokens? passport? jwt?
Depending on your response, are you properly sending your api headers through (Bearer and those things)?
Does everything work 'without' the auth:api?
Was your auth:api working previously? Did you add anything new that could be causing this?
Config uses Passport.
Bearer token shouldn't be needed, I'm consuming my own API as per the documentation: https://laravel.com/docs/5.5/passport#consuming-your-api-with-javascript
Yes everything works fine outside of the call to auth:api
First time I've tried to use the middleware.
Thanks for your help.
Interesting, then I am not sure. My API generally does not 'consume' itself. Users consume it, and I treat them as if they are outsiders. My API does not distinguish between who is using the api... it treats everybody (including itself) the same. (This has its flaws haha)
Thanks anyway, hopefully Bobby will chime in here, he usually finds these things straight away.
I was trying to figure out how I can intercept this before it throws the 401 to see what's happening in Passport or wherever it's failing ... but I haven't had any luck doing that yet either.
Just to be sure, your middleware are registered in the correct order
You should ensure that the EncryptCookies middleware is listed prior to the CreateFreshApiToken middleware in your middleware stack.
Yes CreateFreshApiToken is listed last in the stack.
protected $middlewareGroups = [
'web' => [
\App\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
I need to re-answer part of your initial question.
Other api calls do work when outside the auth:api middleware, but the call to user returns an empty response.
Route::get('/user', function (Request $request) {
return $request->user();
});
returns nothing.
Even if I just return the $request I get nothing but an empty array.
Route::get('/user', function (Request $request) {
return $request;
});
Response = []
Something is amiss here.
Basically you 'user' is not authenticating so thus it will fail to provide you a user.
Additionally if the authentication is not properly functioning (by this I mean re-auth via middleware, not login), you will have a null user, and thus fail the auth:api checks.
This doesn't make sense. By definition, the CreateFreshApiToken middleware adds a laravel_token cookie to each response that contains the authenticated user's information.
When I look at the my list of cookies in Chrome I can see that the cookie exists, with my api guard set to passport, Passport should resolve this cookie to push the user model on to the request object.
Clearly this isn't happening as my request object is completely empty.
You are not replacing/changing this request object in your app anywhere (I mean i doubt it... but maybe???).
It seems very strange, are you using telescope on this? It does a pretty fantastic job of showing full requests, headers, and all that... might help debug, as long as you are at 5.7.7+
No this app isn't in a place yet to be able to be upgraded to 5.7. I took it over about a year ago and have been trying to slowly replace all the terrible spaghetti left by the previous dev.
It's in production, making that much more difficult as the owner is constantly adding new features so as to make getting it cleaned up and refactored that much more time consuming.
And no, I'm not modifying the request anywhere.
What is the version of laravel? Maybe there is something specific with passport version and the laravel version? It could happen maybe...
If the requests are coming from an authenticated user's browser then the whole passport / api thing is an unnecessary complication?
Yeah I'm at that point, I guess I'll just move them into the web routes, but I'd still like to know why this doesn't work as expected.
Using Laravel 5.5.44 and Passport 4.0.3
Please or to participate in this conversation.