ASP.Net MVC Single-Sign On - asp.net-mvc

We're in a period of moving all our applications to sub-domains of the same primary domain.
Once this is done we aim to move our entire set up to a Single Sign-On system. Currently, we use Forms authentication and set a cookie containing an encrypted token when the user is successfully logged in.
When it comes to setting this up for SSO - is it simply a matter of changing the domain to which the session cookie(s) are set? Or are there other matters that need addressing for this to work.

Set the Machine key in the system.web section of your we.config's to the same value, get that from your IIS config:
<machineKey validationKey="<from IIS>" decryptionKey="<from IIS>"
validation="SHA1" decryption="3DES" />
Then all the sites will see the cookie as valid. The domain names in your section should be subdomains, I think. Well, it works when they are subdomains, don't know what it will do if the actual domain names are different.

Related

How is a Cookie validated internally by ASP.NET MVC using CookieAuthenticationMiddleware

I'm trying to figure out how ASP.NET internally validates that a cookie will allow the user to access the application.
CookieAuthenticationMiddleware will set .AspNet.Cookies with an encrypted value. After .NET successfully decrypts the cookie on a request, what validation occurs then?
Developing locally with IISExpress if I have an application (#1) that sets an authentication Cookie after the user logs in, and I create a complete new application (#2) also running on localhost, that is also using CookieAuthentication. When I access #2 it will read the cookie from #1 and allows the user to access the application as well.
I'm trying to understand what the limits are for cookie authentication.
There's not really any "validation" per se. The cookie's encrypted key is used to reference the user that should be "logged in". It works in a very similar way to sessions, where the session cookie holds an encrypted session id that the server can use to look up and restore the session via.
The encryption/decryption is based on the machine key, which either may be explicitly set in the Web.config or generated automatically by ASP.NET. Only applications that share the same machine key may decrypt the cookie, which is why it's so important to protect your machine key.
Anyways, there's two factors involved here. First, cookies are domain bound: only the domain or subdomains of the domain the cookie is set on will be given the cookie. This is handled by the client (i.e. browser). Your two applications currently are able to both see the cookie because they're both running on localhost. However, if you were to deploy one at foo.com and the other at bar.com, then they would no longer be able to see each other's cookies.
Second, the machine key is typically by server (unless you explicitly set it in the Web.config per app). As a result, sites running on the same machine can usually decrypt each other's cookies (assuming they see them in the first place, which again, is based on their domain).
It's not clear whether you're happy or not about this arrangement. If your goal is to segregate the two sites running locally, such that they don't share cookies, you have a couple of options.
You can explicitly set a different machine key for each site in their respective Web.config files. They'll still receive any cookies set by the other site, but they'll no longer be able to decrypt them, which basically results in them being ignored.
You can customize the auth cookie name. Instead of using the default cookie name you can make one .Site1.Auth and the other .Site2.Auth. Then, even though either site will also receive the cookie for the other site, it will simply ignore it, because it's not the auth cookie for it.
If, however, you're intending to rely on this behavior in production as well (i.e. you actually want logging into one site to log you into the other as well), then you'll need to explicitly set the machine key to the same value in both site's Web.config files. Additionally, you'll need to deploy them on the same domain, or at least subdomains of that domain. In the case of subdomains, you'll need to set the cookie domain to be the wildcard domain .mydomain.com for both. Then, you could have one at foo.mydomain.com and another at bar.mydomain.com, and they'd both see the cookie because it was set on .mydomain.com. If you leave it the default, set on the actual domain of the site, then bar.mydomain.com could not see a cookie set by foo.mydomain.com because that cookie would be explicitly set only for foo.mydomain.com.
The primary validations are encryption and expiration. If apps share an encryption context (e.g. machine key) then they can share auth cookies (providing other client side sharing rules like domains and paths are satisfied). So yes it's expected that two apps using IIS Express localhost on the same machine would share cookies by default.
The expiration is also embedded in the encrypted value so the client can't tamper with it.

Authenticate all Subdomains in Multitenant Application

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.

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.

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