So I'm using react native websockets but cannot figure out how i can include cookies in websockets, any suggestions?
At the moment there is no automatic way to do it. There is a third (undocumented) parameter for the WebSocket constructor to pass custom HTTP headers to the connect request.
WebSocket(url, '', {Cookie: 'key=value'});
This works on iOS, I haven't tested it on Android but the WebSocket implementation looks like it is supported there as well.
If you just need to pass a session id or auth token, it's probably easier to pass it as a GET param in the url. Relying on undocumented behavior in a rapidly changing framework can be dangerous.
If you look at the WebSocket declaration, you can see that the header keys should be strings.
This works for me:
var headers = {};
headers["cookie"] = `cookieName=${cookieValue}`;
const ws = new WebSocket(`wss://www.somesite.com/socket`, null, {
headers
});
not this:
{
headers: {
cookie: `cookieName=${cookieValue}`
}
}
As of React Native 0.38, this should happen automatically on Android.
There's currently an open PR for making it work automatically on iOS as well, but at the moment it seems there's still some work left there around testing.
In the meanwhile, you could follow the "manual approach" proposed here:
Manual approach is to retrieve the cookie through a cookie manager plugin and pass it as headers to web socket.
(Once you have the cookie from the manager, the way to pass it to the websocket is, as mentioned previously, to use the undocumented 3rd parameter of WebSocket.)
Related
Basically I'm just messing around with a library which should work with some API (for studying purpose). So, in order to conform OAuth protocol I need to authorize using some sort of web view and get access token. AT is passed as GET parameter after redirection. As a novice in Qt, I have no idea how to track web view state and fetch essential data.
Practically I have an auth procedure that takes a callback, which has to return access token afterwards, as a parameter.
vk_api::auth<>("123456", vk_api::scopes::friends, [this](const std::string& contents) -> std::string {
this->ui->m_webview->setHtml(QString(contents.c_str()));
...
});
Also, I do not want to block UI while calling it.
Some options you have:
Use the new Qt Network Authorization library.
If you want to do it yourself, the usual way is to let the service redirect to a localhost port, which you listen to. See QTcpServer and Network Programming with Qt for that.
Qt WebKit is deprecated, use QWebEngineView instead. You can intercept requests and look for the authorization token using a QWebEngineUrlRequestInterceptor
You can intercept requests made from Qt WebKit and look for the authorization by using a custom QNetworkAccessManager.
Can cookies be used with ember-network requests? Thanks to this answer I know that they can be used with ember-data API requests, but I need to do a network request in an initializer and it doesn't appear the ember-data store can be accessed that early.
Background:
I'm wanting to persist shopping cart data to the backend for these reasons
The ember-cart addon has a smart way of persisting the cart by jsonifying and data model and dumping to localstore when it changes:
window.localStorage.setItem('cart', JSON.stringify(this.payload()));
then upon return visit parsing the json and pushing it into the store in an instance initializer:
...
payload = JSON.parse(payload);
...
cart.pushPayload(payload);
I'd like to do basically the same thing, but instead of getting the JSON from localstorage, get it from the API via the network.
the store ins't available in an initializer, but ember-network is. So hypothetically I think I can do this. The problem I'm running into is that the cookie isn't being passed.
I get around this with ember-data by using this:
xhrFields: {
withCredentials: true
}
in the application adapter, but I can't find any info about whether there's a similar setting for ember-network. I see the request to my API being made in the initializer, but the api doesn't return anything because the browser cookie isn't included.
The fetch API provides a credentials option..
This is also documented at the whatwg-fetch library used by ember-network.
So basically you can do
fetch("/foobar", { credentials:"include" }).then(...)
Is there any way to pass cookie to IWebBrowser's Navigate method.
As far as I can see neither passing Cookie header in headers nor InternetSetCookie/InternetSetCookieEx works with IE11.
The only working method I found is to set cookie via put_cookie of IHTMLDocument2, but for that you have to load page first.
Is there any way to pass cookie to first call of Navigate?
You could try IESetProtectedModeCookie if you are interacting with low-integrity browser controls. This still has limitations as noted in this cookie FAQ:
IE10+ on Windows 8+ introduced Enhanced Protected Mode which uses
AppContainers (rather than Integrity Levels) for isolation. EPM does
not offer an API for interacting with cookies;
IESetProtectedModeCookie will not set the cookie inside an
AppContainer.
Creating AppContainers is not documented so I assume your process is not running in a AppContainer?
This newsgroup thread confirms that you cannot set a cookie in the headers:
In case anybody is interested, I went through Microsoft support to
find out more about this. Their answer: what I want to do is not
supported. The 'headers' argument to Navigate/Navigate2 CANNOT be
used to set cookies.
I'm guessing that refreshing the page after put_cookie is unacceptable?
I am working on a project which is using embedded Jetty (unfortunately I just "inherited" the server side of the project and am not very familiar with the use of Jetty and its configuration).
An odd case just popped up - I'll do my best to describe:
A web-based UI (using AngularJS, from a different domain, so CORS is used) sends a POST request to change the state of something on the server. This worked at some point in the past (it was last used probably a month or so ago).
Yesterday this stopped working. Inspecting the REST calls, I saw that an OPTIONS request is first being made. The content type of the POST is application/json, so based on what I have read, this is correct. I am not sure why it was previously not sent - it is possible that the company had its version of Chrome updated recently, and the old version did not send preflight requests, but that's just speculation. In any case, here's what I think is the relevant code in my application for configuring Jetty for CORS:
FilterHolder holder = new FilterHolder(new CrossOriginFilter());
holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
appHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST));
Everything works fine for POST requests. I can verify this by starting Chrome with the --disable-web-security flag. No OPTIONS request is sent, and the POST works as it should.
My thinking is that since it works for the POST, it's not an authorization or security issue - it's just that Jetty is not configured properly to handle the preflight request (it just returns 401).
I can't find much documentation for embedded Jetty, and which of the CrossOriginFilter constants to use as property keys in the calls to setInitParameter (and furthermore, since the 2nd argument to that method call is a String, I really have no idea how to format the values).
What parameters should I be setting on CrossOriginFilter to property handle OPTIONS requests? And if I have said anything erroneous above or made any false assumptions, please correct me! I've got very limited experience with this.
Documentation for CrossOriginFilter:
http://www.eclipse.org/jetty/documentation/current/cross-origin-filter.html
Javadoc for CrossOriginFilter:
http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/servlets/CrossOriginFilter.html
Actual Source Code: (sometimes this helps people understand too):
https://github.com/eclipse/jetty.project/blob/jetty-9.2.3.v20140905/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
In short, you'll likely want to add OPTIONS to the allowed methods.
(Just like the javadoc says)
FilterHolder holder = new FilterHolder(new CrossOriginFilter());
holder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,HEAD,OPTIONS");
appHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST));
Now, to address another bug you have ...
This does nothing ...
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER,
"true");
That is not an init parameter key. (In fact that is a header name constant for the Access-Control-Allow-Credentials) if you want to allow credentials, then do as the javadoc says.
holder.setInitParameter(CrossOriginFilter.ALLOW_CREDENTIALS_PARAM, "true");
I solved this issue by using the following configuration for the FilterHolder:
FilterHolder cors = new FilterHolder(CrossOriginFilter.class);
cors.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
cors.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
cors.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "OPTIONS,GET,POST,HEAD");
cors.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin,Cache-Control");
cors.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false");
Chrome sends a "Cache-Control" header, if you do not allow this header with your CORS filter, then the OPTIONS request will not be responded to with the correct headers. Most examples of the CrossOriginFilter online do not include this header.
You can optionally set CHAIN_PREFLIGHT_PARAM to false (default is true). If you set it to false, the filter will respond to the request without sending the request to the Servlet. If you would like to handle the OPTIONS request yourself, you do not need to set this param.
Update: I tried your code exactly but I added the filter on the context handler, not on the app. It works this way.
FilterHolder holder = new FilterHolder(new CrossOriginFilter());
holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://localhost:8100");
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
contextHandler.addFilter(holder, "/*", EnumSet.of(DispatcherType.REQUEST));
I’ve got a Web API that I’ve added [Authorize] attributes to, which means that the unit tests I had previously now fail due to them being unauthorised. Here’s a sample of a basic test along with an initialiser method:
[TestInitialize]
public void CreateServer() {
var config = new HttpConfiguration();
WebApiConfig.Configure(config); // Create the routes
var server = new HttpServer(config);
this.client = new HttpClient(server);
}
[TestMethod]
public void MyThings_GET_Returns_All_MyThings() {
var response = this.client.GetAsync("http://localhost/api/1.0/mythings").Result;
var mythings = response.Content.ReadAsAsync<IEnumerable<MyThing>>().Result;
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
Assert.AreEqual(4, mythings.Count());
}
What I’m wondering is if there’s any way that I can either make my test log in so that it passes the authorization filter, or if there’s any way that I can pass as ASPXAUTH cookie along with the HttpClient request? Or another way of passing authorization that I haven’t thought of?
Nothing I’ve tried seems to work and I’m struggling to find any helpful info anywhere.
Thanks in advance.
What does your Authorize attribute do when it performs the authorization check? There are quite a few options that come to mind:
Have the authorize filter support multiple means of getting the "authorization token" that it requires (e.g. through an HTTP header or a querystring parameter, etc)
Right after your test initialization, clear out the filter from the configuration (so that it is not called at all). If you choose to go this route then you may wish to pop in a new filter that sets any authorization values that might be used further along the pipeline
If you are using dependency injection, move the "authorization check" into some sort of IAuthorize location that can be updated in your configuration
I would also recommend using RestSharp for making queries to your endpoints as it does a very good job of specifying headers, parameters, etc.
I decided that the way I was going about the problem was fundamentally wrong. Using cookie-based authorisation with Web API is just not a good idea, so I’ve decided to get rid of the authorize attributes and perform API-Key-based authentication instead. This makes it easier to test as I can just pass the correct API key in the request, but also means that I’m not relying on cookies for authorisation.