Search code examples
asp.netsql-serverconnection-stringimpersonation

Losing my App Pool Identity after first async query


I've got a .NET API running on IIS 7.5. The API is running in an Application Pool that uses an Active Directory domain account, for authentication against the SQL database (hosted on a different server).

The credentials for the App Pool identity work for some of my queries, but others are returning the following error:

The underlying provider failed on Open.

The inner exception is:

Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.

It seems that I'm losing my App Pool identity credentials, but I don't understand why.

An example of where it succeeds, and then fails, can be seen in this call within my API GET:

   using (FtpJobsContext db = new FtpJobsContext())
        {
            Job job = await db.Jobs.FindAsync(guidJobId);
            if (job != null)
            {
                JobDetailAPIModel result = await GetDetails(db, job, NUMBER_OF_EXECUTIONS);
                return Ok(result);
            }
            else
            {
                return NotFound();
            }
        }

The FindAsync call on db.jobs works fine. The connection is made, and the appropriate job is retrieved.

However, it seems that the db connection changes to anonymous when I pass the DbContext to the private method.

The definition for GetDetails is similar to:

private async Task<JobDetailAPIModel> GetDetails(FtpJobsContext db, Job job, int executionNumber)
        {
            JobDetailAPIModel result = new JobDetailAPIModel();

            ICollection<JobScheduleAPIModel> schedules = new Collection<JobScheduleAPIModel>();
            foreach (JobSchedule sched in job.JobSchedules)
            {
                schedules.Add(new JobScheduleAPIModel(sched));
            }
            result.JobSchedules = schedules;
            ICollection<SSISPackageSummaryAPIModel> packages = new Collection<SSISPackageSummaryAPIModel>();
            foreach (SSISPackage pack in job.SSISPackages)
            {
                packages.Add(new SSISPackageSummaryAPIModel(pack));
            }
            result.SSISPackages = packages;
            ICollection<ExecutionAPIModel> executions = await (from e in db.View_Executions
                                                  join p in db.SSISPackages on e.SSISPackageId equals p.SSISPackageId
                                                  join j in db.Jobs on p.JobId equals j.JobId
                                                  where p.JobId == job.JobId
                                                  orderby e.StartTime descending
                                                  select new ExecutionAPIModel
                                                  {
                                                      ExecutionId = e.ExecutionId,
                                                      PackageDisplayName = e.PackageDisplayName,
                                                      Status = e.Status,
                                                      StartTime = e.StartTime,
                                                      EndTime = e.EndTime,
                                                      Duration = e.Duration
                                                  }).Take(executionNumber).ToListAsync();
            result.LatestExecutions = executions;
            return result;
        }

My connection string from Web.Config looks like this:

<add name="{name}" providerName="System.Data.SqlClient" connectionString="Data Source={serverName};Initial Catalog={dbName};Integrated Security=SSPI;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Encrypt=False;TrustServerCertificate=True" />

Solution

  • I found the answer as I was composing the question, but figured I'd share it anyway, in case others ran into similar issues.

    The problem is my connection string. Pooling=False forces subsequent connections within the Using statement to lose the credentials and revert to anonymous.

    Changing the connection string to Pooling=True fixes the issue.