Laravel 5.4 session token changes on every request - php

I have a project on Laravel 5.4 and PostgreSQL. At each page request, the session is renewed with a new _token key and a new cookie. As a consequence, either authentication nor flash sessions message are not working.
Already tried :
Changed laravels' cookie name
Played with $domain variable in session.php, tried null, http://localhost:8000 and http://localhost
Switched from file to array and redis
Played with encrypted => false/true and all others booleans fields
Checking storage/sessions folder permissions (all set to 777)
In my routes.php file, replaced middleware by middlewareGroups
The RouteServiceProvider.php :
protected function mapWebRoutes(Router $router)
{
$router->group([
'namespace' => $this->namespace, 'middleware' => 'web',
], function ($router) {
require app_path('Http/routes.php');
});
}
(there is no web.php/api.php, etc... PHP files, the developper remapped all these files into routes.php).

Your domain is invalid. You need to look at config.session.domain and config.session.path.

Your browser will not store cookies for a domain without a dot. E.g. localhost. A simple fix is to add 'localhost.com' to your hosts file as 127.0.0.1.
Then you can use for example: localhost.com:8080

Related

Laravel - Working with sessions between controllers

I need to show some values in all app, and sometimes I need to use these values between controllers.
I was trying to use Session, but I maybe it is not the answer to that, because if I am not wrong, Laravel store the session data temporarily in memory and only after everything has been executed, will it dump the session data into storage (file, cookie, redis, whatever).
So for example, I have a controller like that:
class GiftController extends Controller
{
public function dashboard(){
$token = (Session::has('token')) ? Session::get('token') : NULL;
if (is_null($token)){
return view('test.erro', ['message' => 'no session!']);
}else{
return view('test.ok', ['message' => $token]);
}
}
public function setsession(){
Session::put('token','xxxxxxxxxxxx');
return redirect('test/dashboard');
}
}
In this case, if I do an echo on Session::get('token') into the setsession(), is showing the value, but when it goes to the dashboard(), the session shows nothing.
What I am doing wrong?
or What is the better Idea to use instead off session?
I am using the Laravel Framework 5.8.37
I found the solution but I got it with the markskayff help.
He told me to Check my .env file, and he was right! It was a different SESSION_DRIVER value from config/session.php
In config/session.php was 'driver' => env ('SESSION_DRIVER', 'file')
Despite not having .env file but app.yaml since I am doing this project in GCP app engine, the session in this file was SESSION_DRIVER: cookie.
So I changed in config / session.php the line 'driver' => env ('SESSION_DRIVER', 'file') to 'driver' => env ('SESSION_DRIVER', 'cookie').
And now it is working!

Share Laravel Session on Subdomains with different guards

I'm currently using spatie/permissions and a Subclass of User with constraints to permissions to Login to subdomains in my application.
I now want to be able to share the session between my main domain example.com and the domains some.example.com where some is dynamically loaded from database.
When my logged-in User in example.com accesses the abc.example.com domain and is able to log in there I want to use the current session.
I use different guards on subdomain and domain with the SubUser and User classes as providers.
I already use the database session driver and can see in the logs that the same session id is loaded from database.
As the application is loading the same session from database I'm wondering why my user is not already logged in.
Anyone ever tried this and got a solution for this?
So I managed to resolve this issue.
My setup is all subdomains got the user guard and the main domain has the admin guard.
I realised that the Auth::getName() included the guard name and as I logged in using different guards I ended up having two active logins in one session. But these logins had different names and where only valid with the right guard. This guard being different in main domain and subdomains resulted in not really sharing login-state over domain and subdomains.
I managed to resolve this by overriding the default laravel SessionGuard and adding my own driver like so:
In config/auth.php:
'guards' => [
'user' => [
'driver' => 'extended_session',
'provider' => 'users',
],
'admin' => [
'driver' => 'extended_session',
'provider' => 'admins',
],
]
In AppServiceProvider.php
\Auth::extend('extended_session', function ($app, $name, $config) {
$providerConfig = $this->app['config']['auth.providers.'.$config['provider']];
// If you don't use eloquent you need to alter the next line accordingly
$provider = new EloquentUserProvider($app['hash'], $providerConfig['model']);
return new SessionGuardExtended('extended_session', $provider, $this->app['session.store']);
});
And add a new Class named SessionGuardExtended like this:
use Illuminate\Auth\SessionGuard;
class SessionGuardExtended extends SessionGuard{}
This results in a shared session with the same auth name for domain and subdomains.
Add SESSION_DOMAIN to your .env file and set it to .example.com

Api routes not working in laravel 5.4

I am trying to call an api route from postman like this
http://project.app/api/someroute
But it does not work and through that error
file_put_contents(/home/vagrant/Code/project/storage/framework/cache/data/a0/c6/a0c65d98bc6f1fe2c35f8ba5fd47c8a3e225165e): failed to open stream: No such file or directory
Create this directory manually:
/storage/framework/cache
Also, make sure you have:
/storage/framework/views
/storage/framework/sessions
Usually, you'll also need to set the right permissions on the storage directory:
chmod -R 755 storage
Couple things to check
1) Make sure you add an api_token column to your users database.
$table->string('api_token', 60)->unique()
2) Add a random 60 character string to that column
3) Add a route to your api.php routes file
Route::group(['prefix' => 'v1', 'middleware' => 'auth:api'], function ()
{
Route::get('test', function(){
return ['name' => 'zechdc'];
});
});
Notice I added a prefix of v1. Looks like laravel already adds an 'api' prefix as well.
4) Visit your url and append your api_token you created for a user. You should see some JSON on your screen at this point.
http://localhost/api/v1/test?api_token=wwfaadmcmsvbtldzxlenjxhxakwyriwhrxcbkgfpnlccyhhxexvzfixxjtjq
Source: https://laracasts.com/discuss/channels/laravel/53-api-routes-auth-middleware-confusion?page=1

Laravel 5.3 API

When user enter username and password on the the browser and successfully logged in.
I like to make some API requests after user have logged in.
Laravel 5.3 provide api.php in routes folder.
in api.php I have included:
Route::group(['middleware' => ['auth']], function () {
Route::get('/test', function (Request $request) {
return response()->json(['name' => 'test']);
});
});
When requesting domain.com/api/test on the browser, for some reason it is redirecting to /home?
API token is not needed.
If you are specifying routes in api.php, you will need to use the auth:api middleware. So using your example it would be:
Route::group(['middleware' => ['auth:api']], function () {
Route::get('/test', function (Request $request) {
return response()->json(['name' => 'test']);
});
});
Notes about Token auth and Laravel 5.3:
If you've setup laravel's default auth system, you will also need to add a column for api_token to the user table. If you are using DB seeders, you might want to add something like:
$table->char('api_token', 60)->nullable();
to your users table seeder. Alternatively just add the column manually and fill that column with a random 60-char key.
When making the request, you can add the api_token as a URL/Querystring parameter like so:
domain.com/api/test?api_token=[your 60 char key].
You can also send the key as a header (if using Postman or similar), i.e:
Header: Authorization, Value: Bearer [your 60 char key].
I order to get a useful error if the token is incorrect, and not just be redirected to login, also send the following header with all requests:
Header: Accept, Value: application/json. This allows the expectsJson() check in the unauthenticated() function inside App/Exceptions/Handler.php to work correctly.
I found it hard to find clear docs from Laravel about using token auth with 5.3, I think it's because there's a drive to make use of Passport, and it supports tokens in a different way. Here's the article that probably helped most getting it working: https://gistlog.co/JacobBennett/090369fbab0b31130b51
first install the passport as stated here laravel passport installation
while consuming your own api add below line in your config/app.php in middleware section
'web' => [
// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
now change your route to
Route::group(['middleware' => ['auth:api']], function () {
Route::get('/test', function (Request $request) {
return response()->json(['name' => 'test']);
});
});
now in your config/auth.php change these lines
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
The reason you are being redirected back to home is because the auth middleware checks if a user session is stored in your browser, but since api middleware does not make use of sessions (see app\http\kernel.php), your request is considered unauthenticated
If you would like to perform simple APIs that utilize sessions, feel free to add them in your web routes, and make sure to secure them by grouping them inside an auth middleware.
The standard behaviour in Laravel 5.5 is to delegate handling of authentication exceptions to app/Handler::unauthenticated(), in your project's application code. You'll find the code in there that redirects to the login page, and you can override it or perform further tests and contextualization in there. In previous versions of Laravel, 5.3 among them I believe, this exception handling was executed way down within the Laravel library within the vendor folder.

Laravel 5 - session doesn't work

Here's config/session.php:
return [
'driver' => 'file',
'files' => storage_path().'/framework/sessions',
];
My storage/framework/sessions have 755 permissions.
When I put these 2 line in my controller
Session::set('aa', 'bb');
dd(Session::get('aa'));
I receive expected "bb" output. But if I comment first line:
// Session::set('aa', 'bb');
dd(Session::get('aa'));
and refresh page, I still expecting "bb" but getting null.
Also, storage/framework/sessions is empty.
What should I do to make Session working?
Laravel 5 handles sessions via a middleware class called StartSession. More importantly, this middleware is a TerminableMiddleware and the code that actually saves the data (in your case to the session file) is located in the terminate method, which is run at the end of the request lifecycle:
public function terminate($request, $response)
{
if ($this->sessionHandled && $this->sessionConfigured() && ! $this->usingCookieSessions())
{
$this->manager->driver()->save();
}
}
When calling dd(Session::get('aa')); the request is being interrupted before the terminate method of the middleware can be called.
Funnily enough, the Laravel Middleware Documentation actually explains Terminable Middleware logic by giving the Laravel StartSession middleware as an example:
For example, the "session" middleware included with Laravel writes the session data to storage after the response has been sent to the browser.
That being said, try using var_dump() instead of using dd().
With laravel 5.*, you must change the kernel file like bellow:
'api' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Session\Middleware\StartSession::class,
'throttle:60,1',
'bindings',
],
then go to storage/framework/session folder and change the permission to 755 if it has another amount, then delete all files in your storage/framework/session path, use your code again to put something in a session, watch the storage/framework/session folder.
If your session work you can see the weird long file that belong to session right now, and you are done!
If your problem is not yet solved, go to config/session and change:
'driver' => env('SESSION_DRIVER', 'file')
to another predefined amount like:
'driver' => env('SESSION_DRIVER', 'array'),
or even
'driver' => env('SESSION_DRIVER', 'database'),
and finally if you have an empty folder of storage/framework/session, you still have a problem for sure !!!
if you're use api route , you might have this problem with your session and most of the time sessions return null ,
try to use web route for this

Categories