SQL Server Authentication for Website Login - asp.net

A client requested that we develop a site for them but instead of the standard ASP.NET authentication or using Active Directory accounts, they would like us to use SQL server accounts for authentication. (That is, an account using SQL Server authentication.)
This website would be exposed to the public Internet and would have users that are not employed by the client and the client's Active Directory is not available in their DMZ.
So I have a few questions on this:
1) Is this a good idea? (Our gut feeling is that it's not.)
2) How should we best go about doing this?
Off the top of my head, the best answer I can come up with for how to do this would be to dynamically build a connection string based off the credentials the user enters in a web form. If the connection is successful, continue to the site. Otherwise, kick them back out to the login page. (And, of course, make sure accounts get logged out in the event of too many failed logins.)
Is there a better way?
Thanks.

1) Is this a good idea? (Our gut feeling is that it's not.)
There are a few problems using this. Notably, you would have to run your application as an escalated user to perform user maintenance-- add/inactivate users, change passwords, etc... Running a web-app with escalated permissions on the database is generally frowned on. If you run this kind of thing outside of your application, then you'll need to get your DBA to run all the user maintenance stuff, which isn't fun. Also, if you have requirements around password complexity, password rotation, etc., you may find SQL Server authentication lacking over what would be available in AD, for example.
2) How should we best go about doing this?
You can easily test credentials provided by attempting to login to SQL Server using the supplied credentials. You can read the connection string from your configuration settings, but then load it into a SqlConnectionStringBuilder object (in System.Data.SqlClientsomewhere), manipulate it to use the supplied credentials, and then connect using the result of that manipulation to test if the credentials were valid.
You would want to use that only for testing your login. After that, you could go back to using your normal connection strings.

Related

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.

Authenticate users syncing time out for 2 different sites

I have been puzzling over this and can't think of an good way of doing this. I am developing a website that would require the user to log in to use the system. I'm thinking of using ASP.NET MVC 4's built in authentication. That isn't much of a problem.
The user would be able to use tools on another server (our server would authenticate him and tell the other website, he is good to go, these messages are passed via HTTPS using XML). The other server, require us to create an authentication token for the user to use when the messages are passed between us.
We need to keep the token in our database to authenticate for every request/response with the other server. Which means that this "token table" knows nothing about the forms authentication time out on our server and vice-verse.
Now the problem, let's say the user uses the other server's tools. He would be on the other server for a long time, this would cause the authentication on our server to log him out, since there doesn't seem to be any perceived activity. The other server will not log him out since we are manually maintaining the token. This would be a troublesome for the user, because now, if he needs to use our service, he'll have to log in again even though he was "online" all the time.
Is there a way to "sync" the 2 authentications? At first I was thinking of getting our server to look up the "token table" (instead of using the built in authentication) so that if the last activity was x ago, the user will be required to log in again, this would solve the untimely logging out from our server. But I'm worried about the security implications.
What would be the best way to do this?
Thank you.
Desmond
If I've understood you correctly you are using Forms Authentication in an MVC4 application to authenticate users, but users will also use another web service located on a different server and so while they are using this other server you don't want the MVC4 application's authentication (for the user) to timeout. Is that correct?
If so, one idea that comes to mind is that your MVC4 application could have an API to the external world that would take in a username and use RenewTicketIfOld() to refresh the timer associated with the ticket. You could do this via the other web server making an HTTP request or by simply placing some AJAX on the page to call the API on every page.
There are, of course, security concerns with this method that you would need to consider. Without knowing more about your situation I'm not sure what solution would be best.

Should an ASP.NET application allow administrators to change SQL Server connection?

As the title suggests:
What is your opinion on allowing administrators to update the SQL Server Connection string dynamically from the application versus just showing them the connection details in the application?
Because the database connection is so important and on a heavily used system the abrupt change to the connection seems like it could cause problems. However I would think displaying the server and catalog and whether the connection is using SSPI or SQL Auth could be helpful for administrators who don't like playing with .NET config files.
Thoughts?
How are you identifying administrators? Presumably not by looking at the database. Because if you do use the db and then change the database to another server, it's possible they aren't administrators or there's no database, and then bam - they can't get in to fix it.
Typically, I like to do maintenance on this out-of-band (the config file or even in Active Directory, so it's in a centrally administered resource). We also typically have application administrators (roles, maintenance, approvals, workflow-related "administrators") who really are not system administrators in a technical sense. And often, we do not allow system administrators as user, managers or administraors within the application. i.e. I might have a purchase order system administrator who can void a purchase order, but they can't change a database connection and I have a sys admin who can't even create or approve a purchase order, let alone void one, but they can change the database connection in the config or in Active Directory as part of an upgrade or migration.
I agree that a debug page, help page or about page can be useful to show information to both system administrators and application administrators. Whether they should be allowed to change things there really depends.
Sounds like two bad ideas. Allowing changes to connection strings while the app is running is sure to cause disruption (broken connections, data out of sync, and who knows what else). And even displaying connection details to anyone (even admins) seems like a dangerous security hole.
What kind of site do you have where this sort of thing would be necessary?
Requires that your application run in full trust, otherwise it's just using the System.Web.Configuration namespace:
http://www.beansoftware.com/ASP.NET-Tutorials/Modify-Web.Config-Run-Time.aspx
On any change to the web.config the app will recycle, so still isn't something you'd want to in the middle of the day if sales might be in flight.
Also, usually authentication and authorization relies on the database. So if you can't authenticate and authorize, you won't be able to get to the admin page to change the connection string! (Unless your authorization and authentication has nothing in it that touches the database, at least for the admin page your considering)
Personally I don't like letting administrators change ANYTHING on a live site. All configuration changes should go through the same version-controlled, time-stamped, user-attributed, build-system-checked process that source code goes through. Only then can you draw connections "this stopped working at time X because user Y changed configuration A at time B".
An extreme view on the topic I know, but given the huge proportion of downtime that can be traced back to operator error I believe is justified, and I honestly can't understand the fascination people have for being able to edit fragile XML files on live servers where a single extra '>' can bring the entire site down.

ASP.Net: How to properly implement this Authentication flow

Here's the flow I'm looking for for authentication:
Attempt to pull in the user's name from windows authentication
If that failed (user is external to network), use BASIC authentication to get the username/password.
Check the username/password against the SQL database. If windows, password isn't required, if BASIC authentication and password is incorrect, prompt again
Create the Identity object with the user name, and populate the user's roles via another SQL database call
This would need to be used for multiple applications.
What would be the best method of implementing this? Creating a HTTPModule? If so, what do I need to keep in mind (security, virtual directory setup, etc)
This type of authentication is called Mixed Mode authentication (some google searches on this will get you alot of hits). We have a flavor of this running on a site I work on, however there are some quirks to our setup that have to do with odd business requirements.
Here is an article that might get you going on the subject:
http://www.15seconds.com/Issue/050203.htm
It is a big topic to give a huge detailed explanation of how you could set it up in one post.
Good luck!

ASP.NET Application to authenticate to Active Directory or SQL via Windows Authentication or Forms Authentication

I am in the process of writing an application that will need multiple forms of authentication.
The application will need to support authentication to Active Directory, but be able to fail back to a SQL Membership Provider if the user is not in Active Directory. We can handle the failing to the SQL Provider in code based on the username provided because the username will be a different format than the Active Directory username.
Is this even possible? What I mean is, can I use membership and use both ActiveDirectoryMembershipProvider and SqlMembershipProvider together or will I have to roll my own?
Another additional added complexity is that I would like to automatically authenticate my internal users based of Windows Authentication back to AD, but use Forms Authentication for users not on our internal network, or users that are using the SQL Provider.
These will most likely be separate servers, one internal, and the other external so I have a lot of planning to do to figure out the data replication, and how I will authenticate the AD users if they hit the outside server etc.
I am wondering what thoughts are out there as I start down this road. Is what I am wanting to do even possible without me rolling my own, or is there a way to mesh these together?
Thanks for the reply.
The reason I asked originally was because I was able to get this specific senerio working about 7 years ago using IIS to authenticate and then passing back the credentials to a Lotus Domino Server Web App. If the user was not authenticated via the Windows Authentication/ISS then Domino would handle the authentication. This was what I was looking to do here, but really couldn't think of a way to make it work in IIS.
As for the rest of your reply, I think you are on to the way that I will need to take. I have thought this through and tossed it around in my head a lot. The application will be somewhat different on the two servers anyway since there is going to be limited access to the data on the external server anyway. The fact that so much is going to be different already I may just treat these as two applications, thus negating the need to use two types of authentication in the same application anyway.
I am playing around with the idea already of writing my own authentication/login window for the external server, and if the user trys to log in with their AD credentials on the external server I will be able to detect that and redirect them to the internal server. If they are not on the local network or VPN'd in they will simply not get access. This part still has some thought process to go though so I am not sure.
As an additional thought - is there a way to pull just enough of AD into a SQL database to allow me to authenticate users to the SQL database from the external server using their AD credentials, without creating any security issues? I hope I am clearly typing what I am thinking....
Thanks again!
Tim
This is the way I've handled a similar situation based on this info:
Configured the application to use Forms authentication.
Set the LoginUrl to a page called WinLogin.aspx.
In WinLogin.aspx, use Request.ServerVariables["LOGON_USER"] to get the username then call FormsAuthentication.RedirectFromLoginPage( authorizedUserName, false ) to log them in. I guess you can manually check Active Directory as this point as well.
Create an html page that redirects to a page called Login.aspx
Login.aspx is your standard username/password login.
In IIS, Enable Integrated Authentication and Anonymous on the entire site, but deny anonymous access to WinLogin.aspx.
In IIS, set your 401 errors to the page created in step 3.
What basically happens is that when an unauthenicated user hits the site, they're redirected to WinLogin.aspx. Since anonymous is turned off, integrated security makes a check. If that passes, your custom code in WinLogin can run. If the integrated security check fails, a 401 error occurs. Your custom 401 page redirects to Login.aspx where the user can log in using their username and password with the SQL provider.
As far as I know, Web Applications are configured to use either Windows Authentication or Forms Authentication, but not both. Therefore, I do not believe it is possible to automatically authenticate internal users while requiring others to enter a username / password.
You could authenticate to Active Directory or a SQL user store via Forms authentication by using a custom provider. However, the AD users would still need to enter their username and password. Although I've never combined these two methods, I have used Forms authentication to authenticate against both sources at one time or another.
With that said, I think you may want to consider reducing the "flexibility" of your system. If you have an external facing server and an internal facing server, you could simply change the provider configuration on each copy of the application to go against a different source. Then, you could configure the internal one to use Windows (automatic) authentication and the external one to use Forms authentication.
IMHO, I believe that internal users should not be using the external server to access the application. If they are, they should have a user account stored in SQL, completely separated from their AD account. Basically, when someone accesses the application externally, they are acting as an external user, irregardless of their physical location.
Well, it is possible to use ActiveDirectoryMembershipProvider and SqlMembershipProvider, but this requires you design your log on page with your own code instead of the Login controls.
About the mix authentication (Windows and Forms), as far as I know only IIS 7 makes it easy and clean. See this post for details,
http://mvolo.com/blogs/serverside/archive/2008/02/11/IIS-7.0-Two_2D00_Level-Authentication-with-Forms-Authentication-and-Windows-Authentication.aspx

Resources