return fetch(`{SERVICE API URL}`, {
method: 'GET',
headers: {
'userName': "username",
'password': "password",
'content-type': 'application/json'
}
})
.then(response => response.json())
.then(json => dispatch(receivePosts(reddit, json)))
I'm trying to get service API data with authorization headers, but getting 401 - Unauthorized error and the response is Missing Request Headers.
Tried with sending authorization content with body also - getting same error 401 - Unauthorized error.
Edited:
headers: {
'userName': "xyz",
'sessionToken': "xyz................."
}
When I'm checking with Postman client it is working fine, but not with the redux-saga fetch method. Kindly help me for this.
Looks like it's a backend problem - CORS Filter configuration
If the backend is on a different server (could be on the same machine, but in a different Application Server, in other words, on a different port) you have to do some CORS Filters configurations.
The frontend code is running on a server - that means it's an application. Postman is a client, just like Google Chrome or any other browser. That's the explanation why you can do the request without any problem from Postman but unsuccessful from your frontend application.
I guess you enabled the Access-Control-Allow-Origin header on the backend
Now you have to allow your custom headers with Access-Control-Allow-Headers
Whenever I use fetch and I need to add headers to the request I do it this way:
headers: new Headers({
Accept: 'application/json',
Authorization: token,
'Content-Type': 'application/json',
}),
so you might want to try this approach, also in order to debug this issue you might want to check your Netowrk tab and verify which headers are sent with the request.
You need to add an Authorization bearer header.
For instance:
headers = new Headers({
'Authorization': `Bearer ${authorizationCodeOrCredentials}`
});
In your code:
return fetch(`{SERVICE API URL}`, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + someValue, // Add this line
'userName': "username",
'password': "password",
'content-type': 'application/json'
}
})
.then(response => response.json())
.then(json => dispatch(receivePosts(reddit, json)))
If you are using Linux system & If you have chrome in it...
Run your chrome using following command
/opt/google/chrome/chrome --disable-web-security --user-data-dir
Try now, If everything works fine then it's CORS issue from Backend.
Related
I am trying out the new Fetch API but is having trouble with Cookies. Specifically, after a successful login, there is a Cookie header in future requests, but Fetch seems to ignore that headers, and all my requests made with Fetch is unauthorized.
Is it because Fetch is still not ready or Fetch does not work with Cookies?
I build my app with Webpack. I also use Fetch in React Native, which does not have the same issue.
Fetch does not use cookie by default. To enable cookie, do this:
fetch(url, {
credentials: "same-origin"
}).then(...).catch(...);
In addition to #Khanetor's answer, for those who are working with cross-origin requests: credentials: 'include'
Sample JSON fetch request:
fetch(url, {
method: 'GET',
credentials: 'include'
})
.then((response) => response.json())
.then((json) => {
console.log('Gotcha');
}).catch((err) => {
console.log(err);
});
https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
Have just solved. Just two f. days of brutforce
For me the secret was in following:
I called POST /api/auth and see that cookies were successfully received.
Then calling GET /api/users/ with credentials: 'include' and got 401 unauth, because of no cookies were sent with the request.
The KEY is to set credentials: 'include' for the first /api/auth call too.
If you are reading this in 2019, credentials: "same-origin" is the default value.
fetch(url).then
Programmatically overwriting Cookie header in browser side won't work.
In fetch documentation, Note that some names are forbidden. is mentioned. And Cookie happens to be one of the forbidden header names, which cannot be modified programmatically. Take the following code for example:
Executed in the Chrome DevTools console of page https://httpbin.org/, Cookie: 'xxx=yyy' will be ignored, and the browser will always send the value of document.cookie as the cookie if there is one.
If executed on a different origin, no cookie is sent.
fetch('https://httpbin.org/cookies', {
headers: {
Cookie: 'xxx=yyy'
}
}).then(response => response.json())
.then(data => console.log(JSON.stringify(data, null, 2)));
P.S. You can create a sample cookie foo=bar by opening https://httpbin.org/cookies/set/foo/bar in the chrome browser.
See Forbidden header name for details.
Just adding to the correct answers here for .net webapi2 users.
If you are using cors because your client site is served from a different address as your webapi then you need to also include SupportsCredentials=true on the server side configuration.
// Access-Control-Allow-Origin
// https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
var cors = new EnableCorsAttribute(Settings.CORSSites,"*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
This works for me:
import Cookies from 'universal-cookie';
const cookies = new Cookies();
function headers(set_cookie=false) {
let headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
};
if (set_cookie) {
headers['Authorization'] = "Bearer " + cookies.get('remember_user_token');
}
return headers;
}
Then build your call:
export function fetchTests(user_id) {
return function (dispatch) {
let data = {
method: 'POST',
credentials: 'same-origin',
mode: 'same-origin',
body: JSON.stringify({
user_id: user_id
}),
headers: headers(true)
};
return fetch('/api/v1/tests/listing/', data)
.then(response => response.json())
.then(json => dispatch(receiveTests(json)));
};
}
My issue was my cookie was set on a specific URL path (e.g., /auth), but I was fetching to a different path. I needed to set my cookie's path to /.
If it still doesn't work for you after fixing the credentials.
I also was using the :
credentials: "same-origin"
and it used to work, then it didn't anymore suddenly, after digging much I realized that I had change my website url to http://192.168.1.100 to test it in LAN, and that was the url which was being used to send the request, even though I was on http://localhost:3000.
So in conclusion, be sure that the domain of the page matches the domain of the fetch url.
I am trying out the new Fetch API but is having trouble with Cookies. Specifically, after a successful login, there is a Cookie header in future requests, but Fetch seems to ignore that headers, and all my requests made with Fetch is unauthorized.
Is it because Fetch is still not ready or Fetch does not work with Cookies?
I build my app with Webpack. I also use Fetch in React Native, which does not have the same issue.
Fetch does not use cookie by default. To enable cookie, do this:
fetch(url, {
credentials: "same-origin"
}).then(...).catch(...);
In addition to #Khanetor's answer, for those who are working with cross-origin requests: credentials: 'include'
Sample JSON fetch request:
fetch(url, {
method: 'GET',
credentials: 'include'
})
.then((response) => response.json())
.then((json) => {
console.log('Gotcha');
}).catch((err) => {
console.log(err);
});
https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
Have just solved. Just two f. days of brutforce
For me the secret was in following:
I called POST /api/auth and see that cookies were successfully received.
Then calling GET /api/users/ with credentials: 'include' and got 401 unauth, because of no cookies were sent with the request.
The KEY is to set credentials: 'include' for the first /api/auth call too.
If you are reading this in 2019, credentials: "same-origin" is the default value.
fetch(url).then
Programmatically overwriting Cookie header in browser side won't work.
In fetch documentation, Note that some names are forbidden. is mentioned. And Cookie happens to be one of the forbidden header names, which cannot be modified programmatically. Take the following code for example:
Executed in the Chrome DevTools console of page https://httpbin.org/, Cookie: 'xxx=yyy' will be ignored, and the browser will always send the value of document.cookie as the cookie if there is one.
If executed on a different origin, no cookie is sent.
fetch('https://httpbin.org/cookies', {
headers: {
Cookie: 'xxx=yyy'
}
}).then(response => response.json())
.then(data => console.log(JSON.stringify(data, null, 2)));
P.S. You can create a sample cookie foo=bar by opening https://httpbin.org/cookies/set/foo/bar in the chrome browser.
See Forbidden header name for details.
Just adding to the correct answers here for .net webapi2 users.
If you are using cors because your client site is served from a different address as your webapi then you need to also include SupportsCredentials=true on the server side configuration.
// Access-Control-Allow-Origin
// https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
var cors = new EnableCorsAttribute(Settings.CORSSites,"*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
This works for me:
import Cookies from 'universal-cookie';
const cookies = new Cookies();
function headers(set_cookie=false) {
let headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
};
if (set_cookie) {
headers['Authorization'] = "Bearer " + cookies.get('remember_user_token');
}
return headers;
}
Then build your call:
export function fetchTests(user_id) {
return function (dispatch) {
let data = {
method: 'POST',
credentials: 'same-origin',
mode: 'same-origin',
body: JSON.stringify({
user_id: user_id
}),
headers: headers(true)
};
return fetch('/api/v1/tests/listing/', data)
.then(response => response.json())
.then(json => dispatch(receiveTests(json)));
};
}
My issue was my cookie was set on a specific URL path (e.g., /auth), but I was fetching to a different path. I needed to set my cookie's path to /.
If it still doesn't work for you after fixing the credentials.
I also was using the :
credentials: "same-origin"
and it used to work, then it didn't anymore suddenly, after digging much I realized that I had change my website url to http://192.168.1.100 to test it in LAN, and that was the url which was being used to send the request, even though I was on http://localhost:3000.
So in conclusion, be sure that the domain of the page matches the domain of the fetch url.
I am trying to run a post request from office scripts on an api, but kept getting a failed to fetch error each time when I add :
"Content-type": "application/json"
to the header, once I remove the content-type option or replace its value with something other than "application/json" , then the fetch request works , but returns an error with code 0 and validation error messages indicating that the userName and password ('which are already defined in the body could not be found'):
Below is the code
async function main(workbook: ExcelScript.Workbook) {
const param = {
method: "POST",
headers: {
//"Content-type": "application/json"
},
body: JSON.stringify({ user_id: "uname", password: "pwd"})
};
await fetch("https://testAPI/login/", param).then(response => response.json())
.then(data => console.log(data));
}
error when I run this code with Content-Type header set to 'application/json' (line 33 contains the fetch instruction ):
Line 33: Failed to fetch
Error when I run this code with content-Type set to 'text/plain', other options or completely removing the content-type property from the header :
Also , this same request from postman or power automate with header content-type set to 'application/json' runs successfully , the issue happens only in office script
The issue could potentially have to do with CORS. I had to include CORS headers on the API endpoint I was trying to hit. This may be the issue since you said the status code of the response was 0. Why fetch return a response with status = 0?
I added the following headers to the API route:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-For
Here is my OfficeScript code for reference:
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(cellData),
headers: {
'Content-Type': 'application/json'
}
})
I created a Formik login form and call to react js fetch method. Add cors in web api end and successfully run in Postman and jquery. How to call "token_type": "bearer", through react js? cors is also enabled in web api and also generate Token successfully. How to call this url https://localhost:44323/token through react js?
My code is
onSubmit={(values) => {
fetch('https://localhost:44323/token', {
method: 'POST',
header: { 'Content-type': 'application/json,multipart/form-data' },
data: JSON.stringify(values)
})
.then(r => r.json())
.then(res => {
console.log(res)
});
}}>
Error messages
The root cause of the problem can be found in the following error message shown:
"Access to fetch at https://localhost:44323/token from origin http://localhost:3000 has been blocked by CORS policy. No Access-Control-Allow-Origin header is present on the requested resource ...."
How to fix the problem?
The problem can be fixed in these ways:
1. Allow the origin (http://localhost:3000) on the server (Recommended)
This can be done by adding the following header to HTTP response on the server side:
Access-Control-Allow-Origin: http://localhost:3000
2. Send Fetch request in the 'no-cors' mode
This can be done by updating the fetch request as follows:
fetch( 'https://localhost:44323/token',
{
method: 'POST',
mode: 'no-cors',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
}
)
.then(response => {
// Code for processing the response
}
)
.catch((error) => {
// Code for handling the error
}
)
More information:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
I'm making a POST request to a node.js server and I'm having trouble getting it to work. Here's my request:
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'this-can-be-anything',
};
export const postVote = (id, vote) =>
fetch(`${uri}/posts/${id}`, {
method: 'POST',
headers,
body: JSON.stringify({options: vote}),
}).then(response => response.json())
.then(data => data)
.catch(err => console.log(err));
The function accepts an 'id' and a 'vote', both strings. The id is being used as part of the URI in the request, and the vote is being supplied as options so the API knows what to do with it. Both of the arguments are being passed correctly:
id = '8xf0y6ziyjabvozdd253nd'
vote = 'upVote'
Here's a link to the GitHub repository for the server/API:
Udacity Readable API
and a screenshot of the network when firing the request:
UPDATE: Added the second screenshot which shows status 200. Though it shows this and appears to have been successful, it still doesn't post to the server and the information stays the same.
What you are looking at is the OPTIONS request in the network tab. For cross origin requests, every request if preceeded by an OPTIONS request which tells the calling client (browser, for example) if those HTTP methods are supported by the remote server for use in crosss origin context.
Check the other requests out. If the OPTIONS request was responded to correctly by the server, the browser must automatically follow up with your POST request
EDIT:
Also, the docs specify the param name to be option whereas in your screenshot it is coming up as options.
Further reading: CORS
Try declaring the headers as such:
var headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'this-can-be-anything',
})