next auth session data is always available in dev console - session

one question, maybe stupid, but I'm not able to figure it out.
I'm using next auth in nextjs for authentication.
this is the relevant part of email provider options I'm using
session: {
strategy: "database",
maxAge: 4 * 60 * 60,
updateAge: 2 * 60 * 60,
httpOnly: true,
sameSite: "strict",
secure: true
},
I'm using SSr on all pages and getSession in getServerSideProps to get the session
On each page I visit if I open the dev console under Network tab i see my session completly visibile.
I'm still in development so no HTTPS is used for now. later it will be introduced.
My understanding, maybe wrong, is that the session information are stored on the database and not on browser side.
I'm asking this becouse I want to add some relevant information inside the session object stored in the database and access it only on the server side but it seems that whatever i add to the session through session callback is not written in the db but visible in the browser.
I feel I miss some relevant point but I don't understand what
Thanks for any feedback

Related

Chrome not allowing Set-Cookie even from the same (sub)domain

Here is my configuration:
SERVER
Laravel 8 application that uses Sanctum to provide access to REST API. It is configured to run on http://b8/
CLIENT
A separate Vue CLI 3.0 SPA that connects to the API using session-based cookie authentication method. I have configured Vue CLI Serve to run it at http://app.b8/.
PROBLEM
Chrome does not allow Set-Cookie operation even when both server and client are on the same domain. After going through several posts and articles, I have successfully run it in Postman, but the real Vue application that runs in the browser can't set Sanctum cookie and thus cannot login.
Here is my configuration:
.env
SESSION_DRIVER=cookie
SESSION_DOMAIN=.b8
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:8080,127.0.0.1,127.0.0.1:8000,::1,b8,app.b8,app.b8:8080
vue.config.js
...
devServer: {
proxy: "http://b8/api/v1",
host: "app.b8"
},
Login function in Vue application
async login(context, credentials) {
axios.get('http://b8/sanctum/csrf-cookie').then(response => {
axios.post('http://b8/login', credentials).then(response2 => {
//successfully logged in.
});
});
},
Error msg
The outer call for /sanctum/csrf-cookie route returns successfully and brings Sanctum cookie. However, Chrome thinks that the cookie is invalid for the current domain and therefore doesn't set it. Here is the Dev Tools pane's Cookies tab after the Sanctum token call returns (tooltip showing Chrome's complaint):
Since the cookie is not set, the following login call fails with a 419 error.
What am I missing here?
Finally got it working. For any future reader, here are the things:
The first mistake that I was doing was to use a single word host name. It looks like Chrome (or Sanctum, not sure) wants you to have at least one period in the host name. So I changed it from b8 to b8.cod.
You should keep same_site attribute set to lax. none is a rather dangerous value. Chrome now shows none as a potential issue.
SESSION_DOMAIN should be set to .b8.cod with a leading period to support front-end subdomain, as correctly suggested by the documentation.
All other things should be done as suggested in the question. axios must use withCredentials set to true.
I've recently set up the exact same thing (Laravel 8 backend with Sanctum + separate Vue Frontend) and it's working.
Your server side setup looks good. Please double-check that the frontend's IP is actually included in your SANCTUM_STATEFUL_DOMAINS - that caused the 419 error for me sometimes.
On the Vue side, make sure to that you enable the withCredentials in your axios instance, e.g.
const baseDomain = "http://localhost"
const baseURL = `${baseDomain}/api`
export default axios.create({
baseURL,
withCredentials: true,
})
If the provided suggestion does not help, I can further extend my answer by showing you more of my working backend code.

Why doesn't the login session "stick" when login in using "ionic serve" window but works when I point the browser to the www folder?

I am using Ionic to build a login system on top of Codeigniter/Ion_Auth/codeigniter-restclient and when I try to login from "ionic server" the login works but the next api request to the logged_in() method returns false.
The same thing works properly when I point the browser to the www folder.
So here is the problem step by step:
run ionic serve
you see the login form (http://localhost:8100/#/app/login)
enter email and pass
the rest api returns "login successful"
$state.go('app.profile') works and redirects to http://localhost:8100/#/app/profile
REST get api/logged_in returns false and I redirect to the login page
If I do the same in a regular browser, step 1 becomes: open browser and go to http://localhost:8888/App/www/#/app/login, at step 6 REST get api/logged_in returns true and I don't get redirected to the login page, I stay on the profile page.
The code is the same. So my guess is that maybe ion_auth doesn't get the cookies it wants or the session is reseted. I am not sure at this point what the problem is. This is my first Ionic/App project so I might be missing something about the proper way to authenticate from a mobile app using code that works in browsers
Thank you
UPDATE:
It seems that when using the 'ionic server' window every request to the API triggers a new session. The new session is stored in the database and ion_auth tests the logged_in against that last one, which doesn't contain the login details.
you were taking about REST api and cookies and sessions. Cookies and sessions don't go with REST philosophy. Here is why.
Let me tell you how we accomplish this problem in our project. Basic way of knowing which user is requesting and if it has the access rights is by the 'Authorization' header value. You can use Basic Authentication, Barer or any other.
We generally prefer token based authorisation system. When a login is successful, server sends a token. In ionic app, we save it using a factory called SessionService. So whenever user logs in, token is stored and is used for every request. But token would be lost if user closes the app. So we can store it in local storage. User can then be directly redirected to dashboard until user logs out.
app.factory("SessionService", function($window){
var user={};
if ($window.localStorage['user']!=undefined){
user=JSON.parse($window.localStorage['user']);
console.log(user);
}
return{
isLoggedIn:function(){
return !isEmpty(user);
},
logout:function(){
console.log("logout")
user={};
$window.localStorage.clear();
},
setUser:function(data){
user=data;
$window.localStorage['user']= JSON.stringify(user);
},
getUser:function(){
return user;
}
}
})
Now in every web request, you can call SessionService.getUser().token when setting value Authorization header.
UPDATE:
Despite using cookies is not recommended, you can use it in your application easily.
If you are sending request with CORS, angular doesn't sends cookies with request.
One of the way address this issue is to send withCredentials: true with every request:
$http({withCredentials: true, ...}).get(...)
Read further about this here.
Hope this helps!

Laravel 5 non persistent session

I'm just installed a fresh L5 app. I'm attempting to use database driven sessions however a new session appears to be created on each page load.
Has anyone come across this issue and managed to resolve?
"_token" value is new on each refresh.
I'm happy that the cookies have been configured correctly.
Not sure where to look next.
Any suggestions would be a huge help.
Thanks in advance
Have you ensured your session domain is set correctly? Your session domain should be the domain alone, for example domain.com, no URIs or protocols (http://), etc.
You may also want to check that SESSION_HTTPS is set to false, unless you're accessing your site over https.
If either are not set correctly sessions will not be correctly stored by the browser, so each request results in a new session.
The _token key will always be a new value for each request, this is part of the CSRF security feature.

Auth::user() returns null with CORS requests

I have a site with a separate REST API on a subdomain, e.g. api.mysite.com, that I send CRUD requests to. The API sub-domain has this filter adding the appropriate headers to the response:
// Simple CORS handling
Route::filter('cors', function($route, $request, $response) {
$origin = Request::header('Origin');
$host = parse_url($origin, PHP_URL_HOST);
// Don't send response for external domains.
if (!in_array($host, Config::get('domains'))) {
App::abort();
}
$response->headers->set('Access-Control-Allow-Origin', $origin);
$response->headers->set('Access-Control-Allow-Headers', 'Accept, Accept-Encoding, Accept-Language, Content-Length, Content-Type');
$response->headers->set('Access-Control-Allow-Methods', 'DELETE, GET, PATCH, POST, PUT');
$response->headers->set('Access-Control-Allow-Credentials', 'true');
});
I'm also setting crossdomain: true and xhrFields: { withCredentials: true } on my jQuery $.ajax request. The requests manage to go through to the server, hit the appropriate routes, etc, but something is going wrong with the authentication process. Every time, Laravel acts as if the user hasn't logged in, causing requests to Auth::user() to return null. Inspecting the requests in Firebug shows that the Cookie header is sent in the request with the Laravel session id, but the server responds with SetCookie, as if trying to start a new session. I'm probably doing something dumb here, but I'm at my wits end trying to determine just what.
Update: From some debugging, I've found something interesting out. Not sure what it means, yet. To get to the page in question, the user must be logged in. Therefore, there is a laravel_session cookie in the browser when the page loads. I then send off a couple of (cross-domain) AJAX requests by interacting with the page. The first request has no cookie set at all and gets a new laravel_session cookie set from the server. The second request then includes that cookie, but the response to it sends back yet another new cookie, as if the back-end never got the memo about the first. I'm starting to wonder if this isn't something to do with cookie domains or some-such.
I finally figured it out.
First of all, the xhr and route filter were both configured correctly. The root cause of this problem was definitely a cookie issue.
The cookie domain for laravel_session was not initially set. Browsers interpret that to be a short-hand for "current domain". That is, app.mysite.com What I needed to do was explicitly set the value in Laravel's session.domain configuration to be ".mysite.com" That way, the same session cookie becomes available to app.mysite.com, api.mysite.com, and any other sub-domains of mysite.com Problem solved!
That said, there were two gotchas that I tripped over on my way to this solution:
The first was that cookies cannot be set for TLDs. I normally set up my development domain to be something like "mysite", leaving off the TLD. As far as DNS is concerned, that IS a TLD, and the cookies will fail. Once I changed my fake domain for development over to "mysite.dev", "mysite" was no longer a TLD, and the browser accepted cookies for it.
The second was that I had to remove my session cookie from my browser before I could log in to the new and different domain. I don't know why this is the case, but remember to clear your session cookie out when doing this.
Obviously, this is too much to ask your users to do. If you're putting this kind of change out into an already deployed site, you need to consider how to get your users migrated over to the cookie changes.
Since Laravel session cookies are set with an expiry time not too far into the future, one option is to simply deploy such changes when your users are not very active and accept the app appearing to be broken until all session cookies have expired. Only your currently and recently active users will be affected and the "solution" is nice and easy. But your app is broken for a while.
The other option is to change the name of the session cookie away from "laravel_session" at the same time that you change the cookie domain. This way, the new cookie sits beside the old one while the old ones expire and your app remains unbroken.

share authentication between domain and subdomain in symfony 2.1

In an application I implemented an javascript chat with long polling. Since there is just one Ajax Request per domain allowed I wanted to move the poll request to a subdomain.
So I have two domains:
dev.site.com
poll.dev.site.com
In my config.yml I entered the following:
framework:
session:
domain: .dev.site.com
cookie_domain: .dev.site.com
But Symfony does not keep me logged in if I try to poll on the sub-domain via Ajax.
Any idea on how to keep the session on the sub-domains?
I'm using the FOSUserBundle
First, the two applications need to share the fos_user table so they can reload the user when. As you have "one app and the two domains pointing to the same app." this should already be correct.
Next is to set the session cookie to be shared between the domain and the subdomain. The config in your question is correct. However for FOSUserBundle to be able to reload the user when you change from dev.site.com to poll.dev.site.com you need to share the session storage between the two domain.
The easiest way I can suggest is to store the session in a database. This is achieved by using the PdoSessionStorage available in Symfony. The official documentation covers how to setup the session storage to do that.
If all above is done correct you should not able to login to an secure area on dev.site.com, and then change the URL to an other secure area on poll.dev.site.com without any need provide login credentials again. Notice that the user credentials are only loaded in an secure area.
When it works to open poll.dev.site.com directly in the browser with any need to enter the credentials again. You need to do some additional work to get the Ajax request to work.
According to these two questions: Setting a cookie on a subdomain from an ajax request, multi-sub-domain cookies and ajax problems the problem is likely the http://en.wikipedia.org/wiki/Same_origin_policy.
The first suggests setting the following header fields on dev.site.com:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://poll.dev.site.com
And then passing withCredentials on the ajax request.
$.ajax({
url: 'http://poll.dev.site.com/some/ajax/endpoint.json',
xhrFields: {
withCredentials: true
}
});
I've tested it using a dummy file that would just set the cookie and try and ajax request. I got it to worked if I had withCredentials on the ajax request, but I could not see any difference when I tried with/without the Access-Control-Allow-* headers.
The other answer suggested using document.domain but I dodn't test that.
I used using Opera's Dragonfly to inspect the network trafic if the Cookie header was sent to the server when I tested. You can use Firebug, Chrome or probably IE too.

Resources