Bluemix generates a VCAP_ID cookie which is not secure at the moment (see below). Is there a way I can force it to be secure? Is there any reason for not making it secure?
Set-Cookie:VCAP_ID=[redacted]; Path=/; HttpOnly
vs.
Set-Cookie:VCAP_ID=[redacted]; Path=/; HttpOnly; Secure
No, this is set internally by Bluemix. We can take this back to the dev team to make the cookie secure though.
What is __VCAP_ID_ cookie
Here's what I found from section HTTP Sessions Not Persisted or Replicated of cloudfoundry document:
Cloud Foundry supports session affinity or sticky sessions for incoming HTTP requests to applications if a jsessionid cookie is used. If multiple instances of an application are running on Cloud Foundry, all requests from a given client will be routed to the same application instance. This allows application containers and frameworks to store session data specific to each user session.
And this sticky session is tracked via a cookie named __VCAP_ID_, see cloudfoundry/gorouter/proxy/proxy.go
Setup __VCAP_ID_ cookie
checkout cloudfoundry/gorouter/proxy/setupStickySession()
The configuration for setting this cookie is a private method which means it's decided internally within proxy. The only variable part are maxAge and Path which means it uses maxAge/Path of JSESSIONID cookie for __VCAP_ID_ cookie.
I'm curious why Secure is not part of this. Instead, it is decided when creating proxy in gorouter. I've create issue 99 to track this because it should be as secure as JSESSIONID.
Related
I have multiple front-end & back-end apps running on different subdomains of the same domain. On the main front-end app I want to build a thing to switch between subdomains but also keep the session.
I've tried to:
use express-session
do some tricks with the JWT authentication
localStorage is not going to work as it is persistent on only 1 URL
but still can't figure out:
Is it possible to have a session shared across multiple subdomains?
What is the best solution to have a shared session across multiple subdomains?
The technologies I use:
Front-end: React JS
Back-end: Node & Express JS
To share sessions across sub-domains, you need to configure two things.
You need the proper cookie settings for the session cookie so that the browser will send the same session cookie to both sub-domains. This involves setting the domain attribute on the cookie to the root domain. You can set this in the cookie options for the express-session configuration.
You need to make sure that the server for each sub-domain has access to the same session store. If it's actually the same server for each sub-domain, then that's easy. But, if it's a different server, then you will need a shared session store, using some type of shared database (redis, mongodb, etc...). There are session store implementations for many different databases.
Luckily we're working on same project these days with with Nextjs as frontend and nodejs express as backend API.
We use cookies to manage the session on sub domains.
But to maintain the session on sub domains we use middleware in nextjs which on every page check for the session using token and user id.
On login send token, userid as parameters in url based on which user data get from api and saved that subdomain.
On logout removing cookies and sending paramter to tell the main domain to remove the saved cookies which completely clean the session.
This is how we maintain the auth session on multiple domains.
Hope this will helps.
If you find other way better then this i would like to know.
My applications consists of 2 parts:
The web API, written in .NET Core
The web app, written in React and rendered using a nodejs express server
I am hosting these parts on azure, each on it's own sub domain so we have:
api.azurewebsites.net
app.azurewebsites.net
When the user logs in I set a cookie, to my understanding a cookie can be used accross sub domains. The cookie is set the following way:
Response.Cookies.Append("token", "token value", new CookieOptions
{
Expires = DateTimeOffset.Now.AddDays(7),
SameSite = SameSiteMode.None,
Domain = "azurewebsites.net"
});
But the cookie is not sent along with requests to either sub domain. How can this be?
If this is the wrong approach how do I authenticate with a SSR app and a rest api? When the app gets rendered in node it fetches data the exact same way as in the browser using isomorphic-fetch, the cookie is passed along with it.
All this works flawlessly on localhost, the problem starts when the app in on a different sub domain from the api.
UPDATE:
The cookie header looks like this:
Set-Cookie: token=<token>; expires=Sat, 22 Jun 2019 05:35:18 GMT; domain=azurewebsites.net; path=/; secure
On firefox it works different from chrome. On chrome i do the authentication api request, get the token get the cookie header and then the cookie does not get sent along any subsequent requests.
In firefox the cookie does get sent with subsequent requests, however upon refreshing the page the cookie is gone.
I found this ASP.NET Core Sharing Identity Cookie across azure web apps on default domain (*.azurewebsites.net)
Cross sub domain cookies are blocked for the azurewebsites.net domain for security reasons.
If an application issues an authenticated user a session and gives them a cookie that should only be valid for a certain subdomain (say, because there are other customers located on other subdomains but all the subdomains resolve to the same running application) then should the server verify this cookie's intended subdomain against the host header before setting the session at the beginning of a request?
e.g.
User successfully authenticates to client.example.com
Server creates a new session for them and adds a property to the session about the originating domain
{user: "fred#gmail.com", domain: "client.example.com"}
Server sends a Set-Cookie header in the response with the session id
Set-Cookie: secure-session-id=1234-5678; Secure
The browser won't send that cookie if the user navigates to otherclient.example.com due to the implicit same-domain behavior of Set-Cookie
There's nothing stopping the user from constructing a curl command with that cookie but pointed at otherclient.example.com.
If the server doesn't validate that the host header of an incoming request matches the originating domain of the session for the provided session id in the cookie, then it's possible that a user with a valid account could masquerade as another customer (if the app bases any logic off of the subdomain instead of purely off of information gathered from the authentication). Prior to setting the user's session and continuing with the request I would expect the server to take the session id submitted, look up the session, see if the request host header matches the "originating domain" that was put on the stored session and if not then either return a 401 or redirect the user to the appropriate subdomain.
This seems like a generic enough scenario that I'd expect most server authentication frameworks to do this out of box unless you turn it off (ultimately it boils down to enforcing on the server side the same behavior that browsers are relied upon to do by default (not send session cookies for one subdomain to another subdomain). Are you aware of any that do this? Is there a better way of preventing this scenario? Am I misunderstanding anything?
Are you aware of any that do this?
ASP.NET has a different Application Domain per IIS application. Therefore, a session cookie from one application won't be valid on another. The only exception is if you've written a multi-tenant application that resides in the same Application Domain and you're not doing any validation on the received session cookie to ensure that the host matches the one where it was set.
PHP on the other hand will store all sessions in the session.save_path (e.g. /var/lib/php/session) and therefore a session cookie from one application would set session variables if used for another, which, as you've rightly pointed out is a security concern.
This can be remedied by overriding the session.save_path local value for each application or access host for the application.
Is there a better way of preventing this scenario?
As an additional security measure you could set the host when starting a session.
Session["host"] = HttpContext.Current.Request.ServerVariables["HTTP_HOST"];
Then validate this before any session values are used in the request. i.e. what you said in your question:
I would expect the server to take the session id submitted, look up
the session, see if the request host header matches the "originating
domain" that was put on the stored session and if not then either
return a 401 or redirect the user to the appropriate subdomain.
If these measures aren't being done then it would be an interesting attack vector in substituting a set of session variables from one application into another that reside on the same server. Of course, if the applications are the same (e.g. multi tenanted scenario) then there would be exploits such as leveraging admin access on one host to gain admin access on another. If not, then there still may be attack paths there depending on which variables are set and how they are used.
After taking a look at the HTTP State Management Mechanism Spec specifically 4.1.2.5 where it mentions:
The Secure attribute limits the scope of the cookie to "secure"
channels (where "secure" is defined by the user agent). When a
cookie has the Secure attribute, the user agent will include the
cookie in an HTTP request only if the request is transmitted over a
secure channel (typically HTTP over Transport Layer Security (TLS)
I was wondering if my setup has this set up correctly. I have a hapijs server and an nginx proxy server that it sits behind. The nginx server is configured for HTTPS (I can access it via https://..., anyway). Now there are ways to provide certs to the hapijs server to provide it TLS. My question is: is this necessary? The connection between the user's browser and my server is protected with TLS and then all that communication happens without sending anything over the wire so I would assume it would be okay.
I may be way off base here so maybe someone can point me in the right direction if I am.
The "secure" attribute of cookies is handled by the client (the web browser) and not by any proxy servers (at least that that I'm aware of!).
So you should be fine as long as the endpoint the browser connects to is secure.
This is a very common set up to only secure traffic at the end point - providing you are comfortable with the the security of the link between endpoint and final destination (e.g. same machine or internal network).
Of course an internal network traffic can be sniffed by someone onsite (e.g. an employee) so https all the way is best from a security point of view, but using http from endpoint to final destination should not prevent "secure" cookies being sent on from my experience.
If using external network as the first server (e.g. CDN) then it's strongly advisable to use https all the way to a secure endpoint, though again they will not be stopped.
I am using express-session module for maintain session. i have two app. i want to share cookies with this apps, parent app run in example.com , and child app run in child.example.com. i set httponly cookie using express-session it sets in the child app.i can verified that cookie in resource tab in chrome debugger.
Network tab:
When the first call to sub-domain:
it load like "http://www.child.example.com" cookie set in the request. while the url is redirect to server IP . cookie not available after that.
like http://13.25.230.2/index cookie not avaliable on that
When you send the Set-Cookie HTTP header, you can specify the domain it is for.
Set-Cookie: name=value; domain=example.com
The domain must be a suffix of the domain hosting the page.
i.e. foo.example.com, bar.baz.example.com and www.example.com can all share a cookie belonging to example.com.
A URL using an IP address has no hostname in it at all and cannot match that rule.
There is no way to share your cookie between example.com and 13.25.230.2. Give the site a hostname instead.
There is no way you can set cookie using setcookie header from one host to another. For example from example.com to foobar.com.
If you have to do it. Then do it by passing the cookie value to server side script for example foobar.com\set-my-cookie.php and use to to save the cookie.
Httponly cookies cannot be set or read from client side code.