views:

306

answers:

7

My website has forms authentication, and all is well. Now I want to create a subdirectory and have it also password-protected, but! I need the subdirectory to use a completely different set of logins/passwords than the whole website uses.

Say, for example, I have users for the website stored in the "Users" table in a database. But for the subdirectory, I want the users to be taken from the "SubdirUsers" table. Which probably has a completely different structure.

Consequently, I need the logins to be completely parallel, as in:

  1. Logging into the whole website does not make you logged into the subdirectory as well
  2. Clicking "logout" on the whole website does not nullify your login in the subdirectory
  3. And vice versa

I do not want to create a separate virtual application for the subdirectory, because I want to share all libraries, user controls, as well as application state and cache. In other words, it has to be the same application.

I also do not want to just add a flag to the "Users" table indicating whether this is a whole website user or the subdirectory user. User lists have to come from different sources.

For now, the only option that I see is to roll my own Forms Auth for the subdirectory.

Anybody can propose a better alternative?

A: 

You will simply not be able to achieve this with FormsAuthentication only.

This problem scenario is perfect candidate for using HttpModules. HttpModules can intercept the Request and Response pipeline. You will need to write 2 HttpModules.

  1. HttpModule for Authentication
  2. HttpModule for Authorization

You can merge these modules into one later once your solution reaches in stable state and you are fairly able to manage the complexity.

In your solution, you will need to have a database mechanism that stores the subdirectory and user authorization and authentication mapping data. Your HttpModules can read these data take decision about the Requesting user.

You can start from here.

this. __curious_geek
I did mention in the question that "the only option I can see is to roll my own Forms Auth for the subdirectory". But the question was if there were any better alternatives.
Fyodor Soikin
+1  A: 

I think you can use this code to validate user with any provider

if (Membership.Providers["myprovider"].ValidateUser("USER", "PWD")) {

  //your code

}
Hameds
I fail to see how exactly this code can help me. Am I missing something?
Fyodor Soikin
The code helps you to use multiple provider authentication in asp.net
Hameds
Actually all you need to do is to implement two membership provider, then you can use code above to authenticate users
Hameds
+1  A: 

You can have a separate web.config file in the subfolder that includes only the validiation settings for that subfolder. Note that you must remove all the other settings, as there are some settings that can only be on application level.

<authorization configSource="alterativeSource.xml"/>
awe
You cannot use <authentication> tag in a web.config that is not on application level.
Fyodor Soikin
But you can use `<authorization>` tag, which is the one for defining users.
awe
So? How does that help me?
Fyodor Soikin
Sorry, I meant `<authorization>`. See my updated answer. I don't know if this can keep 2 login sessions active, but it enables you to have separate users for the subdirectory.
awe
A: 

I could see a better answer if your users were in the web.config file, but since you're using users in a database you're pretty much going to have to use something besides forms Authentication. You'll need to set the sub directory to allow any users and then basically rebuild forms Authentication with sessions. You could make a sub class of the page class and use it to hold your all your routines to authenticate and redirect. Then you won't need to add anything to every page in the sub directory.

I know this is the answer you were probably hoping to avoid but forms Authentication is too simple a solution for this kind of complicated situation.

Peter
Yes, you are right, I want to avoid reinventing Forms Auth, and I clearly stated that in the question.
Fyodor Soikin
A: 

Usually "authorization" is used after login to determine which directories, resources, etc can be used by the given user.

Have you looked at creating a role for the "main" directory and a second role for the "sub" directory and then applying the authorization tag (i.e. in the web.config)? You will need to implement an authorization provider, but that sounds like it might be a better long term solution than having multiple user tables.

Clarification Regardless of authorization (i.e. credential check or password, etc) you would still need to define the user roles somewhere, so for the sake of argument lets assume a "user table". (Nothing stops this from being an XML file in isolated storage if you wish.) NB It doesn't actually matter that the users come from different sources. This should be reflected in the schema for the user table (i.e. a flag or another column, etc). If you fight this common pattern you will likely end up doing more work in the long run.

When there is one exception, there is likely to be another in the future....

Jennifer Zouak
I think I was pretty clear in the question that the users MUST come from different sources. I only gave database as an example. In reality, it could be Active Directory, or a hardcoded list of users, or a list embedded into web.config... And so on. I need a solution where USERS COME FROM DIFFERENT SOURCES. That's all.
Fyodor Soikin
If you need to keep this as 1 app, I think you only have one option. This doesn't change my answer. Note that your custom authorization module can authenticate the users according to any logic you wish, i.e. using different sources. You could base that upon the incoming request Url ... to figure out what source to use. Afterward, you just need to prevent the user from using pages to which they are not authorized, thus you would also need custom authorization module.
Jennifer Zouak
What you are describing now is exactly the "roll my own" solution, which, as I stated in the question, I do see myself and want to avoid.
Fyodor Soikin
I think you will have to compromise on 1 of your requirements, but let us know if you find something else and good luck. :)
Jennifer Zouak
A: 

This can help you - numina.codeplex.com

rushonerok
That you for the pointer, I will try look into this.
Fyodor Soikin
A: 

I've not tried this but I think it would work.

You can have two membership providers (i.e., ASPNETDB_1 and ASPNETDB_2.)

These are specified in the membership provider section of the web.config. So you need a separate web.config in each subdirectory, which I know you can do.

In the root of the site I guess you would not have forms authentication. You could have just a start page that asks the user to choose which subdirectory (or you can just use subdomains (firstdir.mysite.com, secondir.mysite.com) or http:/mysite.com/firstdirectory or http:/mysite.com/secondirectory.

I am not sure of the advantage of this method over virtual directories, though, except that the root can contain some ASP programs that don't require authentication.

I understand you are looking for an "out of the box" solution and don't want to "roll your own". However;the standard membership provider does allow you to establish a profile for each user -- then it is really easy to setup one user maintenance form with a listview for each of your separate users maintenance functions and filter by role or by profile value (e.g., organizational ID). Using the membership provider classes, I personally found this very easy to do out of the box (maybe an hour of creating maintenane forms if that using all drag/drop controls, SqlDatasource + listview -- no VB or C coding required). But, separate providers and webconfigs would do the trick as well.

pghcpa
This looks very close to what I'm looking for. I will look into it. Thank you very much.
Fyodor Soikin