redirect to another URL issue in ASP.Net - asp.net

I have two web applications and sometimes I need user to jump from one application to another. Since they are two web applications and may reside on different domains/machines, I can not share session between them.
The technical challenge for me is how to pass session information (I only need to pass userID string information in the session) from one source application to another destination application -- so that the user feels Single Sign On and personal information is displayed for him/her in both application (as the userID is passed to the destination application, no re-login is needed).
My current solution is generate all URL strings in both application and append them with user ID after user logins successfully, like http://www.anotherapplication.com/somepage?userID=someuserID, the userID value is retrieved from session. But I think my solution is stupid and I want to find some way to automatically append the query string ?userID=someuserID when the user jumps to another URL in another application -- so that I just need to generate the common unified URL http://www.anotherapplication.com/somepage in both application.
Is there a solution to automatically append the userID query string?
thanks in advance,
George

Rather than doing it via the Querystring, it might be more maintainable in the long run if you use create a FormsAuthenticationTicket with the required values.
I especially recommend reading Michael Morozov's excellent article on the subject of SSO (Single sign ons).

I do not think it is a good idea to have the user id in query string.
A better idea would be to implement a single-sign on solution. In your scenario, you could do the following:
Whenever one of your applications receive an unauthenticated request, redirect the user back to the other application to a special single-sign-on url.
This page checks whether the user is logged in, and if so, redirects back with an authentication token in querystring.
This token is checked by the un-authenticated application; and if it passes, you can login the user.
Of course, this seems like "a lot" of redirecting, but it should be reliable, and it only happens once, and then your user will be authenticated on both applications.
Obviously you would need to implement a security scheme so that you can check that the authentication token you get passed is really valid and originating from your other application. You could do this with a challenge-response algorithm; which could be:
Both applications should know a common key.
First application sends some random data (the "challenge") to the second application.
The second application includes a hash-value of the random data + it's answer + the secret key in its response.
Now the first application can check that the second application knew the secret key by calculating the same hash-value.
Have a look at:
http://en.wikipedia.org/wiki/Challenge-response_authentication
EDIT:
With regards to session state, see http://msdn.microsoft.com/en-us/library/ms178581.aspx for an overview. It is possible to share session state between the applications, but I would not recommend it in general. If your application resides on different domains (URLs) you would have to use cookieless session state; which is not safe. If you decide to go this way, you would either have to use State server or SQL Server for session persistence, depending on your setup.

You can persist the session using something else than InProc (which is short for in process). If you persist the session using a SQL Server backend you'll be able to retrive the session cross domain/machine if they are setup to use the same SQL Server backend for session storage. This is configurable in ASP.NET and support out-of-the-box. I suggest you look it up.

Related

Asp.NET WebAPI custom authorization

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.

Simple password protection on a page in ASP.NET MVC

I wish to secure individual (dynamic) pages in an ASP.NET MVC application.
I do not want to use a full blown authentication system - we are already using forms authentication for the administrators of the site. Instead, this is so that we can send out links to a page with a password for specific users.
The way I am handling this currently is when a valid password is submitted we create an encrypted cookie containing the page id (Guid) and their session id and redirect them to the page. In our "Page" controller action we then validate this cookie.
So first question, is this the best (most secure) approach (aside from using forms authentication)?
Second question, can I read the machine key used by Forms Authentication to perform the encryption, or better yet use the FormsAuthentication to encrypt the cookie (the only overload I can see is one that requires a FormsAuthenticationTicket)?
Since we always generate a new machine key before deploying it would be better if all our encryption used the same key.
[Update]
Regarding how to access the machine key I found my answer at http://rich-rogers.com/archive/asp.net-c-sharp-encrypt-hash-using-machinekey-values
[Update 2]
I realize after asking this question that since I will need to maintain a list of pages that they do have access to, I would probably be better off just storing these in the current session. I can store a list of security tokens with an expiry date. Since I already have a wrapper around session, this should be easy to unit test too.
To make really secure your cookie-key, you need to make it available only on SSL pages, or else some one can get it, and even if its encrypted he can use it.
Request.Cookies[cookieName].HttpOnly = true;
Request.Cookies[cookieName].Secure = true;
Also to read: Can some hacker steal the cookie from a user and login with that name on a web site?

User roles - why not store in session?

I'm porting an ASP.NET application to MVC and need to store two items relating to an authenitcated user: a list of roles and a list of visible item IDs, to determine what the user can or cannot see.
We've used WSE with a web service in the past and this made things unbelievably complex and impossible to debug properly. Now we're ditching the web service I was looking foward to drastically simplifying the solution simply to store these things in the session. A colleague suggested using the roles and membership providers but on looking into this I've found a number of problems:
a) It suffers from similar but different problems to WSE in that it has to be used in a very constrained way maing it tricky even to write tests;
b) The only caching option for the RolesProvider is based on cookies which we've rejected on security grounds;
c) It introduces no end of complications and extra unwanted baggage;
All we want to do, in a nutshell, is store two string variables in a user's session or something equivalent in a secure way and refer to them when we need to. What seems to be a ten minute job has so far taken several days of investigation and to compound the problem we have now discovered that session IDs can apparently be faked, see
http://blogs.sans.org/appsecstreetfighter/2009/06/14/session-attacks-and-aspnet-part-1/
I'm left thinking there is no easy way to do this very simple job, but I find that impossible to believe.
Could anyone:
a) provide simple information on how to make ASP.NET MVC sessions secure as I always believed they were?
b) suggest another simple way to store these two string variables for a logged in user's roles etc. without having to replace one complex nightmare with another as described above?
Thank you.
Storing the user's role information in a server-side session is safe providing a session cannot be hijacked. Restating this more broadly, it does not matter where user role info is stored if an authenticated session is hijacked.
I advise not putting too much faith in the article you linked to, but the 2002 vintage report linked to from your link is of interest. Here are my take-aways:
Don't accept session IDs embedded in URLs.
Focus your time on eliminating cross site scripting dangers i.e. scan all user supplied data and parse out executable java script.
Issue cookies for complete domains (e.g. myapp.mydomain.com)
Host your domain at a high class DNS operator e.g. one that only allows DNS changes from a preset remote IP address.
Don't issue persistent session cookies.
Reissue a session cookie if someone arrives at a login page with a sessionID already associated with an authenticated session.
Better still, always issue a new session cookie on successful authentication and abandon the prior session. (Can this be configured in IIS?)
The only way to make a secure cinnection is to use SSL. Anything less than that, and you simply have to make the evaluation when it's "safe enough".
A session variable works fine for storing a value, with the exception that the web server may be recycled now and then, which will cause the session to be lost. When that happens you would have to re-authenticate the user and set the session variable again.
The session variable itself is completely safe in the sense that it never leaves the server unless you specifically copy it to a response.
Have you considered setting up a custom Authorize tag in MVC. I gave an example of this in another question.
On initial authorization (sign-in screen or session start) you could seed a session value with the IP address also. Then in your custom authorization, you could also verify that IP's still match up as well. This will help make sure that someone isn't 'stealing' the person's session. Everytime you access your session data just make sure to pass the requester's IP and have some check on it.
Are you trying to control the access to functions at the client level? That is the only reason I would expose the roles and items to control client side functions.
Alternatively, you could create a function to obtain the items that the roles of the user are allowed to use, and then even if the function is called outside of the items given back to the web application, you can prevent the user from accessing them.
4Guys seems to show how to control functions with the roles.
The approach I have used in the past is to use symmetric encryption of a cookie alongside SSL. Encrypt the user information in the reponse and decrypt it in the request. I'm not claiming this is foolproof or 100% secure and I wouldn't want to do this on a banking application, but it is good enough for many purposes.
The main issue with session variables is that if you store them inProc rather than persisting them, then you need to apply 'sticky' sessions to your load balancing in a web farm environment. Guffa is correct that without this persistence session variables will occasionally be lost causing a poor user experience.
Sticky sessions can lead to uneven load balancing, perhaps reducing the value of being able to scale out.
If you are going to be be persisting the sessions so they can be accessed by all servers in your web farm, you may be better off using a Guid to identify the user, encrypting this in a cookie and retrieving the user record from your data store each time.
My obvious question is that why do you want to store a users role in session ?
Here is my answer to your query, how this helps. I have attached a small demo application for you to take a look at and understand my points. When you open this project in visual studio, click on the project tab on the top and select asp.net configuration. From the page that will show up you can do the user administration stuff.
You need to store the roles of a user in some secure manner ? The answer to this question is that there is no need for you to worry about storing the role for any user, when we have the asp.net membership, profiles and roles framework to help us out on this. All you need to do is create a role in the aspnet database and assign that role to the user.
Next you want to store two string in some secure manner. I suggest you user profile for storing user specific information. This way you have the information available to you where ever you want from the profilecommon class.
Also please see the attached demo application placed at the end of my blog http://blogs.bootcampedu.com/blog/post/Reply-to-httpstackoverflowcomquestions1672007user-roles-why-not-store-in-session.aspx
Just a suggestion, you might consider using this little library:
http://www.codeproject.com/KB/aspnet/Univar.aspx
It has a server side implementation of the cookie whereby all cookies can be stored on the server while asp.net authentification is used to identify the user. It supports encryption and is also very flexible making it very easy to switch from one storage type to another.

Sharing login-system between classic ASP and ASP.Net

A client uses classic ASP to log in to their web based backoffice.
I have written a new ASP.Net app to be included in the backoffice, and I need to utilize the already existing login-system, so that when they are logged in there, they don't need to log in again in the new ASP.Net app.
Logins and passwords are stored as clear text in a SQL Server db, that I can access from my ASP.Net app.
What would be an effective way to integrate these systems?
My current best idea is:
In the link to my ASP.Net app, I link to a "gateway" login-page with their userid and a hashed password + common secret in the querystring. I then compare this to the password of the user in the database... But the problem is, that if this querystring is intercepted, it can be used to access the asp.net site, without actually knowing the username and password...
I am most likely overlooking something simple.
I think your idea is on the right path.
As you probably already know, classic asp and asp.net cannot share the same session state, so you do need to have a mechanism to log from one into the other.
What I would do is: when someone logs in, create a unique GUID that you save in the database for that user. When you jump from one site to the other, pass that GUID into the query string. When you try to auto-log them into the other site, look up that GUID and see if it's attached to anyone. If it is, log them in.
This way you aren't passing anything that a user could guess or decrypt.
How does the classic ASP system maintain login state? "Piggy-backing" off that would be your best bet, by far.
All classic ASP systems I've worked on have used cookies for tracking authentication information, so just read those and compare against the database that you can access.
As the information is stored in a Classic ASP session, could you add a "redirect page" to the classic ASP side of things that is the "entrance" to the new module, and cause this to write the useful data out as cookies, or trigger a POST to your start page? By using cookies or a POST request, you minimise your worry about having the url "hijacked" allowing someone to get into the ASP.net site without username/password.
You are rightly worried about a MITM type attack, possibly through DNS cache poisoning or similar. Depending on your circumstances, it may be enough to mitigate the potential effects of this by adding a time constraint to the login token that is passed across the application boundaries.
The 'GUID in the database approach' is something I have used successfully myself in the past, both for passing users between two applications sharing the same authentication database, and also for 'password reset email' type scenarios. You could 'expire' this by having an additional column on the record specifying the date at which the GUID was added, and modifying your application code to only log in GUID auths which are less than x minutes / hours / days old.
An alternative could be to avoid additional fields in the database by concatenating something like:
UserId + [Value representing current time to nearest x minute / hour /day] + Salt
.. hashing it, then then duplicating your algorithm on the other application and comparing the two generated values.
In general, I think your proposed solution is appropriate to the problem. It is certainly not too complicated.
Couldn't you submit it via Form and not through the Querystring? That would eliminate the possibility of it being intercepted in the url.
If interception is a serious issue then you need to be running the site over HTTPS. Otherwise using the UserID + Nonce that is then hashed by the password is reasonably strong.
Alternatively you could get the ASP app to add a GUID session cookie once logon has been acheived and store that GUID in a DB table. Your ASP.NET can look up the GUID from the cookie to see if logon has been acheived. If you include the ASP session cookie value in the table you can make reasonably sure that the current ASP session is the same session that was used when the GUID was created.

How to create a database driven login system

I want to create a website that the login system shouldn't be handled by cookies, but on (a) table(s) in the local (on the server) SQL DB.
Is there a way to do it?
Even no partial way?
What and where should I save instead of the cookie???
ASP.NET uses Session cookies by default to track user requests. If you use Cookieless sessions, you will find the Session ID being appended in all requests from the browser. In many scenarios, this could also be unacceptable.
Even if you decide to hit the database and check for a "LoggedIn" flag upon each request, you still need some way to identify the incoming request as belonging to a particular user. This could be in the form of encrypted values in hidden fields, depending on your security scenario. That said, it's not a much better method than the use of cookies, because any data that comes from the client has the potential to have been tampered with.
Personally, I think Cookies are great to track user requests as long as you encrypt them properly.
You still need some way of telling the users apart. If you don't use cookies, then you will have to transfer that information in url or allow only one user from a single ip address (this is really stupid) ... or something else. Cookies are not that bad :-).
Cookieless ASP.NET
If you need help actually implementing the login system you'll need to include more details about your specific problem.
You can store your usernames and so in a database, but you will still need a way to recognize the user as he/she navigates from page to page. That is the cookies role in this, to persist this login token...
It is possible to implement some other ways of handling this token. One can use the URL or somme hidden fields (as ASP.NET's ViewState) to store this token.
So, yes; it can be done. But it takes some work, since you can't use what ASP.NET already provides you. (ASP.NET has builtin-features to handle this token as a cookie, and also store the credentials in the database.)
Use the SqlMembershipProvider.

Resources