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.
Related
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.
These are the criteria:
My users are unauthenticated.
My app is a single page web app (written in JavaScript) that uses RESTful web API endpoints to fetch data from my own server.
Objective: I'd like to constrain the web API to only allow requests from my own app, without requiring users to authenticate. Are there existing techniques for this?
The issue is that since the web app's code and the requests made by it are transparent to the client it can't hold a secret for authenticating with the server.
I thought about creating single-use access tokens on the server side, then use those from the client side for the API calls. Now this would make it harder to do requests from the outside, but still you could make requests if you fetch this token from the original website first (even if you'd have to do it for every request).
If it matters I'd implement this with an ASP.NET MVC website and ASP.NET Web API endpoints.
Similar to this question but not entirely the same.
Thanks in advance.
I asked pretty much the same question a couple of years ago, and for unauthenticated users, some kind of token is pretty much going to be your only option. It doesn't make it impossible to get unauthorized access to your API, but does make it a little more painful.
I took a slightly different approach in my solution, using 2 cookies to protect some anonymous GET requests. One of them was the anonymous identification cookie, which was used as an encryption salt for another custom cookie given to the page that delivered the javascript. Only when the API request received both of these cookies and the decrypted result was satisfactory did I allow the WebAPI to respond. But like I mentioned, this only makes it more painful to gain access outside of the javascript app, not impossible.
Here is a reference for using tokens in WebAPI: http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/
I want to create a authorization mechanism for an application based on WebAPI and AngularJs.
I've seen some articles, which use BasicHttpAuthentication, but i really don't like the whole idea of sending username, and password on every request. The more it doesn't fit for me is because i want to use OpenId authentication, where you don't have username/password pair.
I'm thinking about a solution, but I don't really know how to implement it. The concept is that user is authenticated as in an usual Web application - posts a form with user / password or selects an OpenId provider. If the user is authenticated succesfully, it is placed in a static object, which stores the User object for a certain ammount of time. Next a usertoken is generated and passed to the Client Application. The client passes the token on each request to the server, if the user exists in the above mentioned static object with the appropriate authentication token it is authorized to get the data.
Firstly - Do you think this is a good approach to the problem?
Secondly - How should I pass the authentication token, WITHOUT using cookies? I guess it should sit in the request headers, like in BasicHttpAuthentication but, I really dont' know how to handle it.
BasicHttpAuthentication
I'm with you on feeling dirty about caching the username and password on the client and forever transferring it with every request. Another aspect of Basic authentication that might work against you is the lack of sign-off. Other than changing the password, you can't "invalidate" a basic authentication session. Tokens on the other hand, will typically offer an expiration date, and if you want server-side invalidation you can check the issue date and say "any tokens older than issue date xyz are invalid".
Server State
You mention "If the user is authenticated successfully, it is placed in a static object". But this is independent of the token? This sounds like you're wanting to implement server state management of authentication sessions, but this isn't strictly necessary. The token itself should be sufficient for user authentication, managing server state is another potential obstacle. Server state can become difficult to manage when you factor app-pool recycles or web-farm environments (what if you want two services to share the same authentication token, but not require communication with a central "authentication server" for storing the state / session?)
Passing Authentication Token
Headers is definitely a good place for it. Really, where else is there? Cookies, Headers, Message. Other than a browser client, cookies don't make a lot of sense, and including it in the message can muddy your message formatting a bit, so headers is the only remaining option that makes much sense in my view.
Client Implementation
You've not specified, but I suspect you're interested in calling the service from .NET? In which case System.Net.Http.HttpClient could be your friend. In particular, the DefaultRequestHeaders collection. You can use this to add a custom header to store your authentication token.
Server Implementation
When researching ASP.NET authentication recently, I learned a lot about customisation by examining the Mixed Authentication Disposition ASP.NET Module (MADAM). I wasn't interested in using MADAM as-is, but learning about it from that article and examining the source code gave me a lot of ideas of how I could insert my own authentication module into the web stack.
I'm looking for a way to pass some sort of credentials or Authorization token from a VB.Net Client to an ASP.Net web application that allows the Client to auto-login to our Forms-Authenticated website. If a user is logged into a local application, I want them to be able to view some web pages without having to login to the website as well. The credentials are not the same between the apps, but I would just like to pass some sort of encrypted token or key to the web page so I know they are coming from the desktop application. Is this possible without requiring a username and password login?
I also need to make sure this URL that is used cannot be simply copied and used from another location, so I'll need to include some sort of information in the encrypted value to know where it's coming from.
I know how to login the user with Forms Authentication and all that, just need to figure out the best way to secure this. Thanks!
OAuth is commonly used to allow desktop applications to access a user's private data on a web site. Since you're using .NET, I suggest you check out DotNetOpenAuth which includes sample OAuth web sites and client applications. It allows for this secure token to be passed that can tell your web site that the desktop app is the one making the requests and (usually) whose data is being accessed.
The best part about the OAuth solution is your desktop app never has to ask for the user's credentials. No credentials are in the URL. And if the desktop application is ever compromised (perhaps by the computer being stolen), the web site can kill the secure token the desktop app was using to cut off access without requiring the user to change their password.
You might want to look into issuing client-side certificates for these applications. Basically, you generate a certificate that you install with the client application and then on the server side, you check the ClientCertificate property of the HttpRequest instance exposed by the Request property on the current context.
Note that what you are doing is really a very bad idea, in that applications should never be assigned identity, only users. To that end, you should be authenticating each and every user that is using your app, not considering the application to be the identity. It's commonly considered a bad practice to do such a thing.
You can share credentials between the applications using ASP.NET Client Application Services.
Here are some resources:
Client Application Services
Client Application Services with Visual Studio 2008
Is your desktop app running on machines that are in the same domain as your web server (i.e. all in the same company)? If so, Integrated Windows Authentication is your easiest solution.
I think its best idea to use a web browser control inside the desktop application .
Then use the WebBrowser1.Document most probably
WebBrowser1.Document.Cookie
get if the user is singed in.
I also need to make sure this URL that
is used cannot be simply copied and
used from another location, so I'll
need to include some sort of
information in the encrypted value to
know where it's coming from.
If you store the encrypted value in a cookie or as a field in a form (POST request), then the credential is no longer in the URL and so it can't be easily copied (note that I said "easily").
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