ReactJS seems to turn POST requests into GET requests - reactjs

I'm using React and the fetch API to do a POST request to a user authentication backend. I can do this POST request below with Postman, and I get the correct JWT back, but oddly - whenever I use the following code in React, the POST request somehow hits the server as a GET request.
Code in React:
return this.fetch('http://fakeURL.com/auth', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": "email#email.com",
"password": "password",
})
}).then(res => {
this.setToken(res.token);
return Promise.resolve(res);
})
The logs show (first the pre-flight request):
Request URL: http://fakeURL.com/auth
Request Method: OPTIONS
Status Code: 200 OK
Referrer Policy: no-referrer-when-downgrade
And the actual request:
Request URL: http://fakeURL.com/auth
Request Method: GET
Status Code: 405 METHOD NOT ALLOWED
Referrer Policy: no-referrer-when-downgrade
Things I've tried:
Running the app both locally and in an AWS S3 bucket (with CORS configured to allow all methods, and from any origin)
Using Flask on our backend to enable CORS
Hitting our backend via Postman with the same API POST request (when we use Postman, the API request works as intended, as a POST that returns a token)
Hitting other URLs (e.g. http://httpbin.org/post) to see if my code can hit those endpoints with a POST rather than a GET... and those endpoints see GET requests as well (instead of the intended POST)
This is so confusing - what could possibly cause our POST request to go out as a GET request? I feel like we've eliminated every possibly cause outside of something weird happening in React. Thanks for the help!

npm install --save axios
on your auth page:
import axios from 'axios'
Modify your post so instead of using fetch:
login(emailValue, passwordValue) {
return axios({
url: `yourAuthURL`,
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
data: {
"email": emailValue,
"password": passwordValue,
}
}).then(res => {
console.log(res);
})
}

Related

CSRF cookie not set [Django/AngularJS]

First of all, this is not a duplicate question. I have tried all the related posts on stackoverflow but could not find a solution.
I have a Django app for the backend and and AngularJS app for the frontend. I am using djangorestframework-jwt for API authentication. I have an API endpoint that does not require any authentication and I am getting CSRF Failed: CSRF cookie not set error on the browser only for this endpoint.
In my django settings I have:
ALLOWED_HOSTS = ['*']
and it does not include any CSRF_COOKIE_SECURE, CSRF_COOKIE_HTTPONLY, or SESSION_COOKIE_SECURE settings.
The djangorestframework-jwt settings is:
JWT_AUTH = {
'JWT_SECRET_KEY': SECRET_KEY,
'JWT_ALGORITHM': 'HS256',
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': True,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3000),
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_AUTH_COOKIE': 'refresh-token'
}
I noticed that in the browser cookies if there is any refresh-token key then the endpoint works just fine. The problem arises when that key is not present in the browser cookies. I set 'JWT_AUTH_COOKIE': None or removed the following lines:
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_AUTH_COOKIE': 'refresh-token'
from the JWT_AUTH settings but no luck.
I also tried #csrf_excempt for that endpoint but that did not work either.
Interestingly, when I send the request from postman it works.
Here is the request I am sending from the frontend:
$http({
url: url,
method: "PUT",
headers: {
'Content-Type': 'application/json'
},
data: data
})
I would like to know why I am getting the error when refresh_token key is not present in the browser cookies and how to solve this issue.
I solved my issue by adding 'X-CSRFToken': $cookies.get("csrftoken") to the Http request header, so the request now look like:
$http({
url: url,
method: "PUT",
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': $cookies.get("csrftoken")
},
data: data
})

can't receive monzo access token using axios

I've been trying for the whole day to perform a post request using axios in react (I'm trying to get an access_token for a Monzo app). I've followed the instructions here and they work perfectly when trying them out with the httpie command line tool as illustrated on said instructions. However, when I try to use it from within my react app, things go awry. The post request in question using httpie is as follows:
http --form POST "https://api.monzo.com/oauth2/token" \
"grant_type=authorization_code" \
"client_id=my_client_id" \
"client_secret=my_client_secret" \
"redirect_uri=my_redirect_uri" \
"code=my_authorization_code"
and this works as expected and returns a JSON object containing my access_token.
The (problematic) axios command I've been using in my react app is:
axios.post(
"https://api.monzo.com/oauth2/token", {
grant_type: "authorization_code",
client_id: my_client_id,
client_secret: my_client_secret,
redirect_uri: my_redirect_uri,
code: my_authorization_code
})
The error message I'm getting is Failed to load resource: the server responded with a status of 400 ().
I found this very related question, which suggests I add a header specifying Content-Type: application/json so I changed my axios commands to:
axios({
method: "POST",
url: "https://api.monzo.com/oauth2/token",
data: JSON.stringify({
grant_type: "authorization_code",
client_id: my_client_id,
client_secret: my_client_secret,
redirect_uri: my_redirect_uri,
code: my_authorization_code
}),
headers: {
'Content-Type': 'application/json'
}
})
which, unfortunately, gives the exact same error.
Can anybody give me a few pointers on this? I'm very new to networking...thanks!
And as it usually happens with these things, I found the answer shortly after posting the question. Apparently, the 'Content-Type' needs to be sent as 'application/xxx-form-urlencoded' and the data to be transformed accordingly like so:
const queryString = require('query-string')
axios({
method: "POST",
url: "https://api.monzo.com/oauth2/token",
data: queryString.stringify({grant_type: ...}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})

Access-Control-Allow-Origin error when posting to Jira Cloud API

I am using the standard cloud API for Jira and having troubles using their API to create an issue. I have tried both basic and token auth, both with the same CORS error.
I have followed the steps listed in these documents (here and here) and can get the API working in Postman, but not in my React code. I believe this has to do with Postman not sending the preflight options with the request.
Here is a sample of my request with basic auth:
fetch(`https://{DOMAIN}.atlassian.net/rest/api/3/issue/`, {
method: "POST",
credentials: 'include',
headers: {
"Content-Type": 'application/json',
"Accept": 'application/json',
"Authorization": "Basic {ENCODED USERNAME/PASSWORD}"
},
body: JSON.stringify(data)
})
.then(...)
Here is a sample of my request with token:
fetch(`https://{DOMAIN}.atlassian.net/rest/api/3/issue/`, {
method: "POST",
credentials: 'include',
headers: {
"Content-Type": 'application/json',
"Accept": 'application/json',
"Authorization": "bearer {TOKEN}"
},
body: JSON.stringify(data)
})
.then(...)
Does anyone know how to overcome this CORS error with Jira Cloud API? I found this article but would assume the issue has been resolved: https://jira.atlassian.com/browse/JRACLOUD-30371
UPDATE
Could not get this working via basic auth, however the newer OAuth 2.0 is working (only for GET requests).
Follow updates on this stack overflow question: JIRA Cloud REST API (OAuth 2.0) Error 403 on POST Requests

Authentication Error when using mode: no-cors using fetch in React

I am building a React app that is pulling different stats from services for our internal developers (commits, tracked hours, etc)..
I am using fetch to grab API data from Harvest, a time tracking app. According to their docs, you can use basic HTTP authentication. When I use the app Postman, all is well and I can see the response just fine. Initially I used:
getHarvest(){
// Set Harvest Headers
const harvestHeaders = {
method: 'GET',
headers: {
'Authorization': 'Basic xxxxxxxxxxxxxxx=',
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cache-Control': 'no-cache',
}
};
fetch('https://factor1.harvestapp.com/projects/', harvestHeaders)
.then( response => response.json() )
.then( projects => {
// Do some stuff
} )
}
This gives me an error in the console:
Fetch API cannot load https://myaccount.harvestapp.com/projects/.
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access. The response had HTTP status code 404. If an opaque response
serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.
So with that feedback I changed the function to look like this:
getHarvest(){
// Set Harvest Headers
const harvestHeaders = {
method: 'GET',
mode: 'no-cors',
headers: {
'Authorization': 'Basic xxxxxxxxxxxxxxx=',
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cache-Control': 'no-cache',
}
};
fetch('https://factor1.harvestapp.com/projects/', harvestHeaders)
.then( response => response.json() )
.then( projects => {
// do stuff
} )
}
But that results in an Authentication error:
GET https://myaccount.harvestapp.com/projects/ 401 (Unauthorized)
I'm not sure how I can get the response correctly. Am I doing something wrong? It seems odd to me that using the app Postman works but this doesn't. Thoughts? Thanks!
It doesn’t seem like the Harvest API is meant to be used with XHR or Fetch from Web applications.
At least their docs don’t mention anything about using their API from XHR or Fetch, nor do those docs mention anything about Access-Control-Allow-Origin nor CORS in general.
Instead the docs give examples of using the API with curl and with the Postman REST Client.
And trying examples in the docs like below, the response has no Access-Control-Allow-Origin.
curl -H 'Content-Type: application/xml' -H 'Accept: application/xml' \
-u "user#example.com:password" https://example.harvestapp.com/account/who_am_i
So it seems like the answer is: You can’t access the Harvest API with XHR/Fetch from a Web app.
It works in Postman because Postman is not bound by the same-origin policy browsers enforce to prevent Web apps running in a browser from making cross-origin requests unless the site/endpoint the request is made to has opted in to using CORS (which it seems Harvest hasn’t opted into).

http get request in angularjs converts to option request

When sending request with header in angulajs. The request is:
$http.get('http://dev.oms.fetchr.us/order/',{
headers:{
'Authorization': 'Token ' + token
}
})
The request is converted to option request. If I remove the authorization token it works as get request, but returns 403 error.
After so much time and reading I got this about preflight requests.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control
I also tried with adding headers define here. But results gives error.
If I edit the request in mozilla console and resend the request then it works. And I am able to hit the api.
I also tried this: How does Access-Control-Allow-Origin header work?
to allow origin.but as i running on local server.It is not working too.
It is working fine in JQuery. But not with angularjs please help how to send get request in angularjs with express server on cross-origin.
For making get request with header use this
$http({
"method": "GET",
"url": url + "",
"data": '',
"headers": { 'Authorization': Your Token },
"Content-Type": "application/x-www-form-urlencoded ; charset=UTF-8"
})

Resources