How do I keep the FedAuth Cookie from ClaimsPrincipal from being shared between two websites that share a common domain? - cross-domain

I have two websites:
global.domain.com and global.domain.com/site1
/site one is an Application added to IIS under global.domain.com's site.
users will sign into global.domain.com, and then click on a link to global.domain.com/site1 to get there. Since I'm using matching machineKeys, and info in this article:
http://msdn.microsoft.com/en-us/library/eb0zx8fc.aspx
I am setting a Forms Auth cookie, and that's allowing a single user to be "authenticated" between sites across the same domain.
I'm also using ClaimsPrincipal in each site to handle assignment of roles via the new claims in .NET 4.5.
But when the user is either clicking on, or typing in the site for /site1, site1 one is getting the claims for the global site, and I do NOT want that to happen.
If I have a direct link to /site1 from the global site, I can use a controller action to redirect the user after calling:
FederatedAuthentication.SessionAuthenticationModule.SignOut();
and that clears the FedAuth cookie.
But if the user just adds /site1 to the back of the global site's URL and hits go, then the claims from Global carry to the Claims for /site1.
Each site should have its own claims...
I've tried removing the FedAuth cookie in my PostAuthenticate handler in Global.asax:
protected void Application_PostAuthenticateRequest()
{
if (HttpContext.Current.Request.UrlReferrer == null)
{
FederatedAuthentication.SessionAuthenticationModule.SignOut();
HttpContext.Current.Request.Cookies.Remove("FedAuth");
return;
}
}
but that doesn't seem to do the trick, b/c if I put a break on the first line of Application_PostAuthenticateRequest and look at the ClaimsPrincipal.Current.Identities.First().Claims collection, all the claims are there from global.
So even if I call SessionAuthenticationModule.SignOut(); and delete FedAuth cookie, I still have to find a way to remove the Claims from the ClaimsPrincipal.Current, and that seems a little "hackish".
Does anyone know where and or when ClaimsPrincipal.Current gets assigned? Since it has my claims from the global site when accessing /site1 before hitting my handler in Global.asax, there must be somewhere else in the pipeline that's populating the ClaimsPrincipal.Current's claims...
any ideas?

to prevent a FedAuth cookie from working across applications in the same domain, configure a cookie handler with a unique path for each application.
Do your applications have a cookie handler path set to "/" ? If yes, then this is allowing the FedAuth cookie to be shared across the applications.
Try setting the cookie handler path to something unique... such
<cookieHandler path="/myapplicationpath/" />
or - leaving path attribute out completely should accomplish the same thing.

Related

custom domain name per customer single page application

I want to give my customer the ability to create their own todos list app/web.
So, I thought they could register to my application, for instance:
http://mytodos-app.com/signup and provide all preferences such as theme, title, name...
Now i could use the url/router ability to get some unique identifier from the url and use the same app, but fetch data for each customer.
i.e: http://mytodos-app.com/todos/:someuniqeid
1) is it sounds ok? or are there better strategies for this scenario?
2) if it's ok, If I want to give them the ability to configure their own domain (like in shopify you get some dynamic domain yourname.shopify.com).
So, what is the most popular/professional way to do it? I want it to be easy to the customer. any suggestions?
Other than the "cool factor", there is no benefit to using actual customized sub-domains.
You can synthesize the behavior by:
In DNS, set up a wildcard CNAME entry for *.DOMAIN.com to point to www.DOMAIN.com, be sure to buy a matching wildcard ssl/tls certificate.
Configure the web server to respond to all hostnames.
After user registration. SANITIZE the username(or whatever identifier) value.
Set an authorization cookie with the domain=DOMAIN.com option to force it not to
be a host cookie.
Redirect to username.DOMAIN.com. Same server different name.
Check the cookie in the route to serve the correct pages. Just like
you would with any login.
If there is no cookie, use the host information to populate the
username portion of the login page, or display public todos?
Make sure any Javascript scripts hosted on the site and all internal links are loaded by relative addressing.
The technique is much safer than actually creating real subdomains.

Simpler solution against CSRF?

I've been thinking about Same Origin Policy and CSRF, and couldn't answer myself why web browser developers don't use a simpler solution.
Instead of disallowing cross domain scripts, why can't they allow any access to any site, but with an empty cookie jar? (or rather, a cookie jar that contains only the cookies of the current domain)
Same thing about any tag (img, script, etc.)
If any access is with no cookies, what CSRF can be done?
Regarding a cookie jar w/ only the cookies of the current domain: the cookies of the current domain may contain session information for example. This information could then be sent over the wire and result in session hijacking (for example).
Even if the scripts did not have cookie information, there could be other sensitive information on a website, perhaps visible through the DOM. This information could then be uploaded cross domain.
As an side, I don't think the same origin policy actually does anything to stop malicious hackers. As you said img's and scripts can make requests out. I can run a server that returns a 404, but keeps a log of the GET requests (for example: maliciouswebsitehere.com/fake404.html?bankaccountnumber=34398439843983&otherinformation=blah)

Authentication across multiple domains

I want to have an SSO for the following sites:
abc.com
def.com
I read this article which has a very basic example on how to setup an SSO with master/slave domain setup. While it was a very good read it leaves some questions unanswered.
abc.com will be the master site that issues the auth cookie.
Say the user is not logged in on any site. If the site is abc.com, all i have to do is check for the auth cookie, no problem. If the user is on def.com, the example in the article redirects to abc.com and returns the cookie content (if any) as a query parameter in yet another redirect. If the cookie has content the cookie will be stored on def.com.
Issues:
Every page reload on def.com triggers 2 redirects if local cookie doesn't exist.
When user logs out, both master and slave cookies have to be deleted and also propagate to any other slave sites.
When the user logs in, I must make sure a cookie is set both on master and slave sites.
I am especially worried about point 1. Is there a way to get around this?
I thought of having the authentication all in ajax, but then i would need a page reload if an auth cookie is returned from abc.com to def.com. Not a very pleasing solution.
Does anyone have a better architecture altogether?
EDIT
Writing this down helped me out to at least to some extent solve the problem. If cookies are set for master + all slave sites at login, point 1 is no longer an issue.
The question is still open for anyone that want's to improve the solution.

What factors influence IE in determining whether or not to send a cross-domain cookie?

Working on troubleshooting an interface consumed by 3rd parties. The quick overview:
3rd party sends the user out our site example.com/login to let the user authenticate with us
After signin we redirect the user back to thirdparty.com
thirdparty.com consumes a dynamic JS file on our site used to return information about the logged in user example.com/dynamicJs.js
Since this request is made against example.com it should include the cookies dropped during login (they are required for it to serve its purpose)
for IE, they are no longer being included in the request
In researching:
the cookies themselves don't appear to have changed, and manually navigating IE to the URL of dynamicJS.js results in the necessary cookies being transmitted.
example.com has P3P policies in place and is not generating any visible warnings/errors with IE
other browsers include the cookies
So, what other variables could be influencing IE and resulting in it omitting the example.com cookies when loading example.com/dynamicJS.js?
After much research we identified the root of the issue was within IIS's Custom HTTP Response Headers.
Previously we had configured the site to return a P3P header, but in diagnosing this issue we found that somehow the header was now being returned as 3P. Returning the key to P3P resolved out issue.
In researching the actual cause of this change we found that the bad header originated in the web.config, within the <httpProtocol><customHeaders> element -- however it appeared to have been placed there some time ago and remained dormant until the AppPool was stopped/restarted for maintenance.

JSF - Forcing use of JSESSIONID in url for iFrame without 3rd party cookie support

HI all! I am working on a JAVA/JSF app that runs within an iFrame. The client authenticates Outside of the iFrame, then redirects back to a page that contains the application inside of an iFrame. If the client has 3rd party cookies disabled, the iFrame will not be able to access the cookie, and it will never see the jsessionid.
What I would like to do is test for the cookie in the app, and if not found, redirect using JS to the current page, with ;jsessionid appended to the end. I tried that with
;jsessionid=#{session.getId()}
Which looked OK...but would never maintain the current session. I then added an
<h:form><h:commandButton/></h:form>
to the page, turned off cookies, viewed the page in a browser, and saw that the jsessionid listed on the form was different than the one provided by session.getId().
My question is this......how can I get the correct jsessionid, the one that would be part of the form?
Thanks! Mason
--Update--
I should mention that this is on the same domain, webserver, and application. an and the #{session.getId()} on the same page will return a different jsessionid at the same time.
Sessions are by default domain- and context bound. Your issue indicates that the page which the iframe is serving runs at a different domain and/or context.
If the page in the iframe runs at a different domain, then you'll have to write a "local" servlet which acts as a proxy with help of java.net.URLConnection or Apache HttpClient and let the iframe link to that instead.
If the page in the iframe runs at same domain but at a different context (and runs at same webserver), then you need to configure the server to share the same session among all running webapps. How to do that exactly depends on the server in question. If it's Tomcat or a clone/fork, then check the emptySessionPath attribute of the HTTP connector.

Resources