Configuring CSRF tokens with apollo client and graphene-django - django

I am having trouble properly setting up csrf tokens in the authlink header.
const authLink = setContext((_, { headers }) => {
const token = localStorage.getItem(AUTH_TOKEN)
return {
"headers": {
'X-CSRFToken' : getCookie('csrftoken'),
"Authorization": token ? `JWT ${token}` : '',
...headers,
},
};
});
The request being sent looks ok from the browser devtools, as you can see at the bottom the csrf token looks right? I cleared my browser data to make sure it wasn't old, but I'm not sure if that's effective anyways.
accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Authorization
Connection: keep-alive
Content-Length: 505
content-type: application/json
Host: localhost:8000
Origin: http://localhost:3000
Referer: http://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.63
X-CSRFToken: LsV83sz3Rb5RRIlNcRN3AgnniodwsSMpvXwMGquPGRbvoPpISfKv6MBEf86rVzVp
The error I get through the site is
CSRF verification failed. Request aborted
my django server shows
Forbidden (CSRF cookie not set.)

Have you tried to install corsheaders? or are you sure you have this function
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}

I had same issue because x-csrftoken was not transmitted in the Request Headers
Here is the fix i have done
On my React code
import { ApolloClient, createHttpLink, InMemoryCache } from '#apollo/client';
import { setContext } from '#apollo/client/link/context';
import Cookie from "js-cookie";
const httpLink = createHttpLink({
uri: '/graphql/',
});
const authLink = setContext((_, { headers }) => {
return {
headers: {
...headers,
"x-csrftoken": Cookie.get("csrftoken")
}
}
});
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});

Related

Cookie is in /api route but not in 'localhost:3000' or '/'

I am working on the login system but have been stuck for a while, cookies are in the response header but not set in the application tab.
Edit: looks like cookie is being stored to path '/api'. But after setting path:'/' nothing changed.
/api/login.js
export default async (req, res) => {
if (req.method === "GET") res.send(200);
else if (req.method === "POST") {
// console.log(req.body);
const user = await loginHandler(req);
const matchPassword = await bcrypt.compare(
req.body.password,
user[0].Password
);
if (!matchPassword) {
res.send(400);
} else {
const token = jwt.sign(
{
Email: user[0].Email,
},
process.env.SECRET,
{ expiresIn: "12h" }
);
res.setHeader(
"Set-Cookie",
cookie.serialize(token, {
httpOnly: true,
maxAge: 12 * 3600 * 1000,
secure: process.env.NODE_ENV !== "development",
sameSite: "strict",
path:"/",
})
);
res.send(200);
}
}
};
login form
const headers = {
"Content-Type": "application/json",
};
const handleSubmitForm = async (enteredEmailAndPassword) => {
const user = {
...enteredEmailAndPassword,
};
await axios.post(
"/api/login",
user,
{
headers: headers,
},
{ withCredentials: true }
);
};
response header
Set-Cookie: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJFbWFpbCI6InZmdkBnbWFpbC5jb20iLCJpYXQiOjE2NTI1OTMzMzgsImV4cCI6MTY1MjYzNjUzOH0.Wsl25NglaidYnzpIrPxK6FS5nAXjUe1tK7DQQ-KVuUE=%5Bobject%20Object%5D
ETag: "3-n5rwKVhboBTgfNORDKl2z1YWBhY"
Content-Type: application/json; charset=utf-8
Content-Length: 3
Vary: Accept-Encoding
Date: Sun, 15 May 2022 05:42:18 GMT
Connection: keep-alive
Keep-Alive: timeout=5
What should I do to set cookies in the application tab?

AWS lambda HTTP API only receiving header from POST form

I am trying to send a name and email from a static website to a lambda function through a HTTPS gateway. Here's the JS code that handles the inputs.
function submitToAPI(e) {
e.preventDefault();
var URL = "https://fvxw67h6bl.execute-api.us-east-1.amazonaws.com/default/GetData";
let name = (document.getElementById("name") as HTMLInputElement).value;
let email = (document.getElementById("email") as HTMLInputElement).value;
if (name=="" || email=="")
{
alert("Please Fill All Required Field");
return false;
}
const emailRE = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if(!emailRE.test(email)) {
alert("Email Address entered, is not valid");
return false;
}
var data = {
name : name,
email : email
};
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", URL);
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.send(JSON.stringify(data));
}
I was trying to access the data in the lambda function with:
name = event["name"]
email = event["email"]
But it kept returning errors.
So I tried printing the event object and this is what it returned.
{
'version': '2.0',
'routeKey': 'ANY /GetData',
'rawPath': '/default/GetData',
'rawQueryString': '',
'headers': {
'accept': '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
'content-length': '0',
'host': 'fvxw67h6bl.execute-api.us-east-1.amazonaws.com',
'origin': 'http://localhost:3000',
'referer': 'http://localhost:3000/',
'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
'sec-ch-ua-mobile': '?0',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'cross-site',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
'x-amzn-trace-id': 'Root=1-611f1788-7c27d190689e2be22374fd1f',
'x-forwarded-for': '107.2.126.157',
'x-forwarded-port': '443',
'x-forwarded-proto': 'https'
},
'requestContext': {
'accountId': '551656018604',
'apiId': 'fvxw67h6bl',
'domainName': 'fvxw67h6bl.execute-api.us-east-1.amazonaws.com',
'domainPrefix': 'fvxw67h6bl',
'http': {
'method': 'POST',
'path': '/default/GetData',
'protocol': 'HTTP/1.1',
'sourceIp': '107.2.126.157',
'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
},
'requestId': 'EWCdaiwUIAMEVOA=',
'routeKey': 'ANY /GetData',
'stage': 'default',
'time': '20/Aug/2021:02:46:32 +0000',
'timeEpoch': 1629427592825
},
'isBase64Encoded': False
}
Basically it just returned the header.
How would I access the data I sent through the API?

can't send post request from reactJs using Axios to Django restframework

I'm new to ReactJs and am trying to do post request to my Django backend server, Get request works great as expected. But post returns an error (403) Forbidden ,, here is my code :
axios.post('my_url', {
headers: {
'Authorization': 'my_auth_string'
}, body: {
'type':'in',
'amount':'123'
}
}).then(res =>{
console.log(res)
})
NOTES
The endpoint accepts post request, as it works as expected when I
send the request using flutter.
Am using BASIC auth, can this be a problem with axios ?
that's happen when you don't add csrf token to your post request headers like this:
headers: {
'X-CSRFToken':'{{csrf_token}}',
'Authorization': 'my_auth_string'
}
Create a file as csrftoken.js and add below code
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var CSRF_TOKEN = getCookie('csrftoken');
export { CSRF_TOKEN };
import the token in your required file
import { CSRF_TOKEN } from ".csrftoken.js";
do axios POST request then
axios.post(url, data, {
headers: {
'content-type': 'multipart/form-data',
'X-CSRFTOKEN': CSRF_TOKEN
}
}).then().catch(()
};
Better add session auth also with your project

Trying to get then send a cookie using react and fetch

I've been trying to implement some authentication component in my app for a few hours now, and I still don't understand some of the things that are happening.
Basically, I'd like to send a POST request containing some credentials to my API, which sends me a cookie back with a token if the credentials worked. Then, the cookie should be included in the headers of all future requests to my API (which I believed was automatic).
server.js (my API is a mockup for now, with JSON files)
...
app.post('/api/login', jsonParser, (req, res) => {
fs.readFile(ACCOUNTS_FILE, (err, data) => {
if (err) {
console.error(err);
process.exit(1);
}
const accounts = JSON.parse(data);
const credentials = {
email: req.body.email,
password: req.body.password,
};
var token = null;
for (var i = 0; i < accounts.length; ++i) {
const account = accounts[i];
if (account.email === credentials.email
&& account.password === credentials.password) {
token = account.token;
break;
}
}
if (token) {
res.setHeader('Set-Cookie', `access_token=${token}; Secure; HttpOnly;`);
res.json({ token });
} else {
res.json({ token: null });
}
});
});
...
app.js
...
handleConnection(e) {
e.preventDefault();
const email = this.state.email.trim();
const password = this.state.password.trim();
if (!email && !password) {
return (false);
}
fetch(loginUrl, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
credentials: 'include',
},
body: JSON.stringify(this.state),
})
.then((response) => response.json())
.then((data) => {
console.log(data);
})
.catch((error) => {
console.warn(error);
});
return (true);
}
...
Now the console.log(data) always displays my token (or null if my credentials are wrong), but the cookie thing doesn't work...
See, I receive the Set-Cookie header, but I still have no cookie on my page.
And even if I managed to get the cookie, when I try to create a cookie using document.cookie = "access_token=123"; and then send the request again, my cookie doesn't go in my header like it would with a jQuery Ajaxcall :
I read here that adding credentials: 'include' would save the day, but unfortunately it didn't.
What am I missing here?
Thanks in advance!
I had the same problem and I found the answer in Peter Bengtsson's comment here: https://davidwalsh.name/fetch
If I understood, in your case the fetch should be:
fetch(loginUrl, {
credentials: 'same-origin',
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(this.state),
})

401 Unauthorized error for GET request in Ionic 2?

I have below get request. But its giving 401 Unauthorized error.
var headers = new Headers();
headers.append('Content-Type': 'application/json;charset=UTF-8');
this.http.get(urgentPostURL + encodeURIComponent(this.urgentpost.comment))
.map((res:Response) => res.json())
.subscribe(data => {
this.result = data;
console.log('UrgentPost Result : ' + this.result.Success);
if (this.result.Success == true) {
console.log("SUCESSS");
} else {
console.log("FAILED");
}
},err => console.error(err),() => console.log('done'));
What I'm doing wrong here?
Edited
After updated to the following code I'm still getting 401:
var headers = new Headers();
headers.append('Content-Type': 'application/json;charset=UTF-8');
headers.append('Authorization', 'Basic ' + btoa("123" + ':' + "123"));
this.http.get(urgentPostURL + encodeURIComponent(this.urgentpost.comment), { headers: headers })
.map((res:Response) => res.json())
.subscribe(data => {
General:
Request Method:GET
Status Code:401 Unauthorized
Response headers:
Access-Control-Allow-Origin:*
Cache-Control:no-cache
Content-Length:0
Date:Tue, 23 Feb 2016 11:26:17 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/8.0
Set-Cookie:ARRAffinity=6e6dd0608a0902ef40a800ab07ee37397d7b6cfbd85cf3dea254a7115d365bc1;Path=/;Domain=sd.sddd.net
WWW-Authenticate:Basic
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
Request headers:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Authorization:Basic MDAwMDAwMDoxMjM0NTY3OA==
Connection:keep-alive
Content-Type:application/json;charset=UTF-8
Host:sd.sddd.net
Origin:http://localhost:8100
Referer:http://localhost:8100/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36
I seems that the server requires authentication. You didn't define the Authorization header for your call.
Here is a sample for an HTTP basic authentication:
var headers = new Headers();
headers.append('Content-Type': 'application/json;charset=UTF-8');
headers.append('Authorizcation', 'Basic '+btoa(username + ':' + password));
this.http.get(urgentPostURL + encodeURIComponent(
this.urgentpost.comment,
{ headers: headers })
.map((res:Response) => res.json())
(...)
Don't forget to specify your headers for your request and to import the Headers class.