Sails 1.4.0 CSRF Token sent from React App getting rejected 403 - reactjs

for the last three days I got stuck at this problem and it is getting very frustrating. I don't know what else to try.
I am running a Sails app on localhost:1337 and a create-react-app on localhost:3000.
I enabled csrf on the backend and followed the sails documentation to implement it.
I have created the route
'GET /grant-csrf-token': { action: 'security/grant-csrf-token' } and it works fine, I get the token. If I use postman the token is accpeted and my login form works.
In React however, I receive the token but I get 403 Forbidden error when I submit the post request to login.
useEffect(async () => {
let csrfToken;
try {
let csrfTokenRequest = await Axios.get(
`${state.serverUrl}/grant-csrf-token`
);
csrfToken = csrfTokenRequest.data["_csrf"];
dispatch({
type: "csrf",
value: csrfToken,
});
} catch (err) {
dispatch({
type: "flashMessage",
value: "There was an error.",
});
}
}, []);
I tried various ways to send the token with my post request:
await Axios.post(
`${appState.serverUrl}/login`,
{
emailAddress,
password,
_csrf: appState.csrf,
},
{ withCredentials: true }
);
I also tried setting it as a default header like so:
Axios.defaults.headers.post["X-CSRF-Token"] = appState.csrf;
and set cors allowRequestHeaders parameter to allowRequestHeaders: 'content-type, X-CSRF-Token',
I also tried sending it as a query parameter
`/login?_csrf=${encodeURIComponent(appState.csrf)}`
I also tried various cors settings inside Sails, currently it is setup like so:
cors: {
allRoutes: true,
allowOrigins: [
'http://localhost:3000',
],
allowCredentials: true
}
So just to clarify once again:
The /grant-csrf-token route works fine. I am receiving the token
It works in Postman
In React I get 403 error

Could you try something like that:
Send the csrf in header and allow Sails to process the request header.
// config/security.js
cors: {
allRoutes: true,
allowOrigins: ['http://localhost:3000'],
allowCredentials: true,
allowRequestHeaders: ['content-type', 'x-csrf-token', 'authorization'],
},

Related

How to fetch data from a REST API by using an API-Token

I'm trying to fetch data from the Jira Rest API in my React application by using the Axios library for http requests. An API token is necessary, in order to access data via the Jira API. I generated an API token in my Jira account settings, but I can't figure out, how to include it in my http request to gain access.
This is the endpoint provided by the Jira documentation for getting an issue from the Jira board:
curl -u admin:admin http://localhost:8080/jira/rest/api/2/issue/TEST-10 | python -mjson.tool
This is the React state hook for setting the data to the fetched data:
const [jiraTicket, setJiraTicket] = useState([]);
This is the fetch function for the API request (${} will be filled with user input):
function getJiraTicket() {
axios.get(`${username}:${apiToken}#Content-Type:application/json/https:/${jiraSiteName}.atlassian.net/rest/api/2/issue/${projectKey}-${ticketId}`)
.then((res) => {
const data = res.data;
setJiraTicket(data);
})
}
The button inside the react component return should invoke the fetch function:
return(
<Container>
<Button onClick{getJiraTicket()}>Fetch Jira Ticket</Button>
</Container>
);
This is the error I'm currently getting, because the authorization is not working the way I did it
(I replaced the provided username, API token etc. for this example):
GET http://localhost:3000/username:apitoken#https:/sitename.atlassian.net/rest/api/2/issue/projectkey-ticketid 404 (not found)
Edit:
My current approach:
function getJiraTicket() {
axios.get(`${userName}:${apiToken}#https://${siteName}.atlassian.net/rest/api/2/issue/${projectId}-${ticketId}`,{
auth: {
username: userName,
password: apiToken,
},
withCredentials: true
})
.then((res) => {
const data = res.data;
console.log(data);
setJiraTicket(data);
})
.catch(err => {
// This error means: The request was made and the server responded with a status code
if(err.res) {
console.log(err.res.data);
console.log(err.res.status);
console.log(err.res.headers);
console.log("request was made and server responded with status");
// The request was made but no response was received
} else if (err.request) {
console.log(err.request);
console.log("request was made, but no response was received");
// Something happened in setting up the request that triggered an error
} else {
console.log("Error", err.message);
console.log("request is note set up correctly");
}
console.log(err.config);
})
Current error, which I defined accordingly to the axios doc: "request was made, but no response was received"
Endpoint that works well in Postman (Basic auth is provided in Postman):
https://sitename.atlassian.net/rest/api/2/issue/projectid-ticketid
Update: CORS access isn't allowed, when an application tries to access the Jira API endpoints directly. This restriction takes place in order to prevent random authenticated requests to the specific Jira site, because the access is based on session based authentication. However the API endpoints can be accessed, if OAuth 2.0 is used instead of Basic auth, because the application will redirect the user to the Jira auth itself via this link:
https://auth.atlassian.com/authorize? audience=api.atlassian.com&
client_id=YOUR_CLIENT_ID&
scope=REQUESTED_SCOPE_ONE%20REQUESTED_SCOPE_TWO&
redirect_uri=https://YOUR_APP_CALLBACK_URL&
state=YOUR_USER_BOUND_VALUE& response_type=code& prompt=consent
Source: https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/#known-issues
Axios uses a headers config for get/post so you should not include them in your URL. Here is a general example of how you should construct the URL and apply headers:
let axiosUrl = `https://${jiraSiteName}.atlassian.net/rest/api/2/issue/${projectKey}-${ticketId}`
axios({
baseURL: axiosUrl,
method: 'get',
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin", "*"
},
//timeout: 2000,
auth: {
username: userName,
password: apiToken,
}
})
.then((res) => {
setJiraTicket(res.data);
})
.catch(function (error) {
console.log(error);
});

Facing issue with setting up http only cookie while using react js for frontend and django rest framework for backend

I started building a basic Authentication system with JWT token authentication using rest API and react js. But, I was facing an issue while setting my cookie from the Django views sent using rest_framework.response.Response object. Now, the problem is that in the Django server the cookie is set, but in this case, while integrated with react js it fails. Django server is running on port 8000 and react js on 3000.
#api_view(['POST'])
def login(request):
try:
username = request.data['username']
password = request.data['password']
user = authenticate(request=request, username=username, password=password)
if user:
refresh = RefreshToken.for_user(user)
response = Response()
response.data = {
"status": True,
"Access": str(refresh.access_token)
}
response.set_cookie(key='refreshtoken', value=(refresh), httponly=True, samesite=None)
return response
else:
return Response(FALSE_RESPONSE)
except Exception as e:
print(e)
return Response(FALSE_RESPONSE)
This is the axios request, I was making from the frontend side.
axios({
method: "POST",
url: "http://localhost:8000/user-api/login/",
data: {
username:username,
password:password
},
credentials: 'include',
withCredentials: true
})
.then(response => {
console.log(response)
if(response.data['status']) {
setAccessToken(response.data['Access'])
setIsAuthenticated(true)
setLoginModal(false)
} else {
alert("Error! Credentials doesn't match.")
}
})
.catch(error => {
console.log(error)
})
This axios request generates no errors and I was successfully getting the token, but the refresh token was not getting saved in the cookies.
# settings.py
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:3000"
]
CORS_ALLOW_CREDENTIALS = True
Help me with this issue!!

NextJs CORS issue

I have a Next.js app hosted on Vercel at www.example.com, which needs to communicate with a backend .NET Core Web API hosted on a different server at api.example.com.
The .NET core web api has been configured to allow CORS but my Next.js keeps complaining that data cannot be displayed when I use AXIOS to fetch data because the response lacks allow-cors headers:
Access to XMLHttpRequest at 'https://api.example.com' from origin 'http://www.example.com' 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
It works fine when I run it locally using npm run dev, but doesn't work when I build it and then run npm run start
Does anyone know how to fix the cors issue in production?
I found a solution here:
Basically, I just need to add a next.config.js file in the root directory and add the following:
// next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/api/:path*',
destination: 'https://api.example.com/:path*',
},
]
},
};
if you want to use the cors library in nextjs, I created a library for it is nextjs-cors.
https://www.npmjs.com/nextjs-cors
https://github.com/yonycalsin/nextjs-cors
pages/api/whoami.{ts,js}
import NextCors from 'nextjs-cors';
async function handler(req, res) {
// Run the cors middleware
// nextjs-cors uses the cors package, so we invite you to check the documentation https://github.com/expressjs/cors
await NextCors(req, res, {
// Options
methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],
origin: '*',
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
});
// Rest of the API logic
res.json({ message: 'Hello NextJs Cors!' });
}
it was a problem in the server not accepting OPTIONS requests, because routes were declared as GET::something or POST:: something, so the preflight couldn't pass and the POST request was decliend, hope this will help another people to prevent hours of googling, so in my case (Node.js + Express.js) i had to add this to my server.js
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
if (req.method == "OPTIONS") {
res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET");
return res.status(200).json({});
}
next();
});
I had a similar issue, I was making the call from this page:
pages/page1.js
export default async function page1() {
const data = await axios.post('https://www.dominio.com/xxx' , {param: 1}, headers)
}
But the solution is to make axios calls to a local API file inside "pages/api" directory, and this local API file, will handle the request to the external webserver. This avoid the CORS issue.
pages/page1.js
export default async function page1() {
const data = await axios.post('/api/get_page1_data', {param: 1} )
}
pages/api/get_page1_data.js
export default async function handler(req, res) {
try{
const data = await axios.post('https://www.dominio.com/xxx' , {param: req.body.param}, headers)
res.status(200).json(data)
} catch (error) {
console.error(error)
return res.status(error.status || 500).end(error.message)
}
Do an extra check if your base URL is correct that was my issue
In my case, the preflight request was failing due to an agressive HTTP method filter.
Make sure that you specify
// Preflight Check:
if (req.method == "OPTIONS") {
res.setHeader("Allow", "POST");
return res.status(202).json({});
}
// Allow only POST Methods
if (req.method !== "POST") {
res.setHeader("Allow", "POST");
return res.status(405).json({ error: `Method ${req.method} Not Allowed` });
}
You can allow all methods with https://vercel.com/support/articles/how-to-enable-cors#enabling-cors-in-a-next.js-app, but make sure that each endpoint returns a 2XX status code for the OPTIONS HTTP method.
Please make sure it is CORS and is not something else. For example, in my case I was getting a 400 response. Please look on the Response tab of that request for information.
after hours of googleing i found the solution on the next-docs itself!!!
see the following repository on github
API Routes Example with CORS
https://github.com/vercel/next.js/tree/canary/examples/api-routes-cors
I had this issue taking a SoloLearn NestJS course and it was resolved by adding the line: app.enableCors() in main.ts file on the root folder in the NESTJs Project.
The file was like this:
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
await app.listen(3000);
}
bootstrap();
I have Next.js application that has graphql and Apollo Client setup (apollo version : 3.5.10). In order to make a query inside any component you have to use "client" variable that Apollo Client provide. You need to have apollo-client.js file in your project root so that Apollo Client can use it inside any component for query. Inside any component when you trying to make a query like: client.query(...), with these settings of apollo-client file it will throw "cors" error. However you can fix this by adding headers property inside apollo-client file.
This is OLD Settings:
apollo-client.js (old)
import { ApolloClient, InMemoryCache } from '#apollo/client';
const client = new ApolloClient({
uri: 'http://localhost:4000/graphql',
cache: new InMemoryCache(),
});
export default client;
This is NEW Settings:
apollo-client.js (new)
import { ApolloClient, InMemoryCache } from '#apollo/client';
const client = new ApolloClient({
uri: 'http://localhost:4000/graphql',
cache: new InMemoryCache(),
headers: {
fetchOptions: {
mode: 'no-cors',
},
},
});
export default client;
By doing this, you won't get any "cors" error while doing query inside any component.

Proxy error: Could not proxy request /payment from localhost:3000 to https://localhost:5000/

I am trying to create a stripe payment app using reactJS and expressJS, I am getting this error:
Proxy error: Could not proxy request /payment from localhost:3000 to https://localhost:5000/
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (EPROTO)
In package.json file I have set proxy as -
"proxy": "https://localhost:5000"
In my react component I have -
const onToken = token => {
axios({
url: "payment",
method: "post",
data: {
amount: priceForStripe,
token: token
}
})
.then(response => {
alert("succesful payment");
})
.catch(error => {
console.log("Payment Error: ", error);
alert(
"There was an issue with your payment! Please make sure you use the provided credit card."
);
});
};
In my server.js I have -
const stripe = require("stripe")("sk_test_...");
app.post("/payment", (req, res) => {
const body = {
source: req.body.token.id,
amount: req.body.amount,
currency: "usd"
};
stripe.charges.create(body, (stripeErr, stripeRes) => {
if (stripeErr) {
res.status(500).send({ error: stripeErr });
} else {
res.status(200).send({ success: stripeRes });
}
});
});
whenever I submit any payment I hit error -
I tried all method linked here but can't solve that issue. I heartily thank if anyone explain any solution of that problem.
Since your backend works fine without stripe, the 500 error indicates that stripe is the problem.
This is related to the information you are sending in the body of the stripe charges.create request. I think you are missing the customer.id.
This post arjunphp.com/node-stripe-express-js shows the charges.create request as
{ amount,
description: "Sample Charge",
currency: "usd",
customer: customer.id
}
As #CherryDT mentioned, first I set proxy to "proxy": "http://localhost:5000". Then I change my backend code as #Greg M suggested -
app.post("/payment", (req, res) => {
stripe.customers
.create({
email: req.body.email, // customer email, which user need to enter while making payment
source: req.body.token.id // token for the given card
})
.then(customer =>
stripe.charges.create({
// charge the customer
amount: req.body.amount,
description: "Sample Charge",
currency: "usd",
customer: customer.id
})
)
.then(charge => res.status(200).send({ success: "success" }));
});
That's it. My payment method works perfectly.
I think the proxy error is a red herring. The real issue is the parsing on your server, causing the 500.
It looks like by default Axios encodes the json for you (but you should double check the request). To access JSON encoded request body data in Express, you need to use the body-parser middleware.
See this answer for an example: How do I consume the JSON POST data in an Express application
I'm taking the exact react course from Andre. My solution was to start the backend server.
So whoever gets into this issue from the same course either try the answer above or:
npm start
or
yarn start

Axios having CORS issue

I added proxy in package.json and it worked great, but after npm run build the CORS issue has resurfaced again, does anyone know how to deal with CORS issue after npm run build in React.
I have tried to add headers in axios request using various methods. However, I failed to add 'Access-Control-Allow-Origin':'*' in axios request. My code is as follwing:
package.json
"proxy": {
"*":{ "target" : "http://myurl"}
}
GetData.js
axios.defaults.baseURL = 'http://myurl';
axios.defaults.headers.post['Content-Type'] ='application/json;charset=utf-8';
axios.defaults.headers.post['Access-Control-Allow-Origin'] = '*';
axios.get(serviceUrl, onSuccess, onFailure)
.then(resp => {
let result = resp.data;
onSuccess(result);
})
.catch(error => {
if(onFailure) {
return onFailure(error);
}
})
}
Note: It has enabled from server side, it is still not working.Currently, I can't change code from server side, My work is limited to client side only.
your server should enable the cross origin requests, not the client. To do this, you can check this nice page with implementations and configurations for multiple platforms
Just noting my solution for someone who might get here from googling. I resolved my CORS issue (when calling an external api from my UI in the browser) by setting withCredentials to false in my axios call:
axios({
method: 'get',
url: `https://api.someurl.com/subject/v2/resource/somevalue`,
withCredentials: false,
params: {
access_token: SECRET_TOKEN,
},
});
In this case, the external api's endpoint's security is based on the access_token.
May be helpful to someone:
I'm sending data from a react application to a golang server.
Once I change this, w.Header().Set("Access-Control-Allow-Origin", "*"), the error was fixed.
React form submit function:
async handleSubmit(e) {
e.preventDefault();
const headers = {
'Content-Type': 'text/plain'
};
await axios.post(
'http://localhost:3001/login',
{
user_name: this.state.user_name,
password: this.state.password,
},
{headers}
).then(response => {
console.log("Success ========>", response);
})
.catch(error => {
console.log("Error ========>", error);
}
)
}
Go server got Router,
func main() {
router := mux.NewRouter()
router.HandleFunc("/login", Login.Login).Methods("POST")
log.Fatal(http.ListenAndServe(":3001", router))
}
Login.go,
func Login(w http.ResponseWriter, r *http.Request) {
var user = Models.User{}
data, err := ioutil.ReadAll(r.Body)
if err == nil {
err := json.Unmarshal(data, &user)
if err == nil {
user = Postgres.GetUser(user.UserName, user.Password)
w.Header().Set("Access-Control-Allow-Origin", "*")
json.NewEncoder(w).Encode(user)
}
}
}
I have encountered with same issue. When I changed content type it has solved. I'm not sure
this solution will help you but maybe it is. If you don't mind about content-type, it worked for me.
axios.defaults.headers.post['Content-Type'] ='application/x-www-form-urlencoded';
This is happening because of restrict-origin-when-cross-origin policy.Browser sends a pre-flight request to know whom the API server wants to share the resources. So you have to set origin there in API server and send some status.After that the browser allow to send the request to the API server.
Here is the code.I am running front-end on localhost:8000 and api server is running on port 6000.
const cors = require("cors");
app.options("*", cors({ origin: 'http://localhost:8000', optionsSuccessStatus: 200 }));
app.use(cors({ origin: "http://localhost:8000", optionsSuccessStatus: 200 }));
I have set origin as my front-end url, If You set it to true , then it will allow only port 8000 to access rosource, and front-end running on port 8000 can not access this resource. Use this middleware before route in api server.
I had got the same CORS error while working on a Vue.js project. You can resolve this either by building a proxy server or another way would be to disable the security settings of your browser (eg, CHROME) for accessing cross origin apis (this is temporary solution & not the best way to solve the issue). Both these solutions had worked for me. The later solution does not require any mock server or a proxy server to be build. Both these solutions can be resolved at the front end.
You can disable the chrome security settings for accessing apis out of the origin by typing the below command on the terminal:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir="/tmp/chrome_dev_session" --disable-web-security
After running the above command on your terminal, a new chrome window with security settings disabled will open up. Now, run your program (npm run serve / npm run dev) again and this time you will not get any CORS error and would be able to GET request using axios.
Hope this helps!
This work out for me :
in javascript :
Axios({
method: 'post',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
url: 'https://localhost:44346/Order/Order/GiveOrder',
data: order
}).then(function (response) {
console.log(response.data);
});
and in the backend (.net core) :
in startup:
#region Allow-Orgin
services.AddCors(c =>
{
c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
});
#endregion
and in controller before action
[EnableCors("AllowOrigin")]
CORS issue is something you will only encounter on a Broswer. It occurs beacuse the server does not allow request from others servers
i.e If I am sending request from http://localhost:3000 to any api(http://example.com/users) to get the user data from here.
If the server does not recognize your local host
#CrossOrigin(Origin = "*") // this will allow any request from any server you will not face CORS issue if you us this annotation
Now what if you are sending a request using axios in react to another sever which is not in your control the way to overcome that issue is by using http-proxy-middleware
npm i http-proxy-middleware // install this dependency
axios.{
method: 'post',
url: '/endpoint',
headers: {
'Content-Type': 'application/json',
},
proxy: createProxyMiddleware({
target: 'https://www.api.com',
changeOrigin: true}),
data: data
};
Now in this way a proxy request to www.api.com/endpoint will be sent and thus you will not recieve a cors issue
also add this in your package.json
"proxy": "https://www.api.com"
I come across this thread when having the same problem using Axios. What was not mentioned in the responses is that using fetch with no-cors mode can solve your issue.
Why ?
Apparently, Axios uses a XMLHttpRequest under the hood, not Request
and Axios fails because CORS is still being enforced and no-cors mode
is not supported.
Check this thread for more information
Please try this .. it worked for me
axios.get(`http://localhost:4000/api`,{ crossdomain: true }).then((result)=>{
console.log("result",result);
}).catch((error)=>{
console.log("Error",error);
});
Just simply add this to your headers
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
}
No need to use Access-Control-Allow-Origin : *
CORS issue can be simply resolved by following this:
Create a new shortcut of Google Chrome(update browser installation path accordingly) with following value:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="D:\chrome\temp"

Resources