Laravel api routes with auth - ajax

I'm trying to make an api route that's only accessible if the user making the request is logged in. This is what I have in my routes/api.php but it returns
{"error":"Unauthenticated."}
Route::group(['middleware' => ['auth:api'], function () {
Route::post('schedules', ['uses' => 'Api\ScheduleController#store']);
});
Can this be done without laravel passport and how? I only need the route for in-app use for logged in users.

I assumed the login mentioned is on "web" which using "session" as driver.
Your are getting this issue because "web" and "api" guard is using different driver for authentication. Take a look in config/auth.php. The "api" guard is using "token" as it's default driver.
Thus, you have few options to encounter this.
Move the route for "schedules" in web.php. No worry, your ajax will failed if not authenticated. But, take note that anything that involved POST method will require csrf (_token parameter), unless you are using laravel axios
Using authentication using api also which you can refer this tutorial for "token" driver and all your secure routes will be using token in its Authentication header

Related

Laravel Jetstream/Sanctum API authentication

I have been working with Laravel since version 5.X up to version 8.X but always use it for backend API (never used blade template), and always pair it with VueJS on the front-end using JWT authentication (also never messed with any other authentication method).
Now with Laravel 9 and Vue 3, Im trying to use native Laravel Jetstream that uses SANCTUM and Vue+Inertia JS, and I'm quite lost with the authentication process. with JWT method, once the user succesfully login on the browser, all api request to Laravel will be authenticated using Authoraziation header. but this seems a different case with Sanctum.
After deploying and installing Jetstream and completed all the set-up. I created a user and loggedin with that user details. and I notice few things, there is a default API route
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
when I tried to directly access my.domain/api/user I notice it was redirected to GET /login
then redirected again to GET /dashboard
I then created a test api route using below
Route::get('test', function( Request $req) {
dd( [
'test' => $req->all(),
'user' => auth()->user(),
'request' => $req
] );
});
and I notice this request is not authenticated even when the cookies is present on the request as Im when I'm alraedy logged-in on the same browser, the auth()->user() is null.
I tried adding auth:sanctum middleware
Route::middleware('auth:sanctum')->get('test', function( Request $req) {
dd( [
'test' => $req->all(),
'user' => auth()->user(),
'request' => $req
] );
});
but having sanctum middle behave the same as the api/user where if i open api/test directly on the browser, it gets redirected to GET /login then redirected again to GET /dashboard and I'm quite lost at this point. I tried reading the docs and it says I have to do a separate authentication for this that would issue an API token and I was thinking I might better be going back with using JWT auth as it seems a lot easier to deal with.
So my question is; How can I authenticate an API end-point without having to redirect it to /login then /dashboard if the user is already logged in on my application using default sanctum authentication.
My goal is just to simply create /api/test that will be automatically authenticated if user already loggedin on the same browser and return the data I set on its return value and not doing any redirects.
Appreciate any help
I have got the same issue with laravel8
Jetstream and inertia vue3.
Am looking for the solution since 3 days posting messages on discord, searching on YouTube and more but nothing.
When i make an api call from your SPA to laravel, i got UNAUTHENTICATED response.
on postman you need put
headers
Accept = application/json
this tells your application know how works with Json
and go stop redirect to "Login"

Laravel - Protect API routes

I have Laravel application with VUEJS as front-end,
I am getting data by creating API Routes.
So for example the route for getting posts data will be http://localhost/api/posts
What is the best way to protect my routes?
I saw on laravel documentation that there is:
API athentication https://laravel.com/docs/5.8/api-authentication
also Passport https://laravel.com/docs/5.8/passport
For example now any user can reach to the route http://localhost/api/posts
and he will get json with all posts data.
I want protect that and allow only inner api request from my VUEJS commponent to get the data
I’m assuming you’re going to use the Laravel auth routes to do the authentication, and after the authentication, the next view you’re reaching is the one with all the Vue components.
The solution is simple, even that is on the documentation, the necessary steps should be clarified.
We need to:
Add passport composer require laravel/passport
Make the migrations php artisan migrate
Install passport php artisan passport:install
The fourth step is more complex. We need to open our User.php model file. And first we need to import the HasApiTokens and tell the model to use it.
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
.......
}
Then on our config/auth.php we need to modify the api array and change the driver to passport
'api' => [
//for API authentication with Passport
'driver' => 'passport',
'provider' => 'users',
],
Then on our app/Http/Kernel.php we need to add a middleware to the $middlewareGroups array in the key web.
protected $middlewareGroups = [
'web' => [
................
//for API authentication with Passport
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
Now we can use the auth:api middleware on our api routes.
Route::middleware('auth:api')->group( function(){
...your routes here
});
This is what the CSRF TOKEN doing, it's not quite the same with the API Authorization doing
CSRF Token:
To protect (inner) API or access points from cross-site accessing, See Cross-site_request_forgery
CSRF Token is expired and generated within a randomly time, which will make the program access difficulty
API Authorization:
The API is design to be used from other programs, and you'd like to protect them from non-authorized access
Since API tokens expiration and generation is handle by admin manually, since you'll need to place this API token in your HTML to get your function working, it's not what you searching for here
More details of CSRF protection in Laravel see: Laravel CSRF production document
Generally, we'll protect all the routes POST and PUT routes by default

Lumen: add middleware to package defined routes

I have a problem with adding middleware to existing routes of a vendor package. I building an API on top of Lumen (micro-services framework created by Laravel). I am using Passport for oauth authentication and imported this package: https://github.com/dusterio/lumen-passport to use Passport in Lumen. I have implemented a custom route for requesting a token and want to block requests to the existing passport route: /oauth/token. But I also need the route myself in order to redirect token requests from my custom route.
I have tried to override the existing route like this:
$app->post('/oauth/token', [
'middleware' => 'reject',
'uses' => '\Dusterio\LumenPassport\Http\Controllers\AccessTokenController#issueToken'
]);
But this throws a 500 back at me without Exception tracing.
I am using a custom route for requesting a token in order to set the set the token scope based on the role of a user. I am using the scope to check the role of a user (or app with other grant types), the normal token route of Passport should be blocked to everyone except Lumen self. With this only Lumen should be able to set the scope.
TLDR: How can I add middleware to package defined routes in Lumen.
The latest merge of https://github.com/dusterio/lumen-passport supports prefixing the passport routes.
I added "dusterio/lumen-passport": "dev-master", to my composer.json and Dusterio\LumenPassport\LumenPassport::routes($app, [ 'prefix' => 'api/v1/protected', 'middleware' => 'reject', ]); at the end of my bootstrap/app.php.
See this issue for additional information: https://github.com/dusterio/lumen-passport/issues/31

Laravel 5.4: how to protect api routes

I have a react app that fetch datas from laravel api defined like so in routes/api.php:
// this is default route provided by laravel out of the box
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
// ItemController provides an index methods that list items with json
Route::resource('items', 'Api\ItemController', array('except' => array('create','edit')));
// this is to store new users
Route::resource('users', 'Api\UserController', array('only' => array('store')));
for example http://example.com/api/items returns the data as intended but it's really insecure since anyone could access it through postman.
How to make those routes only accessible inside the app?
As I'm new to it I don't understand if I need to set up api_token and how?
Do I need to setup Passport?
Is is related to auth:api middleware?
It may sounds really basic but any help or tutorial suggestions would be greatly appreciated
EDIT
End up with a classic session auth. Moved routes inside web.php. Pass csrf token in ajax request. Actually i didn't need a RESTful API. You only need token auth when your API is stateless.
As you are using Laravel 5.4 you can use Passport, but I haven't implemented yet, but i implemented lucadegasperi/oauth2-server-laravel for one of my laravel projects and it was developed in Laravel 5.1
Here is the link to github repository
lucadegasperi/oauth2-server-laravel
Here is the link to the documentation Exrensive Documentation
Just add the package to the composer json and run composer update,the package will get installed to your application , once installed add the providers array class and aliases array class as mentioned in the Laravel 5 installation part of the documentation,
you have to do a small tweak in order to work perfectly cut csrf from $middleware array and paste it into $routeMiddleware array and again run php artisan vendor:publish after publishing the migrations will be created and run the migration php artisan migrate
if you only want to secure api routes for each client like ios, android and web you can implement Client Credentials Grant, or if you need to every user with oauth the you can implement Authorization Server with the Password Grant or some other.,
Never use the client id or other credentials, generating access token in the form, but add it some where in helper and attach it in the request to the api,
Hope this answer helps you.
You could use JWT it's pretty easy to get it to work. You basically generate a token by requesting Username/Password and passing that token in every request that requires authentication, your URL would look like http://example.com/api/items?token=SOME-TOKEN. without a proper token, he doesn't have access do this endpoint.
As for
How to make those routes only accessible inside the app?
If you mean only your app can use these requests, you can't. Basically the API doesn't know who is sending these requests, he can only check if what you are giving is correct and proceed with it if everything is in order. I'd suggest you to have a look at this question

Laravel 5.3 and VueJS 2 Authenticating

Im using Laravels default auth to lock down some paths in the routes/api.php file.
Route::get('/projects', 'ProjectController#index')->middleware('auth:api');
I log the user in via a PHP form (not via a http request via Vue).
This creates the session and when I submit a HTTP request via Vue I can see that the header includes the Cookie and X-CSRF-Token however I keep getting a 401 {"error":"Unauthenticated."}
In my config/auth I have api driver set as 'token' (have tried changing this to 'session' but that did work :/)
From my understanding and what I have read online I should be able to use the default Laravel auth functionality to accomplish API calls from Vue HTTP requests.
this.$http.get('/api/projects')
.then(response => {
this.projects = response.body;
})
.catch (err => {
console.log(err);
});
I've read about methods of authenticating by generating an JWT token and storing that in local storage when the user logs in. Is this the method I should use or should I be able to accomplish it with the default Laravel Auth middleware?
Hope my questions make sense, any help/advice would be appreciated.
The auth:api middleware doesn't use cookies, it uses api_token param, which can be passed via get or Bearer <token> header. Just use web middleware.
I suppose you need to access the same route in two ways - for API users and for browser users. So why don't you create two routes for one action?
// api group with /api prefix
Route::get('/projects', 'ProjectController#index')->middleware('auth:api');
// web group
Route::get('/projects', 'ProjectController#index')->middleware('web');

Resources