Phone Number not pulled correctly ... and other stuff

Jun 19, 2009 at 5:39 AM

Hey!

First of all .. i'm completely new to aspx, to iis, to c# and to mssql ..

it seems that there is some major issue with the phone number pulling. everytime fillPhone() is called, an exception is beeing thrown, thats caught by this empty catch {} statement you made.... maybe i'm finding out the problem. 

another problem is, that the if clause, that actually retrieves the telephonenumber attribute (if (count > 0)), is never  run. Following the settings you provide, the code is run in the asp net user context (IUSR). Thats why allowedAttributesEffective returns a count of 0 attributes for the retrieved user. These are the attributes that can be modified by the calling user ...  HostingEnvironment.Impersonate() does not do anything by the way. The way to go is by putting the following into the web.config file.

 

 <system.web>
    ...
    <authentication mode="Windows"/>
    <identity impersonate="true"/>
    ...
 </system.web>

see http://msdn.microsoft.com/en-us/library/ms998358.aspx

This runs the web application the whole time in the name of the user, thats logs on through windows authentication. Further the database requests (when not specifying a sql user in the connection string) are also made through this username. the only problem here is to setup delegated trust between the machines (i haven't got this running by now). I got rid of that HostingEnvironment stuff and off you go. There is only this problem with the Exception..... i don't know where to start.

Why are you retrieving allowedAttributesEffective anyway? as i see it, we don't want to modify the ad contents? Shouldn't this be 'allowAttributes'?

 

Some questions:

Wouldn't it be nice if there is no phone number stored in the mssql database?
Is it possible to store the SID in the mssql database instead of the username? Is it possible to get the SID/Domain with some c# functions? Usernames alone are often not enough (steve in two different domains of the same forest)

Bernhard

Coordinator
Jun 19, 2009 at 9:19 AM
Edited Jun 19, 2009 at 9:23 AM

I understand what impersonate does, and in this case, I found that HostingEnvironment.Impersonate() was the correct way to go, it does not 'do nothing'.  I wrote about it here: http://naspinski.net/post/Allowing-users-to-change-their-own-Active-Directory-properties.aspx - it has worked for hundreds of users, maybe it does not work in your specific environment for some reason?

I also used allowedAttributesEffective since it would return a smaller set, either would work.

Keep in mind that I don't claim that my approaches are the best or perfect in any way, just what worked best for me.  If you feel that you can make something work better, by all means, do it; it would be great to see some improvements in the code, that is why it is open-source!

 

As for  your questions:

Wouldn't it be nice if there is no phone number stored in the mssql database?

I had this at first, but people sometimes wanted to be contacted at different numbers that the ones in their AD - you could easily change this if you want.


Is it possible to store the SID in the mssql database instead of the username?

Feel free, I see nothing wrong with that approach.

 

Is it possible to get the SID/Domain with some c# functions? Usernames alone are often not enough (steve in two different domains of the same forest)

I understand your problem, and this is possible - though I don't know off the top of my head as I haven't done AD coding for a long time, this book is infinitely useful when doing such things: http://www.amazon.com/Developers-Directory-Programming-Microsoft-Development/dp/0321350170/ref=sr_1_1?ie=UTF8&s=books&qid=1208318535&sr=8-1

Jun 19, 2009 at 12:21 PM

Hey! Thanks for the quick answer!

I think i was too rude ... i'm sorry for that.

I guess I dont understand the whole impersonation in your program. Can you please give me a overview of the steps with the according permissions/user used? or correct the following please ...

Starting from the point of calling slickticket as a new user, that has a valid account in the AD i understand the user impersonation, as you intendet it to work, as follows (sql server local)

  • Call as User to the page
  • IIS does Windows Integrated authentication (as set in web.config: <authentication mode="Windows"/>)
  • IIS verifies Token (After the "Negotiate" Protocoll there is only a Kerberos Ticket i guess) since Windows INtegrated authentication does not send the password
  • IIS starts aps.net and runs the page as the NetworkService (default)
  • on profile.aspx (profile.aspx.cs) the user logged in through windows authentication is beeing impersonated by HostingEnvironment.Impersonate()
  • The call to the database runs with the users credentials (again: sql LOCAL. On network there is the trust delegation problem with double hop to solve)
  • The phone number is being retrieved
  • The impersonation is being ended and the rest of the script runs as network service.

 

Wouldn't it be nice if there is no phone number stored in the mssql database?

I had this at first, but people sometimes wanted to be contacted at different numbers that the ones in their AD - you could easily change this if you want.

Ok, thats a point. But i personally dont like many different informations on the same topic and i have many colleges in other companies that do also think that way. but you are right. this seems to be a simple topic to change...

 

SID/Domain

I am currently evaluation software like yours. currently yours is the most appropriate for our goal but this would be a tiny problem. if we choose to use your software in production i would definitly like to change that... since its a feature gain for your software and does not destroy currently working versions (storing the sid for future accounts only) i am willing to give it to you if you are interested.

Coordinator
Jun 20, 2009 at 6:24 AM

I think you have how I use the impersonation understood perfectly.

I am very interested in your changes and what you will do with this - please keep me posted.

I hope it works out for you!

Jun 22, 2009 at 7:32 AM
Edited Jun 22, 2009 at 12:05 PM

Ok. So I understood it the way it is supposed to.

It seems to work differently though (at least in our setup). Our requirements are simple: Remote SQL Server (is in the same domain). Since the integrated authentication does not have the users password to pass along to a remote server, it needs trusted delegation between the servers (this is the only thing i am not sure about right now .. but it works). And trusted delegation needs to have an asp.net process that impersonates the user .... as i understand it.

  • Call as User to the page
  • IIS does Windows Integrated authentication (as set in web.config: <authentication mode="Windows"/>)
  • IIS verifies Token (After the "Negotiate" Protocoll there is only a Kerberos Ticket i guess - without Kerberos this is not possible and with kerberos there is the much discussed double hop issue - trusted delegation and co. :) ) since Windows INtegrated authentication does not send the password
  • IIS starts aps.net and runs the page as the NetworkService
  • IIS impersonates as the authenticated user .. from now on EVERYTHING runs as the user that logged in!
  • In profile.aspx (profile.aspx.cs) asp.net impersonates as the original User by HostingEnvironment.Impersonate() (This would be the network service again)
  • The call to the database runs with the "network service" credentials and fails
  • The impersonation is being ended and the rest of the script runs as the user that logged in\

    If i use your original config (that means excluding the asp.net impersonation) it still does NOT work. the HostingEnvironment.Impersonate()  line does nothing but impersonate the network service that it already is ... I do not have anything weird on this IIS Server. This is the only website.

    Can you please test something. Modify your profile.aspx.cs file. Go to the fillPhone() procedure and comment everything within the "using ( HostingEnvironment.Impersonate()  ){ } out. Put in a simple line: strPhone = System.Security.Principal.WindowsIdentity.GetCurrent(true).ToString();

    It looks like this (whitout the comments).

     

    Can you tell me what usename is written to the phone field? And what name is put in if you comment HostingEnvironment.Impersonate() out?

    I think that it would be very interesting for you to use the asp.net impersonation. You do not have to struggle with that database access rights as Machine Account, manual impersonation thing or something like that. Most of the users are having windows authentication in their mssql servers anyway.

     

    protected void fillPhone()
    {
       using (HostingEnvironment.Impersonate())
       {
          strPhone = System.Security.Principal.WindowsIdentity.GetCurrent(true).ToString();
       };
    }
  • Coordinator
    Jun 23, 2009 at 5:11 AM

    i get this error:

    System.NullReferenceException: Object reference not set to an instance of an object.

    Like I described in that post above, I do not completely understand why, but the impersonate is necessary to to the LDAP query.  Also, keep in mind that the fillPhone only calls when a new user is signing up.

    I did delete myself as a new user and checked the fillPhone and it did populate correctly form AD.  Is yours not working?