Tuesday 22 September 2015

Impersonation of Web Users in ASP.NET/SharePoint 2013 without a password

There seemed to be a lack of samples available to demonstrate how Windows impersonation can be done within the context of a web application (such as SharePoint 2013 or ASP.NET). Most of the examples use the "LogonUser" Windows API call to get a user token. e.g. https://msdn.microsoft.com/en-us/library/chf6fbt4.aspx. However - that call requires a password to work. You don't really want all your user passwords to have to sit in a secure store to enable impersonation!

In my scenario, I had to write to a file through an existing COM Component via a .NET COM Interop library. It depended on the write operation being done from the context of a valid user - otherwise the file wouldn't be stamped correctly with author metadata.

To do this, I had to use an overload of the WindowsIdentity constructor which accepts a UPN (User Principal Name). From there, you can impersonate users within your code at will.

NOTE: the account that is doing the impersonation (e.g. svcSP) will need to have the "Act as Part of the Operating System" right as defined in your Local User Policy for this to work.

Code Sample:


void Main()
{
 var userName = "LOCALDEV\\david.klein";
 PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

 var user = UserPrincipal.FindByIdentity(ctx, userName);

 if (user != null)
 {
 var upn = user.UserPrincipalName;
 Debug.Print(upn); 
 WindowsIdentity id = new WindowsIdentity(upn);
 WindowsImpersonationContext wic = id.Impersonate();    
 try
  {
   // Do what you need here under the impersonation context.
   var currentId = WindowsIdentity.GetCurrent().Name; 
   Debug.Print(currentId);
  }
  finally
  {
   wic.Undo();
  }
 }
}

Monday 20 April 2015

Microsoft Team Foundation Server 2013 Update - Error When Installing - "SQL Server Reporting Services is configured to require a secure connection."

You may get the following exception when upgrading to Team Foundation Server 2013 (TFS 2013) or update packages - when you are using self-signed certificates or your SQL Report server runs unsecured (not using SSL):

TF255455: SQL Server Reporting Services is configured to require a secure connection. However, no HTTPS URL is configured with a valid certificate. Use the Reporting Services Configuration Manager to configure or remove HTTPS support. For more information see http://go.microsoft.com/fwlink/?LinkId=179982


To resolve this issue (without getting valid certificates or securing your site), you can go to your Microsoft SQL Server Reporting Services (SSRS) folder and find the rsreportserver.config  file. This is typically in:

C:\Program Files\Microsoft SQL Server\MSRSXX.<ServerInstance>\Reporting Services\ReportServer\rsreportserver.config             

Update the "SecureConnectionLevel" from 2 to 0 - and you will be able to run the update. Change it back after the update has completed.



DDK

Friday 23 January 2015

How can I easily have different app.config files for different build configurations in MSBUILD?

There are a few different proposed solutions I have seen suggested, some including recommendations involving 3rd party tools and Visual Studio Transformation Extensions. The following is the simplest method I have found. It involves a violation of the DRY principle (Don't Repeat Yourself) as the app.config files are duplicated (due to the lack of transforms) - but I considered this to be a small sacrifice based on the simplicity of the solution.

Steps:
1) Unload your Project file (csproj) file in Visual Studio and Right click and select "Edit {My Project Name}.csproj" on that same file to edit it.
2) Add a folder for each MSBUILD configuration that you want and put your different App.Config files in those subfolders e.g. \Release\App.config and \Debug\App.Config
2) Find the section in your csproj project file <None Include="App.config" /> and replace it with the following conditional Include statements for each of your MSBUILD configurations:
<None Condition=" '$(Configuration)' == 'Debug' " Include="Debug\App.config" />
<None Condition=" '$(Configuration)' == 'Release' " Include="Release\App.config" />

When you build, it will use either of the application configuration files that you have created and put them in the relevant build configuration output directory.

DDK