Set-Cookie not accessible through axios or fetch - vue.js

I am building a web application with a go backend and a vue.js frontend.
I want to do a simple sign in form in which I send the sign in request from a method of my component with Axios (or fetch) and get in response a JSON object of the user and a session token in the cookie to be stored and reused in future requests to the server.
The code of my components method :
class LoginComponent extends Vue {
sendLogin (): void {
axios.post<User>('http://192.168.1.227:8080/signin', body)
.then(res => console.log('Axios Response :', res)
.catch(err => console.error('Axios Error :', err))
}
}
The part of the code of the go server :
go API
with the headers :
go headers
the front and backend are on different IP addresses in a local network and they communicate through HTTP.
The problem that I faced is that when receiving the response after the post request to login I don't have access to the cookie that has been set by the server. When I use Axios to analyze the response the cookie isn't in the headers whereas when I look at the network logs in the browser, the cookie is in the headers but it is not saved and it is not sent when I do another request.
Also, the only header that is visible with Axios is Content-Type : application/json; charset=UTF-8
I tried many things to be able to see this cookie but it doesn't work :
adding { withCredentials: true } to the axios request or axios.defaults.withCredentials = true to the axios instance only stops the request because of CORS.
changing all the Access-Control headers to "*" didn't change anything
using { auth: { username: 'foo', password: 'bar' } } in the axios options instead of the body
The only thing that worked and automatically saved the cookie was to send the request via the attributes of the form html tag, like so :
<form method="POST" action="http://192.168.1.227/signin">
...
</form>
But this way I am redirected to the JSON response object and not to one of my routes from vue-router and I can't access the User object in my app.
Is there any way that my problem can be solved?

Ok so the comment of Зелёный was the answer.
I needed the go server to set Access-Control-Allow-Origin: http://192.168.1.218:8080 (the address of the frontend) and then configure axios with { withCredentials: true } to be able to automatically store the cookie. Although I still don't see it when I do a console.log on the axios response, it is successfully stored and reused for each call to the server.

Related

get CORS problem when ty to get a token in keycloak with vuejs and axios

I trying to access one keycloak with axios in my vuejs app, but I receive the cors error, can someone help me please? (If I make a post from POSTMAN to my keycloak works fine)
I using this code:
const params = new URLSearchParams();
params.append("grant_type", "password");
params.append("client_id", "notas-front");
params.append("username", usuario.value);
params.append("password", password.value);
console.log(params);
const config = {
// withCredentials: true,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
};
axios.defaults.headers.common["Access-Control-Allow-Origin"] =
"http://localhost:8080";
axios
.post(
"http://localhost:8082/auth/realms/lumera/protocol/openid-connect/token",
params,
config
)
.then((response) => {
console.log(response);
});
and get this error:
but when I look the request I can't find the error:
the OPTIONS returns 200
but the POST dont
Postman doesn't care about Same Origin Policy, browser do. That's why your request is working in Postman but not in the browser.
Access-Control-Allow-Origin is a response header, you can't set it on the client request. And as you can see from the OPTIONS response headers your server is returning: Access-Control-Allow-Origin: http://localhost:8080
In a development environment the best way to solve this is setting a proxy in your vue configuration. Otherwise you should configure the server to allow requests from localhost:8080
Configure Web Origins properly in the Keycloak notas-front client config.

Nuxt SSR - i can't check if a user is authenticated

I'm trying to work on a Nuxt SSR frontend that uses a Django backend with Session Authentication.
I would like to have some SSR pages as well as client rendered pages in my frontend, so i'm using Universal mode.
The problem is that i did not find a working approach to check if a user is authenticated before loading a page, so i can't restrict pages to anonymous users. In order to check if a user is authenticated, Django will check if the request's headers contain a cookie, and according to that return if the user is authenticated or not.
Here is what i tried:
1) Middleware
export default async function ({context, redirect}) {
axios.defaults.withCredentials = true;
return axios({
method: 'get',
url: 'http://127.0.0.1:8000/checkAuth',
withCredentials: true,
}).then(function (response) {
//Redirect if user is authenticated
}).catch(function (error) {
console.log(error)
});
}
Here i'm sending a request to my backend to check if the user is authenticated. The problem is that the middleware is executed from server side, which means there will never be any cookie in the request, even if the user is authenticated. This means that every time i refresh the page, according to the middleware the user is always anonymous, even when the user is authenticated.
2) Plugin
export default function (context, inject) {
if (process.client){
console.log('client')
return axios({
method: 'get',
url: 'http://127.0.0.1:8000/checkAuth',
withCredentials: true,
}).then(function (response) {
//IF AUTHENTICATED, REDIRECT
context.redirect('/')
}).catch(function (error) {
console.log(error)
});
} else {
console.log('server')
}
}
Here i'm trying the same but with a plugin, and i'm "forcing" the plugin to check if the user is authenticated on the backend only when the plugin executes from client side. This works, cookies are sent in the headers and Django receives the cookie, but the problem with this solution is that Nuxt doesn't allow redirecting to other pages from a plugin (https://github.com/nuxt/nuxt.js/issues/4491).
3) Using beforeMount() in Vue
I tried to do that using beforeMount() from my Vue pages, but the problem is that since it will execute AFTER idration, the page will be loaded and after 1/2 seconds the redirect happens, which is kind of ugly.
Is it possible that there isn't a way to do this? Any kind of advice is appreciated
EDIT: the problem is not that i don't know how to code this, the problem is that when Nuxt sends a request to my backend from the server side middleware, the request will not contain any cookie, and because of this my Django backend cannot check the session cookie, which means that the backend cannot check whether or not the user is authenticated. The same code works when the middleware is executed from client side (if i navigate directly to the page instead of refreshing), because the request will contain the cookies.
I'm trying to understand if this is normal or not, but this could be an issue with Nuxt.
I know this a year old question and it was probably about nuxt 2, now nuxt 3 is out and running and I found my self with the same problem and here is how I solved it, just in case someone stumble here just like I did.
With Nuxt 3 server side you can use useFetch with the options headers: useRequestHeaders(['cookie'])
const { data, error, pending, refresh } = await useFetch(api.auth,
{
credentials: "include",
headers: useRequestHeaders(['cookie'])
}
);
There are a few issues you need to be aware of:
_ The cache, if you perform the same request with the same parameters it will return the same cached response (it won't even call the end point API). Try to use the key option with different values or the returned refresh method and check the doc "Data fetching" for more info.
_ The cookies, any cookie generate server side won't be shared with the client side, this means if the API generate a new token or session cookie on server side the browser won't receive those cookies and may generate new ones, this may get you in some 400 - bad request if you use session with CSRF, check this issue for more info.
I do have a working middleware with this
export default ({ redirect, store }) => {
if (store?.$auth?.$state?.loggedIn) {
redirect('https://secure.url')
} else {
redirect('https://login.please')
}
})

Axios not sending custom header during options request

I have a running Vue.js application that request to the server.
My client-side application is running on e.g. cms.abc.com and the server in ApiGee running on this dns server.abc.com
The request code using axios is
const headers = {
'x-api-key': 'xxxxx123123'
}
return axios({
method: get,
url: 'server.abc.com/items',
headers: headers
}).then(response => {
console.log(respnose.data)
})
When I check the browser network I'm getting status 401 Unauthorized during OPTIONS request.
The APIgee CORS has been enabled, but when I check the logs from the ApiGee the value for x-api-key is missing.
I'm also not sure why my client side application is still sending OPTIONS request. I'm expecting that it should skip the CORS since the client and the server are having the same origin. which is abc.com

Lyft-API - GET from Localhost

I have been trying to figure out how to get this Vue project to work with the Lyft API. I have been able to get an Auth Token successfully created from the three-legged procedure, but I am unable to get the available drive types https://api.lyft.com/v1/ridetypes endpoint from the localhost:8080. It does work on Postman.
It keeps stating:
Access to XMLHttpRequest at
'https://api.lyft.com/v1/ridetypes?lat=37.7752315&lng=-122.418075'
from origin 'http://localhost:8080' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I had tried doing a proxy using a vue.config.js file:
module.exports = {
devServer: {
proxy: {
'/lyftapi': {
target: 'https://api.lyft.com/v1',
ws: true,
changeOrigin: true
}
}
}
}
I been around other parts of Stack Overflow, and this is the closest thing to my problem, but no answers.
CORS error in Lyft API started recently
Any suggestions?
Axios Get Call
axios.get('/ridetypes', {
baseURL: 'https://api.lyft.com/v1',
headers: {
'Authorization': this.lyftToken,
},
params: {
lat: lat.toString(),
lng: long.toString()
}
})
If it means anything, I am able to make successful GET calls to retrieve Uber products, but not so much the Auth Token (unless its from Postman).
Lyft-API has disabled CORS, this means that browsers will block calls to api.lyft.com.
Vue won't be able to do anyting about this as this is a browser security policy.
Luckily there is nothing from stoping you to make this call from your own server.
One solution is to forward the request and response using your own server. You make a call to your server, the server makes a call to lyft, waits for the response and then responds your request.
This is not a vue only solution.

Sending axios get request with authorization header

I have tried to send axios get request using vue.js and it worked just fine when there was no need to send headers. However, when it was required to send an authorization jwt, i was getting CORS error: "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource." I don't know why is this problem occurring since there is Access-Control-Allow-Origin: '*' header in the response. My code is the following:
axios.get(url, {
headers: {
'Authorization': 'Bearer TOKEN'
}
})
.then(function (response) {
console.log(response.data)
})
The weirdest thing is when I use querystring.stringify or JSON.stringify on the header, I don't get the error 403(forbidden), but just an error 401 - Unauthorized. I tried with variable and with the token itself and it didn't work.
I tried to send a post request in order to get a web token with required data - username an password and it worked. I was able to get the token.
I made a whole bunch of research the last two days on this and I found different kind of request structure and configs which I tried all of them, but none were efficient. Is there a way to check if the request is being send with the header? Is something else the problem? If someone can help, I would appreciate. Thanks.
I think you should add this code to the bootstrap.js (or where the axios is defined):
window.axios = require('axios'); // I think its already added
window.axios.defaults.headers.common = {
'X-Requested-With': 'XMLHttpRequest'
};
You didn't mention, but I guess you use laravel, or other framework, what is protected from csrf attack, thats why you need to add the generated token to your ajax request header.