Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Impersonation, Active Directory, and "user does not have authority to xxxx" issues

I have 2 ASP.NET MVC 3 applications. I am using impersonation via the web.config to allow me to query Active Directory to get details on the user. The application uses Windows authentication and does not allow anonymous users. One application is the primary application where the user performs their tasks. The other allows the user to set up other user's to look like them in application one.

The test user's are getting the following error:

SQL1092N  "<DOMAIN ID>" does not have the authority to perform the requested command.

This happens after I send a web request from my primary application to the secondary one. To get that working I had to make the request impersonate the actual user and not the identity the application uses for impersonation. This is actually an SO question I posted and had answered. That's here: How do I call an MVC Action via a WebRequest and validate the request through Active Directory?

At the end of that code, I call:

impersonationContext.Undo();

It is after this web request takes place, that the primary application tries accessing the database and now it seems that the above call has undone the impersonation of the application, so the user's attempt to do anything that opens a database connection fails. At least, that's my working theory after a day of head bashing.

My question is, how can I get the impersonation of the application to revert back to the user in the web.config? Or, when making my web request, is there a way to ensure the impersonation context only applies to that request?

The whole point of all of this is that the second application has its own sql server database. The primary application uses DB2. I would like to write the database access code once, but use it in both applications. Currently that's what I've done, but my method of relying on the web request to get the data may not be the best approach.

I'm open to any thoughts, comments, suggestions, and/or criticism. How should I go about handling this?

like image 672
jason Avatar asked Nov 12 '22 12:11

jason


1 Answers

Okay...my theory that the IPrincipal context was changed when making the web request proved accurate, which made this fix extremely easy. Best part is, I can keep using the api I built to make this request without duplicating the Sql Server Entity Framework parts.

I have the following call to my api library:

            proxyRequestResultDetails = ProxyApiWrapper.GetProxies(
                adUserInfo.AssociateId,
                context.User);

This code is being called by an authorization filter attribute. The method prototype looks like

public void OnAuthorization(AuthorizationContext filterContext)     

Internally, the call makes the GetProxies method following call:

        public static StreamReader GetWebRequestStream(
             string url,
             string contentType,
             bool useDefaultCredentials,
             IPrincipal user)
        {

            var impersonationContext = ((WindowsIdentity)user.Identity).Impersonate();            
            var request = WebRequest.Create(url);

            try
            {
                request.ContentType = contentType;
                //request.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
                //request.UseDefaultCredentials = useDefaultCredentials;            
                //IWebProxy p = new WebProxy();
                //request.Proxy = p.
                request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;
                request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
                var response = (HttpWebResponse)request.GetResponse();
                return new StreamReader(response.GetResponseStream());
            }
            catch (Exception e)
            {
                impersonationContext.Undo();
                throw e;
            }
            finally
            {
                impersonationContext.Undo();
            }

        }

When the calling method returns, the identity of user is no longer that of the one set for the application to impersonate. The fix is pretty simple:

            //Track current identity before proxy call
            IPrincipal user = context.User;
            proxyRequestResultDetails = ProxyApiWrapper.GetProxies(
                adUserInfo.AssociateId,
                context.User);

            //Undo any impersonating done in the GetProxies call
            context.User = user;    

2 lines of code resolved 12 hours of head ache. It could have been worse. Anyhow. Thanks for being a sounding board. I tried having this conversion with the duck, but the duck got confused.

like image 186
jason Avatar answered Nov 15 '22 04:11

jason