DataProtection - Share machine key between multiple applications - c#

Let's suppose that we have two APIs, one for UserManagement and one for Auth.
UserManagement API is responsible for initial invitation email (where i need a ResetPasswordToken because this is my current app flow) and Auth API is responsible for password recovery (where i need a ResetPasswordToken).
Of course, i need to specify the same machine key for both applications.
Let's also suppose that those two applications will be deployed behind a load balancer. 2 apps x 3 instances.
It is sufficient to have the same shared location for persisting keys (Redis or so) in both APIs?
services.AddDataProtection().PersistKeysToRedis(/* */);
I'm thinking that if it works for one app, multiple instances scenario, it will work for multiple apps, multiple instances scenario too.
P.S: I wasn't able to find anything about any locking mechanism (it seems that there is one just looking at how it behaves)
Another thing that i'm concerned of: race condition?!
Duc_Thuan_Nguy Jun 9, 2017
Out of curiosity, how does key rolling
handle concurrency? For example, let's say we have a web-farm with 2
machines and a shared network directory. There may be a race condition
in which both machines want to roll a new key at the same time. How is
this situation handled? Or the two machines can roll their own new
keys and as long as they can have access to both new keys, they can
unprotect data smoothly?
Comment reference: https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/implementation/key-management
Later edit: It looks like if you have multiple apps it isn't sufficient to specify that you want to persist keys in the same location. There is a concept of application discriminator (all apps being isolated).
You will need something like the following:
services.AddDataProtection(configure => {
configure.ApplicationDiscriminator = "App.X";
}).PersistKeysToRedis(/* */);
Locking and race condition questions are still valid.

No, it's not sufficient. ASP.NET Core's data protection isolates applications by default based on file paths, or IIS hosting information, so multiple apps can share a single keyring, but still not be able to read each other's data.
As the docs state
By default, the Data Protection system isolates apps from one another,
even if they're sharing the same physical key repository. This
prevents the apps from understanding each other's protected payloads.
To share protected payloads between two apps, use SetApplicationName
with the same value for each app
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetApplicationName("shared app name");
}

A quick update on this one: it seems like it's possible to eliminate race conditions by using the DisableAutomaticKeyGeneration method on all of your apps except the "main" one.
i.e. it will be
services.AddDataProtection()
.SetApplicationName("shared app name");
for the main one and
services.AddDataProtection()
.SetApplicationName("shared app name")
.DisableAutomaticKeyGeneration();
for all other apps

Related

Single Sign on for 2 .aspx sites on 2 different servers

I have 2 servers with 2 web sites that look exactly the same but contain different forms.
They are linked together in the menu of the sites and the users have no idea that it is actually 2 different servers.
This strange situation is because my company has split all new development off from the old development (by giving me a new server), but still needs access to some of the old forms.
Both use the same LDAP lookup to log in through AD.
the problem is, users must sign into both individually. so they log into one, then immediately log into the second. as you can guess, this is a huge complaint.
I would like to know how to make it so no matter which server they log into, the other will allow them to access its forms.
Both sites are .NET, both servers are using IIS.
Thank you.
To complete this question for anyone else looking, here is how I solved this issue;
I added DNS reverse lookup urls that made them look like they had the same domain, changed all the linking urls to the new ones and used the auth cookie for that domain.
I also had to turn off IIS encryption and authentications as the two servers did not share this. The cookie does not send plain text so I assume there is still AD encryption.

ASP.NET Single Sign On

We have two servers that run on the same machine under the same domain.
Both written in ASP.NET and uses the Identity framework.
I need to implement Single Sign-On (and single sign out) between them.
Actual sign-in is done in AJAX (I POST the username and password, the server authenticate the user and sets the session, then sends the redirect data URL to the client).
I found overwhelming amount of information about OWIN, the Identity framework, Claims, etc.
I found tutorials explaining how to create projects using just about any modal dialog and any Wizard there is in Visual Studio, which I tried to understand but really is useless to me, as I already have authentication system up and running.
I even found some demos claiming to implement SSO in all kinds of ways, and some Stackoverflow questions that said to simply put this and that values in the web.config and you're done, which seemed strange to me and I figured out I'm missing some basic understanding of how it works.
Still, I can't understand how SSO works in ASP.NET Identity.
Can someone please explain it to me in a simple manner, or refer me to some kind of such explanation?
Again: I have two authentication systems up and running. What code and/or configuration changes I need to make to get Single Sign-On working?
First, if you want them to share authentication, they need to be working on the same user store. In other words, you should factor out the Identity initialization code (ApplicationUser, ApplicationDbContext, ApplicationUserManager, and ApplicationSignInManager) into a class library that both applications share. Trying to mantain and share two separate databases with user data is going to be an impossible and insurmountable task.
Then, you need only ensure that both applications utilize the same machine key. The auth cookie is encrypted, and since the encryption is based on the machine key, both applications need to use the same key to encrypt/decrypt that cookie.
Since you've already stated that they will both be hosted on the same domain, that's all there is to it.

Where to put Web API endpoints (urls) in an MVC 5 application?

I'm helping create an MVC 5 web application. Its models are being provided via a Web API. Currently, the endpoints for the Web API are hard-coded into our controllers:
public HomeController() {
string baseUrl = "http://webApi.example/api/";
string endpoint1 = "endpoint1/{0}";
}
Obviously this is not the best approach. However, I'm not entirely sure where exactly we should put them. One of the challenges is the different environments the application will have to 'pass' through on its way to Production. For example, it must work 'as is' (with minimal configuration) in a development environment, QA, and ultimately production.
We've considered a few approaches, such as using the Web.config file. But that means we'd have to edit it in each and every environment ... and what if there's 30 development environments? Or 300? We've also considered reading things from the Windows Registry, under a special Key. This could be easily ported to all environments and supplied a 'generic' solution.
However, reading from the registry seems like bad idea (with no proof to tell me that it is or isn't).
So, what architect, strategy, or method could be used to create a valid configuration solution?
I've been using a Web.config for development, beta and production for years.
You certainly could store the setting in the registry, although a Web.config would be easier (editing the registry seems like more of a hassle). The one benefit to using the registry is in the event of sensitive information (e.g. service account password). This would allow the infrastructure team or server administrators to keep the password (registry key value) secret while letting developers deploy Web.config changes freely. In your case it's just a simple URL so who cares?
Either way you're going to be storing the same number of values (either you have 30 different Web.config files or you have 30 different registry entries). However, if you get to the point of having 30 different environments you're probably not going to be hand rolling these configuration entries. You're probably at the scale of having continuous integration and deployments actually powered by software where the values would be dynamic based upon the deployment settings.

Consistent ApplicationData path between WinForms Apps and Windows Service contexts in C#

I use the following code to build a desired path for an XML file:
System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
When executed from a Windows Forms application, it returns:
C:\Users\MyUsername\AppData\Roaming\...\Database.xml
When executed from within a Windows Service, it returns:
C:\Windows\system32\config\systemprofile\AppData\Roaming\...\Database.xml
I am now resorting to having a custom installer action persist the path in a registry key since the custom action will have a desktop context. If there is a better approach, please let me know.
What I am really interested in finding out is why the behavior is different in the first place. The Windows Service in question is set up to use the LocalSystem account in case that matters.
Only you know what the specific requirements are for this folder, but if it's to share data between multiple users, ApplicationData is the wrong choice:
The directory that serves as a common repository for application-specific data for the current roaming user.
A roaming user works on more than one computer on a network. A roaming user's profile is kept on a server on the network and is loaded onto a system when the user logs on
See the SpecialFolder enumeration and pick an appropriate value that fits your requirements - one that doesn't depend on a specific user. Most of these start with Common.
I suggest that you should check and make sure that two apps are running by the same user.
I tested your code in both winform app and webservice app, but their values are the same, so I can't find your real problem.
good luck!

best practice for DAL and configuration on Multi-Tenant isolated DB

My company holds a dozen websites and isolated DBs (identical schemas).
every customer has its own website (different app pool) and DB.
every website has its own configuration, several connection strings, but they all have same schema for configuration.
cust1.domain.com
cust2.domain.com
cust3.domain.com
We would like to merge all websites to one (single app pool) and stay with isolated DBs for security and large amount of data reasons.
what is the best practice for designing a DAL and configuration of it?
what are the implications of it, if large amount of tenant will be on the same time? does one application pool can manage this situation or it can be managed somehow?
BTW, we are using asp-membership for users authentication.
Thanks in advance,
Eddie
Use Application_PostAuthenticate event in global.asax to load the correct database and then close the connection in Application_EndRequest
One option is to use the profile in membership and store a piece of information that will allow you to determine which of the actual db's they should be connecting to. Downside is that you will need to store this piece of information for the duration of the users session so either a cookie or session variable is likley to be needed.
The implications of one site vs many depends a lot on your environment and application, do you currently have the multiple sites on a single box or do you have a web farm? do you know the number of concurrent users for each site, the amount of traffic? Performance monitor can help you here to see how busy each site is but you may need more invasive logging to determine metrics such as concurrent users. I found this server fault question around IIS 7 performance which may be of help
You can try 'Shared DataBase With Different Schema' from multi tenant data architecture . In your DAL you can choose specific schema which perticular to current user. Simple and secure in this way
Continue reading http://msdn.microsoft.com/en-us/library/aa479086.aspx

Categories