Wednesday, February 24, 2016

CAC, PIV, ADFS, LDAP oh my!





Challenge:

Needed an web application to authenticate against Active Directory on premises.  I need to know how to wire up a web application to AD.  Then I need to understand how to read those claims back on the web application I had designed.

Solution:

Went with the solution suggested by Vittorio over on his blog.  We have an on prem AD server which will be sufficient for our needs.  The guide he wrote was straight forward and worked.  The only issues I had was I need to coordinate with our AD team.  Once they understood, they set up the AD Relying Party Trusts between my app and our AD server. 

We chose to use the MVC 5 templates in VS 2013.  The wizard allows you to choose from 4 types of authentication.  
 
I did look at the LDAP option.  It would work but would require a username and password in the call too
 
DirectoryEntry de = new DirectoryEntry ("LDAP://novellBox.sample.com","admin","password",AuthenticationTypes.None);

This is not something I want to be embedding in the code.  I much prefer the using System.DirectoryServices.AccountManagement.  Then all you need is PrincipalContext. 

Source:

  1. http://www.cloudidentity.com/blog/2014/02/12/use-the-on-premises-organizational-authentication-option-adfs-with-asp-net-in-visual-studio-2013/
  2. https://msdn.microsoft.com/en-us/library/ff649227.aspx (Dated but still lots of goodness)
  3. http://forums.asp.net/t/1356598.aspx (DOD guys asking questions)
  4. http://stackoverflow.com/questions/1437250/connecting-to-ldap-from-c-sharp-using-directoryservices  
  5. https://msdn.microsoft.com/en-us/library/87tye19w(v=vs.110).aspx (DirectoryEntry)
  6. http://goodworkaround.com/node/68(Web Forms)
  7. http://www.schiffhauer.com/mvc-5-and-active-directory-authentication/(MVC 5)
  8. https://github.com/aspnet/Identity/issues/387 (MVC 5 and AD)






Attempted to access an unloaded appdomain. (Exception from HRESULT: 0x80131014)

Problem:

Using MVC 5 application and the namespace System.DirectoryServices.AccountManagement.
I kept getting this error intermittently running my app.  Looks like an issue in ADSI which is a bit buggy. 

Solution:

Tofumaster's suggestion of adding the domain string to the principal context seems to have done the trick for me. 

instead of

PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

do this

PrincipalContext ctx = new PrincipalContext(ContextType.Domain,"MyDomain");



Source:

  1. http://stackoverflow.com/questions/6605666/querying-active-directory-from-mvc-result-in-attempted-to-access-an-unloaded-ap
  2. http://forums.asp.net/t/1697428.aspx?Querying+Active+Directory+from+MVC+result+in+Attempted+to+access+an+unloaded+appdomain+Exception+from+HRESULT+0x80131014+
  3. http://stackoverflow.com/questions/5895128/attempted-to-access-an-unloaded-appdomain-when-using-system-directoryservices

Wednesday, February 17, 2016

C# Argument Out of Range DateTime

Problem:

Had a customer contact about 3rd party solution running on our IIS server.  Customer support for software was expired and they were desperate for help.  I looked at the issue which was when the web page (asp.net) loaded user received an argument out of range error.  The page had been working previously.  The error listed the issue as no date time supported for hours, minutes, seconds constructor error.

Solution:

I took a look at the code behind and found the following constructor

var endTime = new DateTime(today.Year, today.Month, today.Day, 8 + course.LengthInHours, 0, 0).ToLocalTime(timeZone);

The declaration looks syntactically correct.  The error message made me key in on the last 3 fields, hours, minutes and seconds.  I typically don't go to that level of detail when using the DateTime namespace.  But this developer had done it so I took all a look at the MSDN site for the DateTime constructor (https://msdn.microsoft.com/en-us/library/272ba130%28v=vs.110%29.aspx)

It became pretty obvious where the issue was the hour declaration was a calculated time 8 plus some value stored in a database.  I ran the test and sure enough the error condition had an hour count of 32 (24+8).   This definitely was the issue as API says:

hour
Type: System.Int32 - The hours (0 through 23).
The error was due to the value in the object being larger than 24.  The developer had assumed that the value would always be a number under 24.  The new solution which fixes the error uses the AddHours method vice trying to initialize the DateTime in the constructor.

 var tempEndTime = DateTime.Today;
 //Default is 12 AM each day.  Add 8 hours to get to the start of the workday 8 AM.
 tempEndTime = tempEndTime.AddHours(8);
 //Now add the length of the class to estimate end time of class
 if(course.LengthInHours>0)
     tempEndTime = tempEndTime.AddHours(course.LengthInHours);
 var endTime = tempEndTime.ToLocalTime(timeZone);


Wednesday, February 10, 2016

SQL table count in your schema

Needed to get a count on a database that I am reviewing.  This query really helped.


use YourInstanceName

select TABLE_NAME from INFORMATION_SCHEMA.TABLES
where TABLE_TYPE = 'BASE TABLE'
and TABLE_NAME not like '$Foo%'
order by TABLE_NAME

LINQ to SQL equivalent of select top


Problem

I wanted to get the top 10 rows from a linq query.  I was not sure what the LINQ syntax was.

Solution


var q = from m in MyTable.Take(10)  
select m

or 


if you'd like to get the items from 30 to 60
 
var foo = (From t In MyTable Select t.Foo).Skip(30).Take(30);