I am trying to call API to authenticate user. getting 200 success response but not getting JSESSIONID cookie in response.
axios.defaults.withCredentials = 'true';
axios.defaults.crossDomain = 'true';
axios.defaults.headers.post['Content-Type'] = 'application/json';
axios.defaults.headers.post['withCredentials'] = 'true';
const data = {
username: this.state.user,
credential: this.state.pass
}
axios.post('http://3.122.7.162:5000/v60/admin/session', data)
.then(response => {
console.log("response");
console.log(response);
})
.catch(error => {
console.log("error");
console.log(error);
});
Thanks
XMLHttpRequest and fetch (the built-in HTTP request libraries in browsers) do not expose information about cookies in their response object.
It isn't even available through directly reading the Set-Cookie header because it is a forbidden response header.
The only way to read cookie data is through document.cookie, but that only provides information about same origin cookies.
There is no direct way to get the data from a cross-origin cookie using Ajax methods. The only way to do it would be to change the server side code so it returned a copy of the cookie data through another path that the JavaScript could read (e.g. in the response body).
This doesn't stop you using the cookies. Unless third-party cookies are disabled, they will still be set in the browser's cookie jar and automatically sent with future requests to the domain they belong to.
Related
I am attempting to follow this EBAY User Consent API article https://developer.ebay.com/api-docs/static/oauth-consent-request.html
but I am getting a CORS error "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."
I've read numerous Cors posts here this one being a good one: XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header but none of these solutions seem to work.
a pointer in the right direction would be great.
$(document).on('click','.ebay_access', async function(event) {
let scopes = encodeURIComponent("https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.marketing.readonly https://api.ebay.com/oauth/api_scope/sell.marketing https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.account https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly https://api.ebay.com/oauth/api_scope/sell.fulfillment https://api.ebay.com/oauth/api_scope/sell.analytics.readonly https://api.ebay.com/oauth/api_scope/sell.finances https://api.ebay.com/oauth/api_scope/sell.payment.dispute https://api.ebay.com/oauth/api_scope/commerce.identity.readonly https://api.ebay.com/oauth/api_scope/commerce.notification.subscription https://api.ebay.com/oauth/api_scope/commerce.notification.subscription.readonly");
let clientId = "{{env('EBAY_APIKEY')}}";
let clientSecret = "{{env('EBAY_API_CERT_NAME')}}";
let oAuthCredentials64 = btoa(clientId + ":" + clientSecret);
let endpoint = 'https://api.ebay.com/identity/v1/oauth2/token';
try{
let response = await fetch(endpoint,
{
method: "POST",
headers:
{
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${oAuthCredentials64}`
},
body:
"grant_type=client_credentials&scope=" + scopes
}
);
let responseJson = await response.json();
console.log("CLIENT ACCESS TOKEN", responseJson);
} catch(err){
console.log("error: ", err);
};
}); //end function
The request you are making seems to be an authentication request, or "consent request", as eBay call it. This must be made to the authorization endpoint (probably https://api.ebay.com/identity/v1/oauth2/authorize). But you make it to the token endpoint (https://api.ebay.com/identity/v1/oauth2/token), as if it were a token request. But the token request is only the second step ("Exchanging the authorization code for a User access token").
Moreover, neither the authentication request nor the token request are CORS requests:
The authentication request must happen in a visible browsing context, as explained here. The user can only consent if they see what is going on.
The token request is not made by the browser, because this would expose the secret (as pointed out in Jags's answer). It must be made by your server.
In other words: No CORS should be involved at all. The eBay API article explains this correctly.
There are multiple issues here.
In general, if the URL - domain on your browser is not same as the ajax call browser is making then you get this error.
Seems that you have copied the code which was meant for server side execution. You should NEVER expose your credentials to client side. Anyone can use your steal your credentials.
The github link you provided as reference is for server side nodejs application which is running as an app and not under browser.
I understand that there are many similar questions, but I am posting this because I feel it is slightly different.
I am trying to send a GET request to the Slack API using an HTTP request.
Specifically, the code looks like the following.
import useSWR from "swr";
const useSlackSearch = (query: string) => {
const token = process.env.NEXT_PUBLIC_SLACK_API_USER_TOKEN;
const myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer " + token);
const slackURL = `https://slack.com/api/search.messages?query=${query}`;
const fetcher = async (url: string) => {
const response = await fetch(url, {
headers: myHeaders,
}).then((res) => res.json());
return response;
};
const { data, error } = useSWR(slackURL, fetcher, {
revalidateOnFocus: true,
revalidateOnReconnect: true,
});
if (error) {
return console.log(`Failed to load: ${error}`);
} else if (!data) {
return console.log("Loading...");
} else {
console.log(data);
return data;
}
};
export default useSlackSearch;
The environments I'm using are as follows.
Device: MacBook Air
OS: macOS
Browser: Chrome
From: localhost:3000
To: Slack API html page (https://slack.com/api/search.messages)
After reading the MDN articles like below, I understood that
There is such a thing as a simple HTTP request as defined by MDN
If the request you want to send does not correspond to this simple request, the browser will send a preflight request
In the response to that preflight request, there is a header called Access-Control-Allow-Headers.
Only headers set to the value of this Access-Control-Allow-Headers header can be used as headers in the main request after preflighting.
In this case, I tried to use the Authorization header, but it was trapped by the above restriction.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests
https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
That's all I understand.
However, on the official Slack API page for the method in question, it says to specify the token in the Authorization header, so I'm having trouble.
I also don't understand how to specify the Access-Control-Request-Headers in the preflight header, as described in another questioner's thread. The reason is that the only thing that communicates to the Slack API is the browser in this case, and the only relevant source is JavaScript (React / Next.js to be exact)!
After that, I found preflight response from Slack API as follows;
access-control-allow-headers: slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid, x-b3-sampled, x-b3-flags
As I thought, I understand that Authorization is not allowed because it is not included as a value. So the question is how to solve it.
Furthermore, I found out later that the preflight request from the browser properly declared that it wanted to use Authorization as an actual request header. However, the preflight response did not contain the value.
Following CBroe's advice, I was able to contact the Slack help center directly, so I asked this problem. What I found out as a result is that HTTP requests from browsers are not supported as of the end of February 2022. Of course, they have received quite a lot of requests regarding this, so they hope to address it at some point.
This time, the browser sent Access-Control-Request-Headers:Authorization in the preflight request. But the Slack API server side did not allow the Authorization header in the request from the browser. Therefore, Authorization was not set in the Access-Control-Allow-Headers in the preflight response from the Slack API side.
As a result, the response from the Slack API side returned Invalid Auth, even though Authorization was added as a header when making an actual request from the browser.
Through this error, I gained a deeper understanding of HTTP requests such as CORS and preflighting, but since it is not explicitly written on the official Slack website, I left it here.
What is Preflight: https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
What is Access-Control-Allow-Header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
What is CORS simple request: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests
I could not get the Authorization header to work either. However, Slack provided this example for adding token authentication to the Post body following the deprecation of the query parameters method.
This worked for me to make Web API calls to Slack from the browser (for testing) so that Slack would read the token for authentication. Note, according to Slack's best practices for security, user and bot tokens should be stored with care and not used in client-side Javascript:
try {
const res = await fetch("https://slack.com/api/conversations.list", {
method: "POST",
body: `token=${TOKEN}`, // body data type must match "Content-Type" header
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
}).catch((error) => {
console.log(error);
});
if (!res.ok) {
throw new Error(`Server error ${res.status}`);
} else {
const data = await res.json();
console.log(data);
}
} catch (error) {
console.log(error);
}
using token in request body instead of Authorization header worked for me.
axios({
method: 'post',
url: 'https://slack.com/api/chat.postMessage',
data: `text=Hi&channel=D048GGYTJUK&token=${process.env.TOKEN}`
})
In a fetch handler triggered by a page navigation, I tried to do this:
return event.respondWith(new Response('Hello!', {
headers: {
"Set-Cookie": "TestCookie=foo; path=/; Max-Age=60;"
"TestHeader": "foo"
}
}));
Then I loaded any URL in the browser, and got the "Hello!" body. In Chrome devtools, I see the TestHeader set in the network panel. But the cookie is not showing up in the network panel, nor in the Application > Cookies viewer. document.cookie also fails to produce it.
The request is initiated by a page navigation, so there's no opportunity to set credentials: "include" on the fetch from the browser tab.
Is it possible to add a cookie to a response in the ServiceWorker? If not, is it possible to write cookies in any other way?
There's some relevant information in the Fetch specification.
As per https://fetch.spec.whatwg.org/#forbidden-response-header-name:
A forbidden response-header name is a header name that is a
byte-case-insensitive match for one of:
Set-Cookie
Set-Cookie2
And then as per item 6 in https://fetch.spec.whatwg.org/#concept-headers-append:
Otherwise, if guard is "response" and name is a forbidden response-header name, return.
This restriction on adding in the Set-Cookie header applies to either constructing new Response objects with an initial set of headers, or adding in headers after the fact to an existing Response object.
There is a plan to add in support for reading and writing cookies inside of a service worker, but that will use a mechanism other than the Set-Cookie header in a Response object. There's more information about the plans in this GitHub issue.
You may try following:
async function handleRequest(request) {
let response = await fetch(request.url, request);
// Copy the response so that we can modify headers.
response = new Response(response.body, response)
response.headers.set("Set-Cookie", "test=1234");
return response;
}
I am trying to make a POST request to the server (Which is a REST service)via javascript,and in my request i want to send a cookie.My below code is not working ,as I am not able to receive cookie at the server side.Below are my client side and server side code.
Client side :
var client = new XMLHttpRequest();
var request_data=JSON.stringify(data);
var endPoint="http://localhost:8080/pcap";
var cookie="session=abc";
client.open("POST", endPoint, false);//This Post will become put
client.setRequestHeader("Accept", "application/json");
client.setRequestHeader("Content-Type","application/json");
client.setRequestHeader("Set-Cookie","session=abc");
client.setRequestHeader("Cookie",cookie);
client.send(request_data);
Server Side:
public #ResponseBody ResponseEntity getPcap(HttpServletRequest request,#RequestBody PcapParameters pcap_params ){
Cookie cookies[]=request.getCookies();//Its coming as NULL
String cook=request.getHeader("Cookie");//Its coming as NULL
}
See the documentation:
Terminate these steps if header is a case-insensitive match for one of the following headers … Cookie
You cannot explicitly set a Cookie header using XHR.
It looks like you are making a cross origin request (you are using an absolute URI).
You can set withCredentials to include cookies.
True when user credentials are to be included in a cross-origin request. False when they are to be excluded in a cross-origin request and when cookies are to be ignored in its response. Initially false.
Such:
client.withCredentials = true;
This will only work if http://localhost:8080 has set a cookie using one of the supported methods (such as in an HTTP Set-Cookie response header).
Failing that, you will have to encode the data you wanted to put in the cookie somewhere else.
This can also be done with the more modern fetch
fetch(url, {
method: 'POST',
credentials: 'include'
//other options
}).then(response => console.log("Response status: ", response.status));
I'm trying to establish a session using AngularJS, as follows:
var login = function (email, pw) {
$http.post('http://some_api/api/v1/users/sign_in', {'email': email, 'password': pw}
).
success(function (data, status, headers, config) {
alert('success');
console.log(status, headers());
SessionService.isLogged = true,
SessionService.name = data.name,
SessionService.id = data.id,
SessionService.email = email,
SessionService.password = pw,
SessionService.coverUrl = data.coverUrl,
SessionService.imageUrl = data.imageUrl;
// TODO Also store venue id associated to user if applicable
SessionService.venueId;
//TODO route to whatever page we came from in the case that user is being asked to re-authenticate
$location.url('/summary');
}
).
error(function(data, status, headers, config){
SessionService.destroy();
alert('login failure');
}
);
However, when the request response comes back from the API, I only get the following headers by using the $cookies service:
cache-control: "max-age=0, private, must-revalidate"
content-type: "application/json; charset=utf-8"
However, I know the cookie is sent back from the server because Chrome sends it back in the Developer Tools as a populated Set-Cookie header. I read in another question that AngularJS cannot access the Set-Cookie header because the $http service because the inherent spec of the Javascript functions it calls returns all headers except the Set-Cookie header. Thus, my questions are:
Why are the cookies sent back by the API present in the Developer
Tools but do not actually get stored in the browser? (I checked the
browser cookies with an extension and there were none present).
Aren't any cookies sent back by the API to the browser supposed to
be intercepted and stored in the browser's cookie storage? (I also
wonder if this has to do with the run-loop in angular...since my
pages never reload - they are routed using ngRoute with no extra
page loads)
And if the above turns out to be that the Browser will not store
cookies received from a javascript/angular request, how would I
store the cookies? I've seen use of $cookies.mySession =
"cookieContentHere"; but how am I to make use of this if I can't
access the Set-Cookie header?
Thanks for all answers in advance!