How to read cookies in getStaticProps and getStaticPaths in Next.js - cookies

I cannot read cookies in getStaticPaths and getStaticProps, in SSR, I can request the cookie with context but even with packages such as js-cookie, cookie-cutter, cookies, I am unable to read the cookies set, which makes it impossible to get the data.
This is the token I want to get, I removed httpOnly for development.
export async function getStaticPaths(){
const data = await callApi("/jobs", "GET", token)
const paths = data.map(jobs => ({
params: {slug: jobs.slug}
}))
return{
paths,
fallback: true,
}
}
This is the getStaticPaths.

both getStaticPaths and getStaticProps are methods that run on the server (node.js), therefore cookies which is a browser API are not available yet

Cookies can be accessed both on the server req.cookies or req.headers.cookie and on the client document.cookie. But unlike getServerSideProps where the HTML is generated at runtime, getStaticProps generates the HTML at build time and therefore has no know knowledge of requesting devise/browser. This is evident from how user-agent looks when the request is sent from getStaticProps:
'user-agent': 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'
Also, there's a demo app here showing how this all works.
If your reason for trying to access cookies from getStaticProps is for authentication, have a look at this post on The way they built the zeit.co/vercel dashboard (fully static)
Also here, using next-redux-wrapper to access state from getStaticProps.

if you have placed your cookies and want to read them you can get them in getServerSideProps ctx.req.cookies here your cookies
here is the link so you shouldn't try getting cookies in getStaticProps
https://github.com/vercel/next.js/discussions/11734#discussioncomment-3993

Related

Why am I getting "Indicate whether to send a cookie in a cross-site request by specifying its SameSite attribute"?

In a Chrome warning, it says:
Specify SameSite=None and Secure if the cookie should be sent in cross-site requests. This enables third-party use.
How do I do this correctly using express-session?
app.use(
cors({
credentials: true,
origin: ["http://localhost:3000", "https://elated-jackson-28b73e.netlify.app"] //Swap this with the client url
})
);
var sess = {
secret: 'keyboard cat',
cookie: {}
}
if (app.get('env') === 'production') {
app.set('trust proxy', 1) // trust first proxy
sess.cookie.secure = true // serve secure cookies
sess.cookie.sameSite = 'none'
}
app.use(session(sess))
you are getting this because you are using a resource from another site and that server is attempting to set a "cookie" but, it does not have the SameSite attribute set, which is being reported in newer versions of browsers.
this (may) also be shown if you are trying to access the server page from local computer (xampp), which generally doesn't has SSL installed;
set the header line in your server page (if in PHP) as below:
header("Set-Cookie: cross-site-cookie=whatever; SameSite=None; Secure");
(remember: this must be solved from the server side.)
i got the same issue when run my code in localhost. The affected resource is _ga, _gid, _utma, _utmz. All of them from unpkg.com
and i got marker image leaflet failed request but doesnt affect the page.
since i dont understand what the specific problem so i just delete the affected resource cookies in inspect element and the code will run without notif again.
thought i know if it's better to not answer based by personal experience. just tell me if it's not help at all.
If you are using Google login button or any other identity service add this:
<GoogleLogin onSuccess={() =>()} onError={() => ()} cookiePolicy='single-host-origin'/>

How to work with sessions in Vue and Flask?

You know, web applications needs sessions or cookies to authentication. I trying to build web application with Vue.JS and Flask microframework for example ERP or CRM.
I'm confused. How can I work with sessions? Let's think we have a code like this in the Flask:
import os
from flask import Flask, request, jsonify, abort, session
app = Flask(__name__)
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY') or \
'e5ac358c-f0bf-11e5-9e39-d3b532c10a28'
#app.route('/login', methods=['POST'])
def user_login():
user = request.form['user']
session['isLogged'] = True
return jsonify({'status': session['isLogged']})
#app.route('/user-info')
def user_info():
if 'isLogged' in session:
return jsonify({'user': 'ali'})
else:
return jsonify({'error': 'Authentication error'})
and our front-end codes should be like this:
mounted() {
this.checkIsLogged();
},
methods: {
checkIsLogged() {
fetch('http://127.0.0.1:5000/user-info', {
mode: 'no-cors',
method: 'GET',
}).then((resp) => {
return resp;
}).then((obj) => {
if(obj.user) {
this.status = true
}
})
},
login() {
let frmData = new FormData(document.querySelector("#frmLogin"));
fetch('http://127.0.0.1:5000/login', {
mode: 'no-cors',
method: 'POST',
body: frmData,
}).then((resp) => {
return resp;
}).then((obj) => {
this.status = obj.status
})
}
}
Everything is normal until I refresh the page. When I refresh the page, I lose the sessions.
Server-side sessions are important for many reasons. If I use localStore or something like that how could be secure I have no idea.
I need some help who worked on similar projects. You can give me suggestions. Because I never worked similar projects.
Other stuff I've read on this topic:
Single page application with HttpOnly cookie-based authentication and session management
SPA best practices for authentication and session management
I'm still confused to about what can I do.
Session handling is something your SPA doesn't really care much about. The session is between the user-agent (browser) and the server. Your vue application doesn't have much to do with it. That's not to say you can't do something wrong, but usually the issue is not with your front end.
That being said it's tough do give an answer to this question because we don't really know what's wrong. What I can do is give you instructions on how you can diagnose this kind of problem. During this diagnosis you'll figure out where the actual issue is and, at least for me, it usually becomes obvious what I need to do.
Step 1)
Use some low level HTTP tool to check the Server response (personally I use curl or Postman when lazy). Send the login request to the server and take a look at the response headers.
When the login is successful you should have a header "Set-Cookie", usually with a content of a "sessionid" or whatever key you're using for sessions.
If you don't see a "Set-Cookie" one of the following is true:
Your server did not start a session and thus did not send a session cookie to the client
there's a proxy/firewall/anti-ad- or tracking plugin somewhere filtering out Cookies
If you see the Set-Cookie Header continue with Step 2, otherwise check the manual in regards to sessions in your chosen backend technology.
Step 2)
Thankfully most modern browsers have a developer console which allows you to do two things:
1) Check your HTTP request headers, body and response headers and body
2) Take a look at stored cookies
Using the first feature (in Chrome this would be under the "Network" tab in the developer console) diagnose the request and response. To do so you need to have the developer console open while performing the login in your app. Check the response of the login, it should contain the Set-Cookie if the login was successful.
If the cookie is not present your server doesn't send it, probably for security reasons (cross-origin policies).
If it is present, the cookie must now be present in the cookie store. In chrome developer console, go to the "Application" tab, expand Cookies from the left menu and take a look at the hosts for which cookies are present. There should be a cookie present which was set in the step before. If not the browser didn't accept the cookie. This usually happens when your cookie is set for a certain domain or path, which isn't the correct one. In such a case you can try to set the domain and/or path to an empty or the correct value (in case of the path a "/").
If your cookie is present, go to step 3
Step 3)
Remember when I said the app has nothing to do with the session. Every request you send either with ajax or simply entering a valid URL in the browser sends all cookies present for this host in the request headers. That is unless you actively prevent whatever library you're using to do so.
If your request doesn't contain the session cookie one of the following is usually true:
the usage of your http library actively prevents sending of cookies
you're sending a correct request but the cookie-domain/path doesn't match the request host/path and is thus not sent along
your cookie is super shortlived and has already expired
If your cookie is sent correctly then your sessions handling should work unless your server doesn't remember that session or starts a new session regardless of an existing session.
I realise this question is quite old and this extensive answer comes way too late, however someone with similar problems may be able to profit from it.

send a cookie with XMLHTTPRequest (TVMLJS)

I am developing an application for my AppleTV. The App will read movies from an online website that hasn't developed any API for this kind of thing.
I use XMLHTTPRequest to get the different URLs and have the user search for his movie, etc... Everything is working fine, except for a single request. To get the movie URL, I have to send a get request to a specific address (let's say http://example.com/getmovie.html) with a constant cookie (let's say mycookie=cookie).
I've tried using setRequestHeader:
var xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.withCredentials = true;
xhr.setRequestHeader('Cookie', 'mycookie=cookie');
xhr.send();
But no cookie seems to be sent.
I also tried setting the cookie with Document.cookie like I would have probably done in a "normal" js script (running in my browser) but no luck either.
This is extremely frustrating, especially since I'm stuck so close to the end of my app.
I guess cross-origin might be the issue but I'm able to get URLs without issues if I don't have to set cookies, so I am a bit lost there.
Please let me know how I can get http://example.com/getmovie.html with a specific cookie header.
Thanks for your help
im sorry to inform you but the xmlHTTPRequest function of javascript does not allow a cookie header to be set for security reasons as shown here: Why cookies and set-cookie headers can't be set while making xmlhttprequest using setRequestHeader? the best way i could see you making that get request would be to a proxy server that you would be running. I believe that it is built this way to prevent you from setting cookies on domains that you do not own, furthermore i do not see an alternate resolution to this problem as no were in the docs i looked at was cookie persistence or management mentioned
In case someone has the same issue:
I didn't find a solution to sending a cookie with javascript. However, in my situation, the origin of the request didn't matter, only the cookie did. My solution was then to create a PHP file receiving the destination URL and the cookie content as parameters, and then sending the get request with the cookie as a request header. (more information about how to do so here: PHP GET Request, sending headers).
In my javascript I then use XMLHttpRequest to connect to my PHP file (hosted online) with simple get parameters and I then receive the response from the PHP. That trick of course won't work if the origin of the request matters (except if you host your file at home I guess, but in my case I want my application to work even if my WAMP isn't on).
Well... the problem here is the line xhr.setRequestHeader('Cookie', 'mycookie=cookie'); line just because the 'Cookie' header is reserved for the client browser to send the stored cookies. This means you are trying to do what the browser already does. When you send a any request, the client browser automatlycally will take all the cookies related to the site you are requesting and put them on the 'Cookie' header, you don't need to do anything else, if your cookie exist in your browser, it will be send.
Cordova how to send session cookie, allow credentials with XMLhttprequest:
// JS
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/ajax.php', true);
xhr.withCredentials = true;
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
// alert(xhr.responseText);
// Get header from php server request if you want for something
var cookie = xhr.getResponseHeader("Cookie");
// alert("Cookie: " + cookie);
}
}
xhr.send();
// Php
// You can add cookie to header and get with (session works without it)
header('Cookie: PHPSESSID='.$_COOKIE['PHPSESSID']);
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization, X-Request-With, Set-Cookie, Cookie, Bearer');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400');

How to store and reuse cookies in Postman?

I'm using Postman to test and play with an API.
For the login url, the API requires sending a POST request with username and password as fields. I do this, and I get a 200 response with the message that I am logged in.
I then try another request to get user data. However, I get a response that I am not logged in.
I realized this problem is most likely because the cookie that is sent to me when I log in is not included in the next Postman request.
So my question is, how do I save and include cookies for future requests?
Store the cookie value you want to use in a global variable.In Tests tab of login request, write
postman.setGlobalVariable('key', postman.getResponseCookie("cookieName").value);
Pass along with the value in the Headers tab as a cookie in get user request:
Cookie | cookieName={{key}}
I tried using Ashutosh's answer but got an error. I'm guessing this is because Postman's scripting API changed?
At any rate, the following worked for me:
In the Tests tab of the request that will return cookies you want to save, write
pm.globals.set('<your key>', pm.cookies.get('<cookie name>'));
Then, as described in Ashutosh's answer, add the cookie to the headers by setting the key as cookie and corresponding value as <your cookie name>={{<global variable name>}};.
I found documentation for this at the Postman sandbox API reference.
(Using the native Postman app without the interceptor)
The traditional way of reading the cookie does not work for me pm.cookies.get('<cookie name>')
. Here is a workaround that automatically attaches auth cookie to all requests within a collection:
// The test scripts below run after the api /login returns the response
const authCookie = pm.response.headers.idx(3).value
/*
pm.response.headers.idx(3) is equal to:
{key: "Set-Cookie", value: "xs=eyJhb; Max-Age=3600; Path=/; Expires=Fri, 18 Dec 2020 04:40:34 GMT; HttpOnly; Secure; SameSite=None"}
*/
const token = authCookie.substring(3, authCookie.indexOf(';'))
pm.collectionVariables.set('xs_value', token);
Then add this pre-request scripts to the entire collection:
// Scripts below runs before any request within a collection is sent
const token = pm.collectionVariables.get('xs_value')
pm.request.headers.upsert({ key: 'Cookie', value: `xs=${token}` })
Enjoy!
More info on how to attach headers to requests
It seems there are two Interceptor plugin in google chrome. make sure install the correct one.

How to get access to an http-only cookie using Meteor

Some background:
my site: site.domain.com
http-only cookie set by domain.com.
I can see the cookie in the resources view in Chrome & in the network traffic
I really need read access to an http-only (domain) cookie from either meteor client or server (doesnt matter to me)
http-only renders any technique that uses "document.cookie" useless unfortunately.
I can see the cookie details being passed back to Meteor inside the various sockjs GET requests, what i probably need is a way to get at that raw request info so i can tease out the cookie value.
Anyone have any ideas?
Thanks in advance
Have a look at trying to access the headers via req or using connect's cookieparser:
Server Js
__meteor_bootstrap__.app.use(connect.cookieParser()).use(function(req, res, next) {
Fiber(function () {
console.log(JSON.stringify(req.cookies));
}).run();
});
Have a look at : https://groups.google.com/forum/?fromgroups=#!topic/meteor-talk/xLGOcruZ4c4 for more info about this