How to use OAuth in a C# web api app when hosting multiple instances - oauth-2.0

I have a C# web API application, which is using OAuth and annotations such as:
[Authorize(Roles = "admin")]
I'm hosting it on AWS elastic beanstalk. It works fine when there is 1 instance running, but when I started to have multiple instances, I was getting unauthorised messages returned. Clearly the tokens are not valid across multiple machines.
Is there a way that I can add some configuration to the instances so that they accept tokens that have been generated on a different machine?

You can set the MachineKey in web.config which can be used to share tokens between multiple machines.
<machineKey decryption="AES" decryptionKey="..." validation="HMACSHA256" validationKey="..." />
The script to generate the machine key can be found here.

Related

Override MachineKey on Microsoft Azure App Services across multiple App Service Plan

I'm trying to set the Machine Key in Web.Config of ASP.Net MVC apps but it sounds like Azure automatically provision unique machine keys for each web app and override what's in my Web.Config.
The reason I want to do that is because I have an App Service witch is used as Authentication App. Thats where users will login. And I also have plenty others apps that will be using the Token provided by the first app. Doing this will Authenticate users at one unique place and users will be able to navigate through some modules in a portal being authenticated only once. It works very well in localhost or hosted in IIS, but on Azure Hosted App Service it seems like Machine Key aren't read properly or something even if I reset the machine-key configuration section upon Application_Start.
I tried the solution described Here, but as #gorillapower said
Seems this isnt working for us. We are using .NET 4.6.1 and using OWIN startup with app.UseCookieAuthentication() and using a Redis cache session provider. I implemented the above, but the user keeps getting logged out after a slot swap. Any ideas?
It also seems that when you run an ASP.NET application on multiple instances of an App Service Plan (ASP) you do not need to worry about machineKeys as the App Service Platform will use the same one across all your instances and therefore will not need to make any changes to your application.
But in my case, our Apps are all in different App Service Plan. So this solution doesn't apply.
Any clues about this problem ?
Thanks
Generate machine Key and add into web.config file
It will work for Web Farm / load balancer either in IIS or Azure Web App service.
Note : It will only work if you are using IAppBuilder->UseCookieAuthentication-> CookieAuthenticationOptions
<system.web>
<authentication mode="None" />
<machineKey validation="HMACSHA256" decryption="AES" validationKey="D6883865C0490AFA4907A046E838DD2C7B13B636694B552630C13770701B944A" decryptionKey="2C3C48562E6FE018E71B69BDB27D06048A573C094A962AA9A1547C3D874C63B0" />

MachineKey setting for AntiForgeryToken in ASP.NET MVC

I was deploying my asp MVC 5 web site in Azure Web Site. Everything was fine until I tried to manage my account (changging the password), it gave an error like this:
The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the configuration specifies explicit encryption and validation keys. AutoGenerate cannot be used in a cluster.
I was using Asp Identity, so all the code is built in. I have been searching the solution and found two possibilities:
1) It is because there are two #html.antiforgerytoken. One belongs to the MANAGE controller form, and the other belongs to the login partial view int he navigation bar. I tried to exclude the login partial view, but the error persisted, so I concluded that problem might not be it.
2) As the error says, maybe it is about MACHINE KEY. I tried to input setting to the web config. There are two popular ways to generate this machine key, fist is using ISS and the second is using third party. I wanted to use the ISS, but my ISS8 is not showing a modul to see the machine key which is weird that I could not find any solution for it. Then I tried the third party, and created something like this:
<machineKey validationKey="4359B782C08EF91E2AA6CA8AD46C0D63BF323E97ABAA06FBDA1535A1FA1CD2B7702B2BACDC937074ED65FC16D3ECA0F674BBAC8675910AF921D301CA22343AA1" decryptionKey="1A956B2A0405EC07AEBEFBA40DA7E61E2E17F001B868D7507EB3F3CD2AFF060E" validation="SHA1" decryption="AES" />
Then I redeployed my website but the error persisted. Can anyone please help me?

How to prevent "Swapping" of "Staged" Azure Websites from logging users out?

I have deployed a MVC3, Membership Services, .NET4, C#, Razor, EF4.1, SQL Azure Web application into Azure using Azure Websites(Standard).
I have been experimenting with the new "staging" feature where one can "swap" in an upgraded web application. Very good. What we would really like to do is to upgrade code without interfering with the end user ie Continuous integration of small fixes. However we have noticed that a "Swap" logs users out which is not ideal. I suspect this is to do with authentication cookies being lost after the "swap" so the session cannot authenticate resulting in the users being returned to the login page. Is there a way around this? The only thought I have had is to somehow persist the "essentials" in the database.
Thoughts appreciated.
Thanks in advance.
Since your "stage" application is on another instance, you will need to have a matching machineKey across the two applications. Add the following to your web.config, so that a machineKey is not auto generated.
<machineKey
validationKey="052851E2D519231BE84E455B4C4A9FBC0CAC53B8FE7BBA1917FC296ACE6F41832383347EAEC498F40978DDD3374E7A666AFD0ADC1084A9E48B1B40ADC918C9A6"
decryptionKey="7077D8F4C273E3FC5CE296F3B74897ACECF055F9BA01565372EE87B8746DE50F"
validation="SHA1"
decryption="AES" />
Replace the keys with your own. You can generate them through IIS or here. You can also change the encryption and decryption algorithms if you so choose.
More info on MSDN

Using .NET MVC/WebAPI, Is it possible to share an auth cookie between two projects of the same solution? If so, how?

My solution is structured like this:
Web Project (Default, ASP.NET MVC)
API Project (ASP.NET MVC using WebAPI controllers)
When deployed to a server, the web project will be the root and the api project will live in root\api.
I am authenticating users in the web app using FormsAuthentication.SetAuthCookie("foo",false); and so of course within a controller of the web project I have no problem reading the cookie back (HttpContext.User.Identity.Name).
I would like to be able to do the same in my API project when an ajax request is made from a page in the web project so that I can check that the user is authenticated before remitting a service.
Is this possible?
Update
I followed this MSDN article for creating authentication across applications, and I still can not read my auth cookie in the API context. I am wondering if it is because I am running in local host while the Forms node in the web configs expect a domain name:
<forms loginUrl="login.aspx"
name=".ASPXFORMSAUTH"
protection="All"
path="/"
domain="contoso.com"
timeout="30" />
I tried setting the domain to localhost:XXXX but that didn't work either. The machine keys in both applications match.

Method for Sharing Forms Authentication Login between MVC.net and Web API Sites on the Same Domain

I am going to have an ASP.net MVC web site (example.com) and a Web API site (api.example.com) running on the same domain. What is the best and most secure way to use Forms Authentication to allow a user to log in to the MVC site, and have that login accepted by the [Authorize] filter in the API site? Additionally, there is the possibility that both sites will be hosted on multiple servers (each of which might have its own subdomain), so a solution that would allow for a single sign on approach to work among all of the servers in the cluster would be preferred.
Take a look at this link http://www.codeproject.com/Articles/27576/Single-Sign-on-in-ASP-NET-and-Other-Platforms this covers the answer in detail.
You will need to ensure all machines and separate applications on the site share a common (but unique to production) machine key to allow the authentication cookies to be trusted by all the machines/applications.
If you are simply using virtual directories under the same sub domain then simply harmonising the web.conig Forms Auth settings and machine keys should get you up and running very quickly.
If you want this to work between a second level domain then you need to change the "Domain" setting on the Form's Auth cookie. See the article for details.

Resources