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.
Related
I know ASP.NET supports various authentication models like, Windows, Forms, passports and recently Claims.
I have an asp.net that prompts user to enter user name/password to login, it then compares the input username/password with the entries inside the user table of the application's Database. So, my question is, what is the term/name for this kind of authentication model? Where does this fall in the above mentioned ASP.NET supported authentication model?
I also see that many of the internet sites that I know uses this same approach.
(note: I'ev kept my App simple, of course it has user registeration/add page, profile table to authorize users, etc)
Windows, Forms, Passport, Claims, etc.. authentication are BROWSER authentication schemes. They are the mechanism the browser communicates with the server to present credentials. They have nothing to do with databases or any other storage mechanism (well, mostly..). Those are just implementation details.
FormsAuthentication uses a cookie to store an encrypted value that tells the server that the user has been authenticated. How the user is authenticated, be it by comparing things to databases, using a service, etc.. is all irrelevant if the end result is that a FormsAuthentication cookie is issued.
WindowsAuthentication is a little different in that the browser and the web server communicate to share a Kerberos ticket to verify identity, or the user enters the username password into a box that the server requests the browser to pop up. In this mode, the server itself manages the way that authentication occurs and the app isn't involved.
BasicAuthentication uses an HTTP Header to send the password in cleartext, well, technically it's an encoded password, but it's well known so anyone can unencode it. Again, the actual method that it stores the data is up to the server, and the server does this without an applications knowledge. The important part is that it's accomplished via an HTTP Header.
The same is true of other types of authentication, which are all just variations on the cookie and/or header mechanisms.
The point here is that Authentication is about how any given HTTP request identifies who the user is to the server, and ultimately the application. Not how the data is stored, or validated. So, since you did not tell us how the server and browser communicate, we can't tell you how your authentication is defined, although almost certainly it is a variation of FormsAuthentication.
EDIT:
Just a little history lesson. The reason it's called FormsAuthentication is because the authentication system does not use a pop up dialog box from the browser to enter credentials, but typically the web page provides an HTML Form for the user to enter credentials. The browser is not really involved in the authentication process at all, other than for passing a cookie as requested.
It should be more accurately called "CookieBasedAuthentication", but the name has stuck and will probably stay what it is. ASP.NET provides a specific implementation called FormsAuthentication, but you can do the same thing with any cookie based authentication scheme (although I do not recommend rolling your own, you will almost certainly make security mistakes).
Some people think that storing a flag in Session is good enough. Do not, under any circumstances, ever use Session to store authentication information. Session cookies are not encrypted and are easily stolen and/or spoofed. Use a well known method.
The other answers might have already showed most of the details. But if we categorize carefully on IIS and ASP.NET levels, below are the differences you should pay attention to,
IIS Authentication
This occurs first, as HTTP packets arrive at IIS level first. IIS supports several ways,
Anonymous (the anonymous user account configured in IIS configuration)
Windows (browser side user)
Basic (browser side user)
Digest (browser side user)
How those authentication methods work at packet level requires you to capture network packets and dive into the conversation at that level.
The result of this authentication is that IIS generates a user token and passes on to ASP.NET pipeline.
ASP.NET Authentication
ASP.NET has several authentication methods of its own,
Windows (here ASP.NET trusts and interprets the user token IIS passes, and determines which ASP.NET user identity should be created and which roles it supports, without doing further authentication on ASP.NET level.)
Forms (based) authentication (where ASP.NET ignores the user token, and uses cookies or similar mechanism to build a high level authentication approach. On IIS side you usually set anonymous authentication.)
Claims based authentication, OpenID, OAthen and so on are similar to Forms based, where they don't care much about the user token generated by IIS.
It is possible to use non-anonymous on IIS plus non-Windows on ASP.NET side to set up the so called mixed authentication.
All the Authentication methods that require the user to input a Username and Password that you maintain are a form of Forms Authentication. This is because you are asking them to fill out a form (Username and Password) in order to authenticate them.
Read more about it Here or Here.
Edit: The answer provided by Mystere Man is much more complete and accurate than mine.
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.
I'm using a login form to authenticate users.
FormsAuthentication is right out as it stores sensitive user/role membership in either client-side in a cookie or within the URL. Within the URL is a huge security risk, so I won't even get into that. With the
FormsAuthentication cookie, this creates problems with a) security where the client is in the position of dictating it's own roles; and b) way too much data stored in cookies. Since I'm gaining nothing through security and loosing out big time on the size of user data storage, I'd rather just work with Sessions.
I'd like to reuse something like FormsAuthentication for all its basic login form-handling features. But i would rather have it store user data server-side in perhaps Session rather than client-side all stuffed into a single cookie. I'd rather just authenticate against a Session token of some sort.
I have no database and local disk storage of user data is forbidden. I rely on a 3rd party authentication service provider, and a requirement is that I must reduce chatter with this service. Thus, sessions for temporary storage of user info. Sucks, but that's not necessarily the problem I'm asking about. Also, a requirement is that I must set/use HttpContext.user and likely Thread.CurrentPrincipal for use later on in such things as AuthorizeAttribute, for displaying user info in views, etc.
So FormsAuthentication stores all user data client-side in a cookie. Whereas Session stores all data server-side and just relies on a simple client-side token cookie. However, Session is not available anywhere during the asp.net startup and authentication steps. Is there an equivalent forms "membership" provider that stores all data in Session server-side instead of client-side?
If there is no Session equivalent...
Where do I set HttpContext.user and Thread.CurrentPrincipal to make both values available throughout the rest of both MVC apps without interfering or messing up other MVC components?
Hinging on #1, is Session available at that entry point? If not, how do I make it available so I can create the Principle/Identity object using the data stored in Session?
This can't possibly be a unique requirement. Are there libraries already available which handle this?
Session stores information in a client-side cookie too! (or in the URL if cookieless).
If you want to authenticate a client, he'll have to provide some kind of credentials - usually an encrypted token in a cookie once he has logged on. If not a cookie, then what do you propose?
You should use FormsAuthentication. The sensitive information stored in a client-side cookie is encrypted using a key that should only be known to the web server. "the encryption methods being public knowledge" doesn't mean that you can decrypt the data without access to the appropriate cryptographic key.
You mention "roles" and a "third-party authentication provider". If your third party is also providing roles (i.e. an "authorization provider" as well as an "authentication provider"), then it would be reasonable to cache roles obtained from the provider on the server. Session is not available when a request is being authorized, so the best solution is to use the Cache (System.Web.Caching.Cache).
Personally I would encapsulate this in a custom RoleProvider. The custom RoleProvider would implement GetRolesForUser by getting roles from the third party on the first call, then caching them in Cache.
Not sure if I like what I'm about to suggest, but you could do the following:
Leverage the Application State or System.Cache as a global storage for user credentials.
Use an InMemory database (like RavenDb) which can also have encryption (in memory, I believe).
Using the Application state as a place to storage relatively common / frequent stuff I think is not a great place because of
Scaling / locking issues? <-- just a gut feeling.
Permenant data? so you have users in the website's memory .. then the website crashes or recycles, etc... what happens now to that data?
RavenDb is awesomeballs - go.use.it.now.
I understand that you are not storing anything locally, so whenever a user hits your system, you need to refresh your inmemory cache, etc. Fine. A pain in the f'ing butt , but fine none-the-less. (EDIT: unless the data has been cached in memory .. that is)
Anywys, two suggestions.
ProTip:
Oh! move away from role based shiz and start using Claims based identity stuff. Yes, it still works with IPrincipal and HttpContext.User, etc. So all previous code is NOT busted. But now it's baked into .NET 4.5
Awesome Video on this for you, me, everyone!
Finally - bonus suggestion
A nice package that auth's with either Facebook/Google/Twitter. You said you're keeping the user cred's on another site (good move!). If you're using other providers, then stick with DNOA or SS.
GL!
I've got a requirement to allow impersonation ("act as") in my API. So a user with the appropriate permission can exercise the API as another user. I'm wondering if there are some specific strategies employed in this space?
I can create an endpoint to begin and end the impersonation. Beginning the impersonation might involve getting a user and their permissions and loading them into memory for the current request, easy enough. What about subsequent requests? Is it bad practice to add an HTTP header indicating a "Impersonated-User"? If that header exists, use it to do auth on subsequent requests? What about using a cookie with that UserId? Or additional information?
Is there added benefit (assuming a .NET impl) to assigning the impersonated users to the Thread.CurrentPrincipal? The current permission and role implementation is custom, essentially using a bit array (although this is on the table for change in the future).
HTTP doesn't include any native support for delegate credentials / impersonation, so a combination of HTTP Basic Authentication with a custom header indicating which other user the client is trying to act as would be fine.
I would avoid polluting your API with the idea of "beginning and ending the impersonation", however. That implies stateful session knowledge that must be maintained between API calls, and it will make it more difficult to manage on the server side.
I would just have the client pass all the required information (their creds and the impersonation principal) with each call, and validate them each time against the resource being invoked.
I'm investigating creating a WCF REST service for an existing asp.net application to be consumed by various clients including Windows Phone 7, Android, iPhone apps etc.
Creating a simple WCF REST service and consuming it from the above platforms is not a problem and works really well. What I am struggling to get my head around is authorization.
The asp.net application uses the Membership provider to provide authentication and authorization and I'm comfortable in using that API from the REST service.
How do I secure my REST service so that the first call has to be to authenticate (passing the username and password) and following calls know who is 'logged in'. I'm guessing the authenticate method will have to pass back some sort of token to be used in subsequent calls identifying the caller. Is this secure enough as the whole site / service is over SSL?
Any suggestions welcome.
The more restful authentication scheme is to use HTTP Authentication, e.g. Basic or Digest. Since your service is over SSL, Basic should be sufficient. The authentification tokens (login/password) are sent with every request, so that the service can be stateless. Every client library that I'm aware of can deal with basic authentication.
In general the token approach is better then just sending username+password (Basic Authentication) in each request. The problem is to implement it correctly: while Basic Authentication is very easy to implement, and actually it's already implemented by most application and web servers, the token is something you'll need to implement yourself - it must be encrypted, so clients won't understand it, so you'll need some keys management, it also must have some expiration date and may be you'll want some revoke functionality.
In addition, it will make client's life harder: instead of just attaching basic authentication header to each request, client must first go to some authentication point, receive a valid taken and then use the token on the requests. If the token expires, the client will need to go to the authentication point again.
So if you have time and knowledge, and your clients are smart, it's better to use the token approach. Otherwise with SSL, basic authentication should be sufficient.
I've seen an example in the latest Windows Azure toolkit for WP7 that might be helpful for you. It basically uses the Membership Provider, logs in a person (the first time the person installs the app) and then generates a Ticket. It then Encrypts this ticket and sends it back as a TOKEN which is then stored on the phone in the isolated storage. The expiration of the ticket is set to int.MaxValue so that the token remains good for a long period of time.
Now, this token is passed over to the Web Services in the Authorization Header where it is decrypted, the identity of the user is verified and then the web service call is made.
Hoping this helps. I am trying to solve a similar scenario and trust me, there isn't much out there that points us in the right direction...which is a pretty sad state of affairs if you ask me.