I'm experiencing a problem with sessions in Laravel. My project consists about two projects, one an API and another a WebApp. Both with Laravel 5.5.
The problem is that I want to save a session in my API project but it isn't saved. I save the session like this in api.php:
Route::get('test', function () {
session(['data' => "data"]);
session()->save();
});
If I visit: http://mydomain.dev/test through Firefox, I can see the session in the Laravel DebugBar because it has been saved:
If I make a request with Postman to that URL, session doesn't appear in the Laravel DebugBar! It isn't saved.
After some research, I found this question and people say to include in Kernel.php these two lines:
protected $middleware = [
//...
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
];
I have already added those two lines and the problem persists.
The same happens with Guzzle. From my WebApp, I make a GET call to my API. In the method called in the API, I save a session, and when I retrieve the session in another method of the API, I get null because session hasn't been saved!
My suspicion is that Postman and Guzzle problems with sessions are related, and that there's something I'm missing.
My config\session.php files are as default. I know I have as alternative to save sessions in database, but I would prefer to keep it as default, but if I don't have any alternative, I will change my SESSION_DRIVER option from session.php from file to database.
APIs are and should be sessionless/stateless.
They can not handle it.
That's why token based authentications are used.
In order to make you sure about it. Write a route in web.php file and hit it from postman or browser then you will see a session info if any.
Related
I have tried so many options I could think of or find online, user details are still persisted even after successful deletion of all the tokens!
I am using Laravel sanctum with Vue. The logout function I created works as expected when I use postman to make the request, but this is not the case when I make the request via axios from the browser. The tokens gets deleted quite alright but I still can access protected routes.
I have also tried
Auth::logout()
I have continued to try this using sanctum and web as guard.
Any help will be appreciated.
I am using Laravel 5.8 with Passport 7.2 for building API for my application. I am using password_grant for authentication.
I have created everything from registration to login and everything seems to function properly. I am able to get access_token and refresh_token and to access routes that has middleware auth:api attached.
In my routes i have this:
Route::group(['middleware' => ['auth:api']], function () {
...
Route::get('test', function (Request $request) {
return $request->user();
});
...
});
When i call this /api/test URL with header Authorization: Bearer access_token i am getting currently authenticated user. That just works fine.
I am testing these endpoints with Postman, but everything is same if i test this using javascript from browser.
The problem is when i have two different access_token from two different users. If i call this URL with one access_token i get correct user data as response and if i wait for few seconds and call same URL with second access_token i get correct second user data as response. But if i call this URL two times with these two access_tokens at same time (call first and for example after half second call second) i get first call user data as response in both requests.
I hope you can understand what is problem.
Could this be caching problem, or maybe session problem (even if api is stateless)?
If you need more informations just tell me.
Firstly i thought it was browser cache issue, but it is same in postman. I have also tried to use Google Chrome for one request and Mozilla for second and everything is same.
If you have any idea about what could be wrong i will appreciate it :D
I have found a solution. It is not Laravel or Passport problem.
The problem was:
on my server we have Nginx and https://engintron.com/ configured and this Engintron has some micro-caching mechanism.
This micro-cache could be completely disabled or can be disabled with headers in request (Cache-Control: private).
Micro-cache is caching GET request to URL for 1 second and ignoring different Authorization headers. That's why i get same user data for two different Authorization headers if i make these two requests in under 1 second period.
I hope this will help someone else in future. If somebody need more info do not hesitate to contact me :D
Eloquent: API Resources
I am Trying to Crud a table using POSTMAN and laravel Api Resources. ]
Although using get method i can get all the data. When i use delete or post method, it returns an error of session expired.
Thanks in advance.Image Of POSTMAN
Image of routes
Sounds like you're missing the CRSF token, which would explain why HTTP GET's are working. One option to work around this is to disable the CSRF middleware when working in your development environment. Simplest solution is to open up app/Http/Middleware/VerifyCsrfToken.php and set:
protected $except = [
'*',
];
The * is a wildcard-like option that will disable CSRF verification for all routes. Obviously ideal solution would to be to disable it on a higher level only when working on local development, but the provided answer is a quick solution.
See the Laravel documentation on CSRF Excluding URI's
Sorry for the trouble. I found the problem,actually i was posting the routes in web.php instead of api.php . That was why i was getting the errors. Thankyou for the concern.
Usually I save temporary data/array inside session while working with Website (Non API).
Today I want to do the same thing (save temporary data/array inside session) with Laravel API.
So here is my route.
Route::middleware(['auth:api', 'isMember'])->group(function () {
Route::get('createSession', function (){
$a = Session::put('example', 'this is example session.');
return "session created";
});
Route::get('getSession', function () {
return Session::get('example');
});
});
When I visit /api/createSession it return session created, but when I visit /api/getSession it return nothing.
So how do I work with session inside API?
What I think why this not work because API use Token based authentication instead of Session based Authentication, refer to config/auth.php Authentication Guards section.
If work with session inside API is consider as bad practice, What is your suggestion to save temporary data/array inside API for shared hosting?
What I have tried so far is save data/array in Storage::disk(local) but I don't think it best practice.
Thanks in advance.
PS: I will use Session to store temporary data about Cart
Middleware api did not include StartSession middleware, so you can not get the session. Check it here: https://github.com/laravel/laravel/blob/master/app/Http/Kernel.php#L33
You can add middleware "web" to your route or add \Illuminate\Session\Middleware\StartSession::class, to middleware api but I'm not recommended it. APIs should not use session.
Hope that it can help you.
open app/Http/Kernel.php and then , add \Illuminate\Session\Middleware\StartSession::class, on array protected $routeMiddleware and add on protected $middlewareGroups on api
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