how to send fetch request with ssr nuxt and httpOnly auth - fetch

I have an SSR nuxt app and laravel backend. In auth, we are using HttpOnly and we are Ok in most of the code but there is a problem in sending requests with fetch and asyncData on the server-side.
I know that only the browser automatically merge a header for auth with request and send it. Now I'm using fetch and this will send requests to the server and there is no browser on the server.
I searched for making custom fetch in nuxt, but I don't find any.
How should I send a request with fetch and asyncdata and do not get a 401 error?
UPDATE
***: I have to change nuxt mode to spa from ssr unfortunately, because I don't find any answer yet.

I still haven't found an answer. I changed axios part in nuxt.config.js like this:
axios: {
baseURL: 'https://api.iranicard.net/api/v1/admin/',
credentials: 'same-origin',
common: {
'Accept': 'application/json',
"Content-Type": "application/json"
},
retry: { retries: 2 },
proxyHeaders: false
},
But still after a successful login, when in a component that I used fetch or asyncData hook, I got logout and it's not working.

fetch won’t send cookies, unless you set the credentials init option. Try setting the credentials option to same-site or include like this:
fetch('your-endpoint', { credentials: 'same-site' }).then(...)

Related

Firebase AppCheck POST request is unknown

I'm trying to configure AppCheck in my web app (using SvelteKit).
I've registered my web app with recaptcha and then Added this basic code:
onMount(async () => {
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaV3Provider('my-key'),
isTokenAutoRefreshEnabled: true
})
})
But it fails with 400 error. Those occur because the POST request has 'unknown' where the Recaptcha (and firebase collection) should be.
POST URL: https://content-firebaseappcheck.googleapis.com/v1/projects/undefined/apps/undefined:exchangeRecaptchaV3Token?key=undefined
Why does it happen? how can I fix it?
*The only similar case is here, but it has no solution, and might not be the same.
SOLVED: The request was malformed due to mistaken firebaseConfig data.

Browser not saving cookie sent by Golang backend

I know this question has been asked a bunch of times, but I tried most of the answers and still can't get it to work.
I have a Golang API with net/http package and a JS frontend. I have a function
func SetCookie(w *http.ResponseWriter, email string) string {
val := uuid.NewString()
http.SetCookie(*w, &http.Cookie{
Name: "goCookie",
Value: val,
Path: "/",
})
return val
}
This function is called when the user logs in, and I expect it to be sent to all the other endpoints. This works as expected with Postman. However, when it comes to the browser, I can't seem to get it to remember the cookie or even send it to other endpoints.
An example of JS using an endpoint
async function getDataWithQuery(query, schema){
let raw = `{"query":"${query}", "schema":"${schema}"}`;
let requestOptions = {
method: 'POST',
body: raw,
redirect: 'follow',
};
try{
let dataJson = await fetch("http://localhost:8080/query/", requestOptions)
data = await dataJson.json();
}catch(error){
console.log(error);
}
return data;
}
I tried answers like setting SameSite attribute in Golang, or using credential: "include" in JS with no luck.
Thanks to the discussion in the comments, I found some hints about the problem.
Saving cookies (both API and frontend on the same host)
I used document.cookie to save the cookie. I set the options by hand since calling res.cookie on the response of the API fetch only returned the value. An example is document.cookie = `goCookie=${res.cookie}; path=/; domain=localhost;.
Sending cookies
This has been answered before in previous questions and answered again in the comments. The problem was that I used credential:'include' instead of the correct credentials:'include' (plural).
CORS and cookies
In case the API and the frontend are not on the same host you will have to modify both the API and the frontend.
frontend
The cookie has to have the domain of the API since it's the API that requires it, not the frontend. So, for security reasons, you can't set a cookie for a domain (API) from another domain (frontend). A solution would be redirect the user to an API endpoint that returns Set-Cookie header in the response header. This solution signals the browser to register that cookie with the domain attached to it (the API's domain, since the API sent it).
Also, you still need to include credentials:'include' in the frontend.
API
You will need to set a few headers. The ones I set are
w.Header().Set("Access-Control-Allow-Origin", frontendOrigin)
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, withCredentials")
w.Header().Set("Access-Control-Allow-Methods", method) // use the endpoint's method: POST, GET, OPTIONS
You need to expose the endpoint where the frontend will redirect the user and set the cookie in the response. Instead of setting the domain of the API by hand, you can omit it, the browser will fill it with the domain automatically.
To handle the CORS and let JS send the cookie successfully, you will have to set the SameSite=None and Secure attributes in the cookie and serve the API over https (I used ngrok to make it simple).
Like so
func SetCookie(w *http.ResponseWriter, email string) string {
val := uuid.NewString()
http.SetCookie(*w, &http.Cookie{
Name: "goCookie",
Value: val,
SameSite: http.SameSiteNoneMode,
Secure: true,
Path: "/",
})
// rest of the code
}
I recommend you also read the difference between using localStorage and document.cookie, it was one of the problems I had.
Hope this helps.

Stripe API redirectToCheckout not redirecting to the correct url in Next.js

In Next.js the Stripe redirectToCheckout function is sending the checkout page to a url that fails, but the json response data is full and the url is correct (works if I try it manually). Stripe is not sending the checkout to the session.url for some reason.
How can we have the redirectToCheckout redirect to the session.url?
I'm currently using this...
await stripe.redirectToCheckout({ sessionId: id });
I've tried what the Stripe docs suggest...
res.redirect(303, session.url);
But that gives a CORS error - CORS request external redirect not allowed.
Any ideas?
I solved my problem by explicitly telling Next.js the names of the stripe API keys in the next.config.js file.
next.config.js
env: {
stripe_public_key_test: process.env.stripe_public_key_test,
stripe_secret_key_test: process.env.stripe_secret_key_test,
stripe_webhook_endpoint_secret: process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET,
},
Restart the app after editing the next.config.js file
I ended up using await stripe.redirectToCheckout({ sessionId: id });

`fetch` does not work from middleware page when deployed to vercel

I have a middleware page on a route that first makes a check against the backend server.
In that middleware I'm trying to call a next.js api page using the fetch API, which in turn communicates with the backend. This flow works as expected in the local development environment, but when deployed to vercel, this fails.
The caught error displayed in vercel is: TypeError: Fetch API cannot load: /api/make-check-at-backend/].
The URL used is a relative path: fetch("/api/make-check-at-backend/", ...).
What is the issue there? Do I need to include the fully qualified URL value where the next.js app is hosted, including domain, protocol, etc? If that's the case, how can the server/host name be retrieved from Vercel? Should I use env variables?
This is the fetch code used in the middleware:
const retrievedValue = await fetch("/api/make-check-at-backend/", {
method: "POST",
headers: headers,
body: JSON.stringify({ someKey: 'someValue' }),
});
P.S. I've also tried using axios to make the http call directly to the backend, but this failed with an axios adapter known issue. This same backend call works as expected from any api/* page. Is all this due to middleware functionality being still in Beta?
Turns out that the Vercel setup has a number of system environment variables which are available in their corresponding deployed sites.
From my experience, in those deployed sites, the fetch API needs to have the full URL, including protocol, host, pathname, etc.
After some trial and error, I have found the code that works in the deployed sites is:
const retrievedValue = await fetch(`https://${process.env.VERCEL_URL}/api/make-check-at-backend/`, {
method: "POST",
headers: headers,
body: JSON.stringify({ someKey: 'someValue' }),
});
Below follows a screenshot of the Vercel's environment variables documentaiton, in case the link above becomes broken over time.

Meteor js requestPermissions not working

Meteor js requestPermissions not working. I want to access google calendar, access token not permission with google calendar. How I can get access google calendar.
there are two things to consider. The right permission you need from google, and the API you use to access your data. You don't provide too many details so I don't know whether you need mobile (Cordova) too.
For your project, in Google Developer Console you need to enable the Calendar API. Once you do that, you have options to see what appId / authorization is relevant for your API so you add it to your Meteor Settings.
Then from the OAuth 2.0 scopes you need to select the exact scope you need (search for "calendar" for instance) and add that scope (the entire url) to your array of scopes.
Then you can do GET or POST with something like the native HTTP API of Meteor
example:
let data = HTTP.call('GET', `https://people.googleapis.com/v1/people/me/connections?pageToken=${res.data.nextPageToken}&personFields=emailAddresses`,
// let data = HTTP.call('GET', `https:https://www.googleapis.com/calendar/v3/calendars/{... your calendarId} `,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json'
}
},
(err, res) => { handle these })

Resources