Authenticate all Subdomains in Multitenant Application - asp.net-mvc

I have built a Multitenant SAAS application. In this application the User can pick his preferred subdomain name during signup. When user logins to the main application i.e. app.example.com, I validate his credentials and then redirect him to his preferred domain i.e. client1.example.com
I am using Forms Authentication and trying to authenticate the user over the domain "example.com" by making following changes in the web.config.
<forms loginUrl="~/Login/Home/AuthenticateLogin" timeout="2880" protection="All" domain=".domain.com"/>
My understanding is that once authenticated over "example.com" user will be able to access any subdomain of (domain.com). But it seems this does not happen as expected. After successful login to app.example.com when I redirect him to client1.example.com it again shows the login page.
What am I missing here?

You need to configure the same machineKeyfor all applications that share the authentication cookie. See Generate a Machine Key for a Web Farm (IIS 7).
Also verify that the cookie is set when you log in, and that it flows to all the applications.

Okay, So after trying for so long I got to know what the real problem was.
Actually even after allowing subdomains to share authentication cookie it did not work because the SessionId was not being shared between the subdomains. My Application had outproc Session Configuration (Sql Server). To share SessionId between subdomains I had to make following entry in my web.config :
<httpCookies domain=".domain.com"/>
After this it worked like a charm.
Hope this helps someone in need.

Related

Why "requireSSL='true'" was throwing IIS error

I am working on MVC framework in ASP.NET where, I was trying to access the application but I was not able to go past the login screen, after which it kept throwing the not found IIS error. After workaround i found that i had this line : httpCookies httpOnlyCookies="true" requireSSL="true" in my web.config file which was stopping the access. Can anyone help me understand the problem and concept here?
Thanks already.
I was able to access the site after removing the requireSSL part only.
Web-config
httpCookies httpOnlyCookies="true" requireSSL="true"
Global.asax's Application Start :
if (ServicePointManager.SecurityProtocol.HasFlag(SecurityProtocolType.Tls12) == false)
{
ServicePointManager.SecurityProtocol =
ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls12;
}
I think the part of code in global.asax's Application Start might be causing the problem, but I'm not sure about it.
Websites use cookies to store information between page requests or browsing sessions.
The callback from an external provider to your site contains security tokens(httpCookies) that allow access to your site and contain user information.
If someone manage to steal other's authentication cookie for a website, he could carry out all the actions that they are capable of.
Transmitting this information over HTTPS to prevent interception while this information travels over the Internet is important
You can stop script access to all cookies in your site by adding a simple flag: HttpOnly. You can set
this flag in the web.config, as follows:
<httpCookies domain="" httpOnlyCookies="true" requireSSL="false" />
So If you write requireSSL="true" in your Web.config It Enforcing the external provider to make their callbacks to your site using HTTPS only.
#Vishesh Pandita In your case you are trying to access site using HTTP only. So faced "HTTP Error 403 - 403.4 Forbidden: SSL required" error.It means the page you are trying to access is secured with Secure Sockets Layer (SSL).
Solution:
To view the page, you must enable SSL (Secure Sockets Layer) by typing "https://" instead of "http://" at the beginning of the address you are attempting to reach. The "s" in "https" specifies a secure site.
Migration for HTTP to HTTPs
source : Professional ASP.NET MVC 5

Using ASP.Net Identity on multiple web applications

I've got several applications hosted on the same IIS (different context roots), that are all protected using the Microsoft.ASPNet.Identity 2.1 NuGet packages. At the moment however, when I log in to one of the applications, the next visit to any of the other applications prompts me to log in again. I can't be logged in to more than just one of the applications at once.
I'm guessing that they are all using the same cookie to store the login token, so when you log in on one app, it resets the cookie which becomes invalid for requests to the other applications.
What are my options for resolving this? I don't mind having to log in to each app individually, so can each app be configured to use a different cookie?
Alternatively, each app does in fact share the same User table in the DB, so it might be possible to configure it so that when you log in to one of the applications, the others also become logged in.
Have a different cookie name for each app:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieName = "CookieNameHere",
});
As shown on this page http://tech.trailmax.info/2014/07/rename-authentication-cookie-name-of-asp-net-identity/
Yes, this is because on 'localhost' you are sharing the same cookie.
This will not happen on production, because cookies are domain only. (unless, of course, all applications are deployed to same domain).
This is kinda annoying on localhost but easy to solve. Just change the name of the cookie for each application.
This varies from identity version to version but something like this is what you are looking for :
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieName = "MyApp1", // <-- add this, with different names for each app
// ...
});
normally found on Startup.Auth.cs or Startup.cs file.
As of using the same cookie on all applications (if they share subdomain.domain) you need to get MachineKey (validationKey, and decryptionKey) AND same cookie name on all your applications.
something like this on web.config:
<machineKey
validationKey="..." <-- some valid validation key
decryptionKey="..." <-- some valid decryption key
validation="SHA1"
decryption="AES"/>
I think Single Sign-On could be your solution. Search for it on Google.
For your start up, you can refer couple of links below:
Single Sign-On Asp.Net
Claim base Single Sign-on for Web and Azure
Single Sign-on for existing MVC App
Hope this is what you are looking for and will resolve your problem.

Membership can't validate user after providing machineKey

I have a web site with two endpoints, let's say www.mydomain.com and mydomain.com.
I need my user stay loged in when he jumps from one domain to another.
For this task I could force my users to login on one of domain (let's call it the main) and if somebody visits another - just redirect him to the main domain.
But I have read that I can use Forms Authentication Across Applications and share the same authentication ticket accross multiple domains.
So I decided to give a try to this approach, but it doesn't work for me... the main question why?
What I did:
I generated new machineKey from this service.
Added it in my web.config.
After this step my old membership provider stoped working correctly. It doesn't validate users with right passwords.
I suppose it's because all passwords in my current database should be encrypted by values from machineKey section.
Could anybody point me at what I am doing wrong and is it possible to make shared authentication with machineKeys and existing membership database that contains passwords in hashed format?
I also experimented with addint protection="All" (I assume that it shouldn't work with hashed password because it forces its encryption by machineKeys) and domain="mydomain.com" attributes to my <forms/> section in web.config, but - no luck.

STS Authentication - MVC Site

I have two servers: STS and Web. On the STS server, I call:
FormsService.SignIn(model.UserName, false);
The next line, I check:
User.Identity.IsAuthenticated
This is set to TRUE. Then I redirect back to my Web server and in the controller I hit, I check:
User.Identity.IsAuthenticated
This is set to FALSE.
What could cause this?
UPDATE: I also just tried moving the STS web site to the Web server. I get the same error/issue
UPDATE: I forgot to mention that our DEV server works just fine. The configuration there is identical (except for the server name and cert thumbprints). The only thing different between these two servers is that one (DEV) is using a self-signed cert and is inside our firewall. The other (QA) is using an official (thawte) cert and is ourside our firewall. This cert's common name does not match the server name (so it can be shared in our farm). So when we access the site, we do so using https://[commonname].com/web as opposed to https://[servername]/web. I tried the latter approach (I get cert errors that there is a name mismatch) but still have the same result.
Also, I can access the STS site directly and login fine there.
ASP.NET authentication is based on cookie by default. Cookie lives inside web domain.
So if you have two servers installed like this:
http://www.web.com
http://www.sts.com
WEB server cannot read cookie set by STS
There are two possible solutions:
Implement both servers as sub-domains
Store authentication ticket in URL instead of cookie
For option 1
Move servers as follows:
http://www.web.yourdomain.com
http://www.sts.yourdomain.com
Update web.config to scope cookie to yourdomain.com:
<authentication mode="Forms">
<forms domain=".yourdomain.com"/>
</authentication>
For storing ticket in url check this article - http://www.codeproject.com/Articles/2796/Cookieless-ASP-NET-forms-authentication
Update: Seems that I did not get that STS stands for Security Token Service. My answer is not relevant. :(
While redirecting from your STS server you will have to redirect using the AutoPostform which will submit the token to the Relying party.
And when Relying party will receive the token it will create the cookie against that user.
So next time whnen you will check User.Identity.IsAuthenticated at Relying party it will return you True.
Go throung the following link to know more,
http://chris.59north.com/post/2013/03/27/Claims-based-identities-in-ASPNET-MVC-45-using-the-standard-ASPNET-providers.aspx
We had the same issue when moving the RP to a different server. It turns out that we needed to go into the application pool -> advanced settings -> Set 'Load User Profile' = true.
After that, everything worked as it should on the new server and User.Identity.IsAuthenticated was returning 'true' after it came back from the STS.

Forms authentication & subdomain

I'm trying to use forms authentication that will work for both my top level domain & sub domains.
for example, if I log in with this domain: mydomain.com and afterwards going to www.mydomain.com i want to have the ability to identify the user who logged on to mydomain.com (it's the same application).
i'm using the following in my web.config file:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" domain="mydomain.com" timeout="2880" />
</authentication>
This is an mvc project, and i'm getting the user id with the following API:
HttpContext.Current.User.Identity.Name
The creation of form authentication cookie is done by the following api after performing openid logon to the user:
FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
I can see that the authentication cookie is being sent to both domain but only the domain that the authentication was made against recognizes the user.
Am i doing something wrong?
Thanks,
Lior
Make sure you have the same machine keys setup for those two applications. If the authentication token is encrypted with the machine key of application 1 and application 2 has different key it won't be able to decrypt it.
This question isn't exactly the same as yours, but it looks like it's the solution your looking for.
You need to issue your ticket in the toplevel domain, in order to be recognized by subdomains. This is because of how cookies work:
If you set the cookie in domain.com it will be visible on sub.domain.com
However if you set it on sub.domain.com, it will not be visible on domain.com
This is a security issue because of cookies and you'll have to consider it, beyond the settings of the <form> element which have to do with validating/rejecting a authentication cookie, where you will need to have domain='domain.com', which you already do.
In addition to all this, if on the subdomain you have a different application, you will need to explicitly define the machine key to be the same. You can generate your self some keys here: http://aspnetresources.com/tools/machineKey

Resources