Best way to log users programmatically into a 3rd party website (when OAuth is unavailable)? - asp.net

I'm working on an asp.net website that needs to store user passwords for another website so that I can retrieve data periodically without requiring the user to keep logging in. I can't imagine how one-way hashes would work in this case since the user isn't going to be re-keying the password every time. I'm assuming I need to encrypt the passwords to store in a SQL Server database and decrypt them when needed. But that's where things get tough for me. The basic infrastructure is a C#/Asp.Net MVC3 website running on load-balanced Azure compute instances and storing data in SQL Azure. I'm not a crypto guy, and I don't want to make a rookie mistake. There seems to be a lot of information out there, but nothing seems clear to me. Even though the data I'm connecting to isn't sensitive, I want to treat my users' information with the same care I want my personal data treated. Any advice on how to proceed would be appreciated.
EDIT:
I certainly understand that storing passwords is not a best practice, but in some cases it is simply unavoidable. I have come across this project, but have not tried it yet: http://securentity.codeplex.com/. It uses a digital certificate on the web server.
Users of the 3rd party site are able to set their data as "public", in which case I wouldn't need to store their password. So I may give users the option of doing that instead.

You should have a look at OAuth and Single Sign-On.
In simple terms: Only an authentication token is sent between the different systems.
You (the site) should never have knowledge about the users passwords. At most you should know the hash of the passwords to your site.
Read the two topics above and you will know how to properly secure your and the "neighbour" site.
Edit
In Short:
The other site (site B) implements OAuth server processes. Your site (site A) implements OAuth client authentication. When requesting user information from site B you redirect the user to site B authentication to allow site A to read information from site B regarding the user. Site B creates a token that site A can use to access the information. This token can be time limited (or not).

Related

Retrieving all users and roles in a .NET Web Application through ADFS

We have a hosted .NET web application (Windows Server 2012 R2 environment) and we need to provide Single sign-on (SSO) to users from a corporate LAN environment. We have used ADFS to enable SSO and it is working as expected thus when a user hits our web application login page URL he is authenticated against ADFS and is automatically logged in to the application.
We have an additional requirement where we need to obtain a list of all users, their groups, email addresses some additional information periodically from their Active Directory so that this information can be bulk loaded into our web application however since ADFS is implemented we do not have direct access to the Active Directory.
Is it possible to connect to ADFS and obtain a list of all users, their email addresses etc. programmatically?
If the above is not possible then what is the recommended approach for this kind of a setup?
Thank you.
No, this is not possible. There is no such API because with SAML and WS-Federation, users can come from anywhere. This does not have to be AD, technically it's possible create a "Log in with Facebook" implementation.
What would you need the information for? The user's claims contain all information which you might need (user name, e-mail address, group memberships).
If you really need that information about all users in your application, perhaps ADFS is not the solution you are looking for.
As Alex mentioned above - the way it works, ADFS does not provide any way of importing data from the AD or other trust stores. It just gives you the information that are carried over with the token.
In case you need more information, you should extend the number of claims being issued by ADFS. You can then collect the information - when the user comes for the first time, use the data from the token and fill the profile. If it is returning user - update the information if necessary.
The other solution (but I wouldn't say it's recommended - rather a workaround) would be to implement custom solution for importing information from AD to your application. I'd say it's fair as long as you use your local AD for reading this data. In the moment you decide to extend the access to third party (e.g. partner company), which might be using different identity provider, which doesn't have to be backed by Active Directory any more - you find yourself in tough spot.

Granting Secure Access from one website to another

I'm really just looking to see how much folly is in the below suggestion from a security perspective.
I have two websites. One is an administration portal and the other is a members portal.
Within the administration portal administrators can retrieve a listing of members and I need to offer the ability for administrators to login to the member portal without having to enter the members login credentials.
Both are separate websites within IIS and for this discussion lets say they are on different servers.
Both websites access the same SQL Server database.
I was thinking that I could on the administrator clicking a "Login as Member" link create a random code string and save this to the database along with the member number.
I could then pass the code and member number to the member portal as query string parameters.
The member portal then read in these values and checks them in the database to verify that the code string exists and if so that it matches the member number also being passed. I could then login the member and set a flag in the database to set the code as being used and therefore invalid for future requests.
I'm thinking to bypass this a hacker would need to successfully guess the random code and pass that to the page alongside the corresponding member number for that code and for that combination to be marked as unused in the database.
This would seem to be unlikely given that only seconds will pass between the code being generated and the code being used.
If necessary I could always check the IP address of the request as users of the administration portal all share the same fixed IP address.
So do you think the above would stand up to scrutiny on a security review or will I need to go down the SSO route?
Your approach is very sound. I can confirm because I have implemented just such a solution for just such a reason. We analyzed the options and exposure. And after implementation, our application passed a PCI Complaince Audit.
Reasons:
SSL is Esential! protects against sniffers. Essential. Without Encryption, sniffers could detect your GUID and may have a window to use it)
As Tony pointed out, the GUID is effectively unguessable.
Guid Tokens expiring should expire within 24 hours.
Suggestions:
Checking against IP is good. But don't be fooled into a feeling of security from it. Anyone can fake IP's in headers. To be Secure against XSS and CSRF by using AntiForgery tokens.
The AntiForgery token is a cookie that populates your HTTPHeaders with __RequestVerificationToken which is almost as hard to guess as your GUID.
Consider using an established Authentication framework like .NET Identity 2 and multitenancy.
An established framework takes the burden of encrypting your passwords. MS Frameworks like Simple Membership and Identity integrate into modern ASP.NET frameworks and give you very strong base of functionality to lean on.
If you're using an old framework like classic ASP or .NET 2.0, the classic Membership Provider is more appropriate.
If you are creating new MVC 5 applications utilizing Entity Framework, I strongly suggest using Identity 2.1.
Consider Mult-Tenancy. While there is nothing wrong with your solution, if Admins and users shared Membership Provider, your solution would be cleaner. An admin could log into the main site and "get" the token from the DB. Then no exposure.
Assuming the use of HTTPS and adequate physical and IT security processes and procedures in place for the administrators, this method should be adequate. It is more secure than most financial website password resets, which typically only require a compromised email account and some personal information to reset the password. If you check the IP address range of the originating client request as well, a hacker would have had to already have access to your systems or network. Also, if you make the code a GUID, it would be (pragmatically speaking) impossible for someone to guess.
You could add a layer of checking for hack attempts by storing a record in the database each time this event occurs (or at least each it fails due to a bad key), and each time it occurs run a check to see if it is happening too often (like 100 times in the past hour, or something--the right number depends on how often you expect it to happen). If it's happening too often, then have it send an alert to IT personnel and revert so that the user has to enter their credentials manually.
Disclaimer: I am not a security expert by any means, so I'll gladly defer to anyone claiming such status. I'm weighing in here due to a lack of answers.

Creating a Forms Authentication cookie for a search engine crawler

Big picture: I have been asked to create a search engine for our company's intranet. Such a search engine will crawl pages supplied to it by XML files for each independent application on the intranet. Problem is, the entire intranet is using Forms Authentication, and so the crawler will have to have access to each application without actually having user credentials (e.g. username and password).
Each application within the intranet has its access controlled by a permission manager, which is essentially a wrapper on the default Role Manager ASP.NET comes with. Each application can define its own roles and assign people who have those roles.
Please note that there are potentially hundreds of applications.
The crawler has access to the permission manager's database, so it knows what all the roles are. Therefore my idea was to have the crawler create a cookie that identifies it as having all roles for each application.
The problem I'm running into is this: how do I create a forms authentication cookie which already has the roles assigned in it without creating a corresponding user (IPrincipal).
It is entirely possible that I've failed to completely understand how Forms Authentication works, and if so, please tell me what I can do differently.
This is probably not what you want to hear, but...
I would just have the crawler authenticate like anyone else.
Given that this is a crawler you control, why fight Forms Authentication? Seems logical to create a user with all required roles in each application (hopefully you have a central administration point for the hundreds of apps, else I would not want to be an administrator there ;-)
If you do anything that allows "just the crawler" special access (bypass user-based authentication based on... what? The crawler's user agent? A specific origin IP?), you create a security hole that a hacker can leverage to gain access to all of the intranet applications that have otherwise been diligently secured with user IDs, passwords and roles (in fact, the security hole is particularly wide because you propose granting access to EVERY role in the system).
It sounds like what you want is an appropriately encrypted System.Web.Security.FormsAuthenticationTicket (which then gets attached to HTTP requests as a cookie).
The encryption logic is located in System.Web.Security.FormsAuthentication.Encrypt(), which I think uses the MachineKey as the encryption key. Also have a look at the GetAuthCookie() logic (using Reflector).
You might have to write your own version of the encryption method, but what you want to do should be possible, provided you have a copy of the remote site's encryption keys. You don't need the user's passwords -- only the user name is encoded into the Ticket.
It seems to me that the problem is not yet well defined, (at least to me!).
Why do you need to crawl the pages and index them if there are fine grained permissions on them?! How do you show search results without violating the permissions? Why not index the back end by passing the pages altogether (I mean index the database records not the pages)....

SSO - Share single User table between several websites or somehow keep multiple User tables in sync?

I'm working on a single sign-on solution for two ASP.NET MVC3 websites. The sites are on separate subdomains. I'm using Forms Authentication and so far I everything is working well. When I sign into a.example.com I'm automatically signed in to b.example.com too. Nice.
Each application has its own database.
My question is this - if I want to keep certain user information in sync between the two sites (say the last activity date or some user preference) then should I have a User table in both databases and somehow keep them in sync or should only a.example.com's database have a User table and b.example.com somehow reads and writes to it?
Thanks for your advice.
Edit: Thanks to adam I'm leaning towards storing all user data in a separate database. I will pass the authenticated user's username and ID to each application in the authentication cookie. Can anybody offer any advice around maintaining referential integrity between the two databases?
Most SSO solutions I've seen have a central accounts portal where users can maintain settings, change email address etc.
Think Google:
google.com/reader
google.com/analytics
google.com/accounts
This represents a single user store, providing authentication to several sites. This has various benefits, such as a single place to store session hashes and other security details (for preventing things like man-in-the-middle attacks).
In a true SSO, an authentication request redirects to the central auth system (ie google.com/accounts), authenticates and then redirects to the service that requested authentication.
From your description, it sounds like you have separate authentication for each site/service, but the user db is shared.

Using Active Directory to authenticate users in a WWW facing website

I'm looking at starting a new web app which needs to be secure (if for no other reason than that we'll need PCI (Payment Card Industry) accreditation at some point).
From previous experience working with PCI (on a domain), the preferred method is to use integrated windows authentication which is then passed all the way through the app to the database using kerberos (so the NT user has permissions in the DB). This allows for better auditing as well as object-level permissions (ie an end user can't read the credit card table).
There are advantages in that even if someone compromises the webserver, they won't be able to glean any/much additional information from the database. Also, the webserver isn't storing any database credentials (beyond perhaps a simple anonymous user with very few permissions for simple website config)
So, now I'm looking at the new web app which will be on the public internet. One suggestion is to have a Active Directory server and create windows accounts on the AD for each user of the site. These users will then be placed into the appropriate NT groups to decide which DB permissions they should have (and which pages they can access).
ASP.Net already provides the AD membership provider and role provider so this should be fairly simple to implement.
There are a number of questions around this - Scalability, reliability, etc... and I was wondering if there is anyone out there with experience of this approach or, even better, some good reasons why to do it / not to do it.
Any input appreciated
Having used ADAM in a project, I found it to be bear. Documentation for developers can be sparse, it has quirks that differentiate it from full AD and, most importantly, I could not get a straight answer from MS as to whether it will be fully supported in the future. The impression I got was that ADAM was the bastard child and that the new Federated services (ADFS) was where they wanted people to go. Just moving the ADAM store from one member server to another was a pain. Now that said, my issues with ADAM had to do with development against and maintenance of the store, It definitely has the ability to scale and it was reliable. That said there are times when you need to delve into 80th level spells of LDAP/Directory magic to figure what it is or is not doing.
For a public facing site, AD/ADAM might be overkill IMO. You could use alternate MembershipProviders like the SqlMembership provider to get the good level of security with respect to credentials. If you wanted to go further, you could use database encryption (SQL Server at least has this ability built-in) to encrypt information that falls into the PII (Personally Identifiable Information) arena and of course encrypt the backups. The advantage that a database backed authentication store has is that you have all the tools that your database product provides to scale out, do backups, control access and so on.
EDIT: Let me add, that with .NET you can setup your site so that it runs under a Windows user and connects to the database using Windows Authentication (assuming the db supports it). Thus, no credentials need to be stored in a config file. However, if you had to store credentials for whatever reason, you can then use DPAPI to encrypt the credentials in the config file.
ADDITION In response the question about securing encryption keys you have a couple of choices. The first is to simply hash the credit card numbers. That greatly simplifies any problems with access to the data however, it means that the customer would have to re-enter their card number for each purchase. If you want to remember the customer's card number, then you move into a new realm of maintenance of the decryption keys. In this scenario, you absolutely should use Windows Authentication to the database and look into SQL Server 2008's Extensible Key Management feature which lets you hook-in a third-party key management program into SQL's encryption functionality. In this way, only the website user would have access to the keys used for decryption. There are other solutions to ensure that the website cannot be compromised. The greater worry is that someone gets a copy of the database undetected. Here's a link on using SQL Server to be PCI compliant:
Deploying SQL Server 2008 Based on Payment Card Industry Data Security Standards (PCI DSS) Version 1.2.
couple ideas
Run AD/AM - Active Directory Application Mode.
It scales well. It's the same core code as AD. Similar management capabilities. Solid reliability. Works with the ASPNET AD Membership Provider.
And it's included in Windows.
Also consider exploring a federated identity system, via ADFS 2.
unlike AD/AM, this approach is fairly leading-edge. The final version of the ADFS v2 server is not yet available from Microsoft, but it is at "release candidate" stage. If you have the stomach to be an early adopter, ADFS2 holds the possibility to employ a federated identity approach. That means you could accept identity tokens from a variety of existing sources: a google sign-in, a yahoo sign-in, any OpenId source, and use that as the identity on your site. Users would not have to "register" and authenticate to you. Instead, your site would honor the identity and authentication provided by some trusted third party, and perform authorization based on that identity.
This is not a direct answer but having a AD user account means you need a windows CAL for that user. Another way would be to issue client certificates to user and map client certs to AD users in IIS.
You might also consider AzMan with SQL store available from Windows 2008 onwards or the open source netsqlazman.

Resources