Actix-web unable to send Set-Cookie - rust

So i use actix web on the backend and svelte on the frontend
This sends the cookie to the frontend
let cookie = auth_authority.create_signed_cookie(UserClaims {
id: o.id,
role: Role::User,
})?;
info!("Logged in user");
info!("{}", cookie);
Ok(HttpResponse::Ok()
.cookie(cookie)
.json("You are now logged in"))
And this is the CORS config:
let cors = Cors::default()
.allowed_origin("http://localhost:3000")
.allowed_methods(vec!["POST", "GET"])
.allowed_headers(vec![
header::AUTHORIZATION,
header::CONTENT_TYPE,
])
.expose_any_header()
.supports_credentials()
.max_age(3600);
And this is the function that fetches the data for svelte:
const resp = await fetch("http://0.0.0.0:4000/login", {
method: "POST",
mode: 'cors',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(
{
username,
password,
}
)
})
I do not recieve the Set-Cookie header when using a web browser but when i use curl i do(Most likely caused by CORS). I can send other headers that i create but i cannot send Set-Cookie no matter what. I used the .supports_credentials() method to allow cookies but that did nothing.
Can someone guide me into a direction to solve this or does someone know how to solve it?

Related

CSRF issue while importing dashboard in superset through nodejs API

I am facing flask_wtf.csrf:The CSRF session token is missing. while trying to import dashboard (with VERSIONED_EXPORT enabled) via a NodeJS POST API call. Below is the same setup that works for all my other superset API calls:
const config = {
headers: {
'X-CSRFToken': await this.getCsrfToken(),
'Authorization': `Bearer ${await this.getAccessToken()}`
}
}
axios.get<T>(url, config) //or
axios.post<T>(url, data, config)
For the import dashboard API call, I am using form-data and it works if I add dashboard import to WTF_CSRF_EXEMPT_LIST, but I want to avoid doing that but it can't work with all of these approaches I tried:
const formData = new FormData()
// With X-CSRFToken (shown above)
formData.append('formData', fs.createReadStream(filePath))
// With X-CSRFToken & defined file name & length
var stat = fs.statSync(filePath);
formData.append('formData', fs.createReadStream(filePath), {filename: fileName, knownLength: stat.size})
// With X-CSRFToken and/or Referral and/or Content-Type and/or Content-Length
var stat = fs.statSync(filePath);
formData.append('formData', fs.createReadStream(filePath), {filename: fileName, knownLength: stat.size})
const contentLength = formData.getLengthSync()
const config = {
headers: {
'X-CSRFToken': await this.getCsrfToken(),
'Authorization': `Bearer ${await this.getAccessToken()}`
'Referrer': url,
'Content-Type': 'multipart/form-data',
'Content-Length': contentLength
}
}
// With X-XSRF-TOKEN
const config = {
headers: {
'X-XSRF-TOKEN': await this.getCsrfToken(),
'Authorization': `Bearer ${await this.getAccessToken()}`
}
}
formData.append('formData', fs.createReadStream(filePath))
await post(url, formData, config)
I suspect it could be caused by form-data which can't handle csrf token headers as I am able to import dashboard on Postman:
Headers: {
Authorization: 'Bearer {token}',
X-CSRFToken: {csrfToken}
}
form-data: {
formData: {uploadedFile}
}
I am open to suggestions on how I can import dashboard without using form-data in node
This is common problem with csrf token.
See related post.
In superset case you need to get not only csrf token but also session cookie. Session cookie looks like this
session=eyJjc3JmX3Rva2VuIjoiMGYwMzRiNzgyMzIyMDgwNTM5M2Y4YzdjODYyZmIzZGMyMGJlYjAwZiJ9.Ykb6sQ.PSJYvZBxYK7nEMzK3smE4WUSVEY;
You need to add this session info to Cookie header of your client and it will work.

How can i implement logout feature in NodeJs with keycloak

I'm trying to implement a logout functionality with keycloaks which is running as a docker container.
When tried with postman I'm getting a 204 response, even after that I am able to access the web pages without having to login again (Hence logout has not happened correctly).
I have supplied the bearer token, client id, client secret and refresh token.
Please see the screenshots below from Postman.
Similarly have tried to implement these changes on nodejs using axios.But however things are not working.
var axios = require('axios');
var qs = require('qs');
var data = qs.stringify({
'client_id': 'VideoKYC',
'client_secret': 'my-clinet-secret',
'refresh_token': 'refresh token from cookies'
});
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0
var config = {
method: 'post',
url: 'https://3.109.1.86:8443/auth/realms/VideoKYC-Realm/protocol/openid-connect/logout',
headers: {
'Authorization': 'Bearer my-token',
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
};
axios(config)
.then(function (response) {
console.log("data is");
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Stack trace from where response is empty:
$ node logout.js
(node:16732) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
data is
""
Ideally I think we should get some response, and the token should be invalidated and automatically be logged out.
Please help me implement these changes
this code works for me.
const data = qs.stringify({
client_id: 'your_kc_clientId',
client_secret: 'your_kc_client_secret',
refresh_token: 'your_referesh_token',
});
const config = {
method: 'post',
url: `${process.env.KEYCLOAK_SERVER_URL}/realms/${process.env.KEYCLOAK_REALM}/protocol/openid-connect/logout`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data: data,
};
axios(config)
.then((response) => console.log('logout successfully'))
.catch((err) => console.log('error!!!'));

Basic Auth is not working with Axios post Nodejs

I am trying to send a request using axios post with basic authorization. It is working fine with postman but not working when I try to send via code.
axios.post(`my-url`, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic **KEY_HERE**',
},
data: {
'id': 'event_order',
'date': '2021-09-09'
}
}).then(async (response) => {
console.log(response.data)
})
It is returning 401 Unauthorized. But, it works as excepted when I call it via Postman:
Postman Setup Image
Did you add your domain to whitelist in your cors module? If not:
app.use(cors({ origin: "PROTOCOL://DOMAIN:PORT", credentials: true }));
edit: Ok, sorry, I was confused and thought you were sending a frontend axios post request to your own NodeJS server. If possible, could you be more precise. But try passing in your headers/auth as the third argument-- since you're passing in everything in the second argument, the API is not parsing out your headers since its part of the data parameter.
const data = {
'id': 'event_order',
'date': '2021-09-09'
}
axios.post(`my-url`, data, {
headers: {'Content-Type': 'application/json'},
auth: {
username: "YOUR_USERNAME",
password: "YOUR_PASS"
}
})
.then(async (response) => {
console.log(response.data)
})
Also try and post the network errors, if you can.

No 'Access-Control-Allow-Origin' policy error on sending POST request to REST API

I am making a simple full-stack project wherein I have a very basic REST API built using NodeJS and Express. It is a server-side rendered website.
While trying to login, when I send a POST request to the login endpoint, I am getting the following error in the console
Access to XMLHttpRequest at 'http://127.0.0.1:3000/api/v1/users/login'
from origin 'http://localhost:3000' 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.
This is the code snippet that sends the POST request
const login = async (email,password) => {
try {
const res = await axios({
method: 'POST',
url: 'http://127.0.0.1:3000/api/v1/users/login',
data: {
email,
password
}
});
if(res.data.status === 'success') {
alert('Logged in successfully');
window.setTimeout(() => {
location.assign('/');
}, 1500);
}
}
catch(err) {
console.log(err);
}
}
Please explain as to why I'm getting that error and how to fix it. The API is not deployed yet and it's running on localhost
Your request origin is:
http://localhost:3000
This is not the same as the domain you're sending the request to:
http://127.0.0.1:3000
To avoid this CORS error, the FQDN must be the same, including hostname and port. (Or you could configure your server for CORS.) As far as the server is concerned, the different host means a completely separate entity, even if it's the same machine.
Change your url to:
url: 'http://localhost:3000/api/v1/users/login',
could you add Access-Control-Allow-Origin header to the request and see ,
const login = async (email,password) => {
try {
const res = await axios({
method: 'POST',
url: 'http://127.0.0.1:3000/api/v1/users/login',
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
},
data: {
email,
password
}
});
if(res.data.status === 'success') {
alert('Logged in successfully');
window.setTimeout(() => {
location.assign('/');
}, 1500);
}
}
catch(err) {
console.log(err);
}
}

How to pass JSON object from API to server

I am using React and node.js, and I've used react's fetch to POST some Login credentials to my restAPI in order to receive a webtoken...
fetch('http://localhost:8080/api/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: this.state.username_login,
password: this.state.password_login
})
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson); //this is the object containing the token
})
.catch(function(error) {
console.log("request failed");
})
}
so responseJson is the the object containing my web token. The request was successful and now I've passed it to the client. Now, I am thinking of saving it to a cookie.
How can I send this to the server? Should I make a POST request? If so how do I do that once the JSON object is received? If there is a better way, I would like to know.
Cookies are automatically passed along any HTTP request made with fetch

Resources