I want to create an internal website, preferably in asp.net, that uses ajax calls for performing all operations.
The requirements are that the site should use windows domain authentication (to act as a single-sign-on solution) for verifying which user is sending the request. What is the best way to accomplish this in a secure fashion? I am open to a solution using https or cookies or anything else feasible.
( I would prefer regular ajax using jquery since I havent used asp.net ajax but if that solves some issues more easily, then let me know)
The current way I am doing this (not through ajax) is disabling anonymous access in iis and then getting the logged in username from asp.net, but this requires the site to perform postbacks, etc which i want to avoid.
An Ajax request is not different from any other HTTP request when it comes to authentication.
Your user will most likely be authenticated when they access the index of your site. Any subsequent request, Ajax or not, will be authenticated. There is nothing special to do, and your jQuery code will look just like what it normally looks.
Windows authentication is checked on every request.
How this is checked depends which authentication method /provider is enabled and supported on the server (kerberos, ntlm, custom, etc)
Credentials are automatically sent over under certain rules (I believe intranet trusted for IE, I dont recall what else outside of that).
Firefox will prompt you if I recall every time.
Check out:
http://www.winserverkb.com/Uwe/Forum.aspx/iis-security/5707/IIS-6-0-Windows-Authentication-401-Every-Request
The important thing to note is the browser and server will take care of this and prompt the user when necessary.
Also to note is I highly highly suggest ALL traffic is under an SSL connection at this point to prevent sniffing and credential stealing/token stealking (such as is extremely easy for basic auth)
You can enable this protection inside of IIS and use all file permissions or you can control this in your web applications web.config by enabling windows authentication. How this is accomplished though depends on your server config (kerberos support, etc)
You should absolutely:
Use an https connection to transmit username and password
Authenticate on the server side, with asp.net
Leverage the asp.net session to as great an extent as possible.
If you're not familiar with ASP.Net ... well, consider this a good opportunity to learn :)
jQuery is great, but it's just a tool. In this case, it's probably not the best tool for this particular job.
IMHO...
Related
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.
If I am on a website#1, and I enter my username/pwd for website#2 on a login page that is on website#1, and website#1, behind the scenes, makes a httpwebrequest to website#2 and posts to the login page. If I then navigate to website#2, should I be logged in?
website#2 uses formsauthentication and I call a httpHandler that is on website#2 and pass it the username/password via the querystring.
Should this work?
What you're trying to do is called Single Signon. The way you're doing it, posting values from one site to another, probably won't work because you're using the same technique a hacker might use to trick user into sharing their login information. It's called a cross-site request forgery attack. IIS is configured not to allow that.
Generally, you need a central authentication system that both sites use to share login information. This can be done in several ways, including a shared database-based login system. Google "asp.net single sign on" for more ideas.
Do site #1 and #2 want their users to have single sign on?
If so, read up on single sign on. It's a bigger project than can be addressed here. There is a good book on it though from Wrox :
http://www.amazon.com/Professional-ASP-NET-Security-Membership-Management/dp/0764596985/ref=cm_lmf_tit_10
Or are we imagining something sinister?
If we are imagining something sinister, then evil site #1 would collect the credentials, then automate a browser on the server side to start checking to see if site #2 uses the same password and user combination. Then the server would have an authenticated session. This wouldn't give the user who accessed site #1 an auth cookie, the HttpWebRequest object on the server would get the auth cookie. Site #2 couldn't really do anything to prevent this because a browser request from one computer looks much alike a browser request from another. A well crafted attack would spoof all elements of the browser's request so that it looks like it came from a browser instead of a primitative HttpWebRequest object, which may not even set the user-agent.
Site #2 should stop using passwords and user Id or use 2 factor ID if they are concerned abut this, or do something that requires javascript for logon because spoofing a browser that is executing javascript is harder than spoofing a browser that just sends and receives http requests and responses.
There are too many security issues trying to auto-authenticate between sites. There needs to be a central security provider that both sites belong to so that hand off is completed securely.
We use CA's Siteminder for cross site authentication. Effectively, web 1 creates a unique session id on the siteminder server and passes any credentials and info to it. Siteminder invokes web2 and passes the information by means of session variables. Web 2 retrieves the data from the session and uses it. There's much more going on there but that's the just of it.
To do something like this, I would strongly consider using an out of the box solution as generally coding up custom security generally falls short.
While this can be done on some cases, in the form of an HTTP request with POST parameters, you will not be authenticated once you browse to site #2.
This is because, generally, these sites store a cookie on your end and these are domain-based, which means that even if you grabbed that and stored it yourself from site #1, the cookie name would not match site #2.
Additionally, site #2 may not be easy to authenticate against and this is usually a security concern that developers are aware of. This can be considered an attempt of XSS as well.
In case you're simply doing this for yourself, I'd recommend LastPass and save most of your info in it.
Please reconsider your goals and how to achieve them, this is not the way.
Edit: Link text.
This could work, depending on the security measures in place on website #2. For a secure website, this would fail.
I would recommend against this purely on the basis of good security and good coding/design practices.
If you are unclear what security measures stop this, you should probably educate yourself so you can prevent the same issues on your own site. See http://www.owasp.org/index.php/Top_10_2007
Since both your sites are using FormsAuthentication you can easily configure both of them to share FormsAuthentication encryption schemes.
This will allow you to do Cross Application Authentication automatically :)
I've built an application that uses jQuery and JSON to consume an ASP.NET .asmx web service to perform crud operations. The application and .asmx are on the same domain. I dont mind people consuming the read operations of the .asmx remotely but dont want people randomly deleting stuff!!!
I can split the methods i'd like to be publicly accessible and the 'hidden' ones into 2 web services. How can I lock calls to the 'hidden'.asmx web service to the same domain that its hosted in?
Thanks in advance.
Edit:
Can someone comment on this, seems plausible ( source: http://www.slideshare.net/simon/web-security-horror-stories-presentation ):
Ajax can set Http headers, normal forms cant.
Ajax requests must be from the same domain.
So "x-requested-with" "XMLHttpRequest" requests must be from the same domain.
There are two scenarios you need to secure with web services:
Is the user authenticated?
Is the action coming from my page?
The authentication piece is already taken care of if you're using Forms Authentication. If your web service sits in a Forms Authentication-protected area of the site, nobody will be able to access your web services unless they're logged in.
The second scenario is a slightly trickier story. The attack is known as CSRF or XSRF (Cross Site Request Forgery). This means that a malicious website performs actions on behalf of your user while they're still logged in to your site. Here's a great writeup on XSRF.
Jeff Atwood sort of sums it all up in the link above, but here is XSRF protection in four steps:
Write a GUID to your user's cookie.
Before your AJAX call, read this value out of the cookie and add it
to the web service POST.
On the server side, compare the FORM value with the cookie value.
Because sites cannot read cookies from another domain, you're safe.
In AJAX the browser makes the calls, so even if you were to check that the domain is the same it wouldnt be secure enough because it can easily be faked.
You need to use some sort of authetication/autharization tokens (preferably with a time out) to keep things safe.
Quick and dirty solution would be to use IP address restrictions to allow only your domain's IP address access via IIS.
Probably better would be using HTTP authentication. There are many ways to do this, I found Authentication in ASP.NET Web Services a helpful overview.
I am maintaining a public website (no authorization required) that uses web services over https to perform various operations. Most of the calls to the web services are invoked from javascript.
What has recently occurred to me is that a malicious hacker could, if he/she chose to, call the webservices directly in an attempt to play havoc with the system.
In reality, there is not much damage they could do, but in practice these things are difficult to predict.
Bearing in mind that the web service calls will be exposed in javascript code (which is available to the client) what is the best approach I could use to prevent unauthorized and/or malicious access to the web services.
Sadly, I can't just restrict access by IP, as there are windows forms-based client applications out there which also interact with the web services.
Using windows authentication may be difficult, as these client apps can be run from anywhere in the world and the users are not part of any specific AD Group - or even domain for that matter.
I'd appreciate any suggestions, bearing in mind the two different classes of access and the exposure of the javascript code.
Anything called by javascript can be mimicked easily by a malicious user who has the right to use that javascript. I would suggest modifying the page to use a more server-side solution. Leave AJAX to stuff that can't be easily exploited.
Preventing an unauthorized user is MUCH easier than supporting full public access. If you drop a time-expiring guid on the user's cookies, tied to the individual user, that gets sent as one of the arguments to the Web Service, you have an extra, generally difficult-to-break, layer to the application.
Anyone who has access to execute the javascript, though, should have no trouble piecing it together. Someone who has no access to the javascript can probably be kept from accessing the Web Service easily.
It takes a bit of doing, but if your page is also ASP.net you can set up a shared session, turn on the EnableSession attribute on your webservice and use session data to secure the session. An overview can be found here: http://blogs.lessthandot.com/index.php/WebDev/ServerProgramming/ASPNET/sharing-asp-net-session-state-between-we
This would necessitate a different "version" of the service for your windows apps to consume.
I am building a web based application written in ASP.NET and Flex. One of my biggest challenges is implementing security for the application in a flexible and maintainable way. This challenge is compounded when different technologies are involved. I'll try to describe what I have below.
The website is laid out as follows:
/mydomain.com/
Login.aspx
Default.aspx (hosts flex [.swf] application)
/Administration/
AddUsers.aspx
AddRoles.aspx
AddPermissions.aspx
etc...
/Services/
SecurityService.asmx
MapService.asmx
PhotoService.asmx
etc...
I am currently using forms authentication to secure the resources on the website. All pages/resources not in the /Services/ folder require an authenticated user and will be redirected to Login.aspx if they are not yet authenticated. The .asmx pages allow unauthenticated users. To secure these resources I throw an exception in the SOAP method. This avoids redirecting pages for SOAP web services which is not supported by any SOAP web service clients I am aware of. Finally, SecurityService.asmx contains a Login method to allow the Flex application to Login without redirecting to the Login.aspx page should the cookie expire for any reason. Because the cookie established is sent with any request to the server, including requests coming from the Flex application, this seems to work pretty well.
However, this still feels like a bad approach securing web services. I feel like I am using Forms Authentication for something it was not intended for. Specifically, I am concerned about:
This model will not work when the services are separated from the core website. This is a newly discovered requirement and I believe that Forms Authentication is not going to work well (if at all) without a lot more modification and trickery.
Clients other the Flex may require access to the services. Some of these clients may not even be able use cookies. If so, this model immediately falls apart. This is not an immediate requirement but it is known that this is one of the long term goals.
We will eventually (hopefully sooner rather than later) move to a REST based architecture (vs. SOAP) so any solution needs to work for SOAP and REST.
So, my question is.
What are the best authentication and authorization mechanisms for securing an application built on ASP.NET, Flex, and SOAP or REST web services?
Note: I am actively looking into OAuth; however, I am having a difficult time finding complete examples from which to learn. Additionally, I need to be able to filter the data returned for a given user based on the permissions that user has, OAuth seems to remove the identity of the user from the token. As such, I am not sure how OAuth applies in a fine grained security model.
Others may disagree, but I actually don't see a huge problem with handling it the way you are now; that's probably how I'd handle myself, at least initially. One way or another, even down the road, you'll probably want to keep the Flex app aware of the authentication state of the session, so if that means checking the ASP.NET session token directly, or some other cookie you set when you set that one, it seems like a fine and reliable way to go.
I do see what you mean about the services redirecting, but even so, with forms auth, it's not so much the service specifically that's handling the redirecting so much as the ASP.NET app itself. Later, should you need to use a different authentication scheme, you can consider that scheme's specific implementation considerations. Unless you've got concerns about using forms auth in general, there's probably no need complicate your approach simply because of the Flex client and Web services.
I admit I don't work with web services much, but what about requiring an access key as a soap header parameter? Any client app which can communicate with a soap web service is likely to have a low level API to modify the soap request, and use of the access key allows you to (in theory) limit the use of the service. Google, Amazon, and several other providers use this type of authentication for their web services and it seems to work very well.
This article seems like it might be a good place to start...
The WCF Security Guide published on CodePlex may help you there, if you are using, or can use WCF.
There's also Microsoft's Web Services Enhancements (WSE) 3.0 which I believe implements some of the WS-* security specifications.
Hope that helps.
If you move your services to another place, then the standard ASP.net authentication cookie can be re-used if both web apps have the same machineKey in the web.config.
As far as I know, FLEX will honour the asp.net authentication cookies because it will make http requests through the browser, which will pass the http cookies (including the asp.net authentication ticket) like a normal http request.
Have you tried securing your website and services using normal asp.net authentication yet?
I think it's best to have independent authentication systems - even if there are relations between the user and the auth tokens on the back end. They are different beasts that have differing capabilities and demands.
Use the normal forms based auth for the flex portion. That is good.
For web services, you could create a login method that returns some auth token which is used by subsequent tasks to execute. Or add a few fields to your web services (posted in the header or as params) to use a userid/password combo for authentication each and every time.
A side note: I wouldn't rely on a soap exception to handle authentication problems. But you wouldn't need to worry about the redirection if you send an auth token or user/pass with the WS requests.
EDIT:
RE: Comment-
Ideally there is. There are products out there (Tivoli access manager) that service those needs, but they are expensive.
I gave this recommendation because it eases the pain of allowing access to alternative clients and as long as you designed the services correctly it's stateless. It also gives you finer grained control over data level access on the service side of things.
See Web Services authentication - best practices?
Dave Dunkin wrote:
The easiest way to handle it across a
variety of platforms is to use HTTP
basic authentication and HTTPS for the
transport layer. WS-Security would be
good if your needs go beyond simple
username/password but the support is
going to vary quite a bit between
platforms. HTTP authentication is
supported by every decent SOAP
implementation.
and my Custom HTTP Basic Authentication for ASP.NET Web Services on .NET 3.5/VS 2008.