So I have a React Native App where a user can register. React Native uses the normal JavaScript Fetch API:
fetch("http://myip:8000/api/account/register/", {
method: "POST",
headers: {
"Accept": 'application/json',
"Content-Type": "application/json"
},
body: JSON.stringify({
username: username,
password: password,
email: email
})
})
.then(response => {
return response.json()
})
.then(data => {
afterRegister(data)
}
.catch(error => {
console.log(error)
}
})
The problem is, that I also could make a POST request from e.g. POSTMAN :/ I thought about a security code, that I need to add to the body (hardcoded) that only the Client, who has the code could make a POST request. A code like this could look like this: Dhiuw1298md()AJM8d9j289j)N ASIDH)8zh2n1ujD)(AZwh98em9812z)(ZDM)("ZM)8mdwuJio2h1hn398 and so on...
But now if I do this and a user register in the App he/she also could use a man in the middle attack to fetch the code and the spam POST requests to the Server until the Server crashes.
How can I prevent, that the user can see the content of the HTTPS POST Request with a man in the middle attack?
I also could make a POST request from e.g. POSTMAN :/
[…] spam POST requests to the Server until the Server crashes.
A code is only useful for authentication, i.e. identifying which user is sending the request to your server (and it's no good if the code is shared across all users, i.e. basically public). It doesn't help against a DoS attack - that's what a firewall is good for.
Related
I send post request to my API that contains userName and password in the body. When I do that with Postman I can get a response which has a body contains a token.
But when I send the same request with fetch in fronted I get a responce with an empty body.
My feth is here:
async function login(){
await fetch('/auth/login',
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(
{
'userName' : userName,
'password' : password,
}
)
}
).then(
res => {
console.log(res)
localStorage.setItem('Authorization',JSON.stringify(res))
}
).catch(
err => {
console.log("Erorororor: " + JSON.stringify(err))
}
)
}
What is the problem?
I changed my code to
.then(res => return res.text()).then(data => console.log(data)).catch(...)
and now I can get the result which I want.
TLDR Solution
It's caused by some header settings from the server side (For example, setting Access-Control-Allow-Origin: *
twice will likely cause this issue). By tuning the headers you can fix it.
Details
I met the same issue. It's NOT caused by javascript code as the browser itself doesn't get body either, but headers and cookies are got.
By expanding the timing tab you can see a warning showing the request is not finished!
But the postman can get the body:
When
The same code works in the past. It came out recently. I'm not sure what's changed as there are many things changed, for example, the browser version, the nodejs version upgraded, etc.
Fixed
By tunning the headers in the server side fixed the problem.
I have a login page in my REACT website sending a POST request with fetch, but every time the request is submitted for some reason it refreshes the page and send it as a GET request, here's the method on my login page:
onSubmitSignIn = () => {
fetch("http://192.168.56.1:8560/signin", {
type: 'POST',
headers: {'Accept': 'application/json',
'Content-Type': 'application/json'},
body: JSON.stringify({
email: this.state.signinEmail,
password: this.state.signinPassword,
}),
})
.then(response => response.json())
.then(data => {
if (data ==='success'){
}
})
}
the server side signing page is as follows:
app.post('/signin', (req, res) => {
if (req.body.email === database.users[0].email && req.body.password === database.users[0].password){
res.json("success");
}else{
res.status(404).json("Error loggingin");
}
})
It's working fine with Postman, the server seems to be ok.
I have tried changing HTTP to https even though my server is HTTP just in case.
Tried restarting both servers, tried changing to fetch to axios but nothing seems to be working.
Any thoughts?
onSubmitSignIn = (event) => {
event.preventDefault() // <= You Need this
fetch("http://192.168.56.1:8560/signin", {
type: 'POST',
headers: {'Accept': 'application/json',
'Content-Type': 'application/json'},
body: JSON.stringify({
email: this.state.signinEmail,
password: this.state.signinPassword,
}),
})
.then(response => response.json())
.then(data => {
if (data ==='success'){
}
})
}
Create-React-App Proxying API Requests in Development -- src/setupProxy.js
People often serve the front-end React app from the same host and port as their backend implementation.
Such setup is not required. However, if you do have a setup like this, it is convenient to write requests like fetch('/api/todos') without worrying about redirecting them to another host or port during development.
To tell the development server to proxy any unknown requests to your API server in development, add a proxy field to your package.json, for example:
"proxy": "http://localhost:8560",
Configuring the Proxy Manually
First, install http-proxy-middleware using npm or Yarn:
$ npm install http-proxy-middleware --save
$ # or
$ yarn add http-proxy-middleware
Next, create src/setupProxy.js and place the following contents in it:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:8560',
changeOrigin: true,
})
);
};
API:
https://create-react-app.dev/docs/proxying-api-requests-in-development/
I'm just replying in case anybody has got the same issue as I was having, after a couple of sleepless nights digging through my code, I figure the template for my login page was taken from a "tachyon" template, what I missed, somewhere in my version control, was a "form" that was actually supposed to be turned into a "div", after going through this question here why-the-post-request-becomes-a-get-request it hit me, basically, if you happen to be taking the information from inside of a "form" and this form does not have a method post, it will automatically turn the API request into a GET request and fill up the URL with the information.
So that is sorted. Now let us tackle the rest of the bugs.
I'm trying to post data. Everything works fine, but I don't know why I'm getting two requests OPTIONS & POST
POST:
OPTIONS:
Here's the code:
const url = 'http://rest.learncode.academy/api/johnbob/myusers';
export function postUsers(username, password) {
let users = {
username,
password,
};
return{
type: "USERS_POST",
payload: axios({
method:'post',
url:url,
data: users,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
}
}
Non-simple CORS requests via AJAX are pre-flighted. Read more about it here. This is a browser behavior and nothing specific to axios. There's nothing inherently wrong with this behavior and if it's working for you, you can just leave it.
If you insist on getting rid of it, there are a few ways you can go about:
You can set Access-Control-Allow-Origin: * on your server to disable CORS.
Make your CORS request a simple one. You will have to change the Content-Type header to application/x-www-form-urlencoded, multipart/form-data, or text/plain. Not application/json.
I'd say just leave it as it is if the OPTIONS request is not blocking you.
I have the following code that makes a post request to my Nodejs app on the backend:
fetch('http://localhost:3000/ws', {
method: 'POST',
body: JSON.stringify(data),
headers: {'Content-Type': 'application/json'}
}).then(res => {
return res.json();
}).then(data => {
alert(JSON.stringify(data));
});
Everything works fine, it sends the request and gets the response successfully. The problem is that most of the browsers allows the users to debug my code, they can put a breakpoint where the response is being handled and modify its values.
How can I prevent them from doing that?
You can't apply that kind of control to code running on the client. You should always assume it's untrusted code running on the client. If you need controls, you'll have to apply them on the server.
I've came across the following error.
At the moment I developing an Android App with React Native therefore I'm planning to use fetch for doing a post request for me.
fetch("https://XXreachable-domainXX.de/api/test", {
method: "post",
body: JSON.stringify({
param: 'param',
param1: 'param',
})
})
.then((response) = > response.json())
.then((responseData) = > {
ToastAndroid.show(
"Response Body -> " + JSON.stringify(responseData.message), ToastAndroid.SHORT
)
})
.catch((error) = > {
console.warn(error);
});
The app now throws an error:
TypeError: Network request failed
When I change the code to a GET-Request it's working fine, in the browser with a window.alert() as a return it's cool and also the Chrome extension Postman returns data correctly.
Developing with Windows OS/PHP built-in server/react-native Android on device:
check server local IP address (ipconfig), e.g. 172.16.0.10
in react-native fetch use this URL and proper port (fetch('http://172.16.0.10:8000/api/foo))
run PHP built-in server with this specific IP instead of the localhost: php -S 172.16.0.10:8000 ...
turn off Windows firewall for the private networks
That fixed the connection problem between Android phone and the local server for me.
This React Native's error is rather useless, so you need to get the actual underlying error first. The most straightforward way is to write a small native program that would just perform the same query using HttpsURLConnection.
For me the actual error was java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
which has a well known solution: https://developer.android.com/training/articles/security-ssl.html#MissingCa
This is quite likely your case also, given that the browsers and Postman have no problem with the request. To check it run openssl s_client -connect XXreachable-domainXX.de:443 -showcerts. If there are certificate errors, fix them first, it could spare you time writing the native program.
Edit: actually the easiest way to see all underlying android errors for react native is simply running 'adb logcat' in terminal
None of the other answers helped me.
The problem was headers:
Old header:
fetch(API_HOST, {
method: 'POST',
headers: {
Accept: 'application/json'
},
body: JSON.stringify(data),
Updated header:
fetch(config.API_HOST, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json' // I added this line
},
body: JSON.stringify(data),
If you have had this error and you are sure everything works well and you are running an emulator, simply close your emulator and fire it up again.
It should run now.
This usually happens after you have hibernated your system for a while
step1>
add android:usesCleartextTraffic="true" line in AndroidManifest.xml like:
// add this line
...
step2>
Delete all debug folder from your android folder..
I had a major issue doing the same on the android emulator. On iOS approving the domain in the info.plist was necessary. To be clear I was attempting to login to my .NET web hosted API.
The fix was to make sure the post data was parameterised.( I'm pretty sure that's a word)
export const loginUser = ({ userName, password }) => {
const data = `UserName=${userName}&Password=${password}&grant_type=password`
return (dispatch) => {
dispatch({ type: LOGIN_USER })
fetch(URL_LOGIN, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: data
// body: {
// UserName: userName,
// Password: password,
// grant_type: 'password'
// }
})
.then((response) => {
loginUserSuccess(dispatch, response)
})
.catch((response) => {
loginUserFailed(dispatch, response)
})
};
};
If you run into this problem on emulator make sure you also test it on the device. It's most probably not happening there.
Just so you know there's nothing to worry about if you can work around it.
I had this problem on Android due to an expired certificate. The error message I had was com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: Certificate expired at Fri Sep 29 16:33:39 EDT 2017 (compared to Fri Dec 08 14:10:58 EST 2017).
I was able to confirm this using digicert.com.
Unfortunately I did have to dig rather deep into the React Native code and debug the XHR code in the bundle (index.android.bundle) in order to find the error message and the URL in question, because it was in some of my logging code, which I obviously didn't log to the console as well. :)
I was helped by this GitHub issue comment.
My issue was fixed when I restarted the emulator
I had same issue using the fetch,this is a type error.so try using Axios. This worked for me.
the code which wasnt working :error:[typeError : network Request failed]
return fetch(addProduceApi, { method: 'PATCH', body: bodyParamData, headers: getAuthHeader() })
.then((response: any) => response.json()) .catch((error: any) => console.log('Error in patchProduce: ', error));
the working code:
return axios.patch(addProduceApi,produceData,{ headers: getAuthHeader()})
.then((response: any) => response.json()) .catch((error: any) => console.log('Error in patchProduce: ', error));?
Check two cases bellow
Wrong end-point
Internet connection: both real-device, virtual-device
It has eaten 2 hour with the second reason.