This project has moved and is read-only. For the latest updates, please go here.

Active Directory security setup

Dec 19, 2014 at 2:38 PM
Edited Dec 19, 2014 at 2:43 PM
I know this has been asked, but some pieces are missing from the various answers. So, I'm hoping to get help with details and all the steps included.

I took the existing db and moved it to the db server. I copied the ADWeb.config file and made it the web.config file and adjusted it accordingly.

Environment: Windows server 2008 R2 IIS 7.5 with Windows authentication setup. SQL Serve 2008 R2 has the db.
Web site: ticketdesk.domain.local is function and gets to the home page. When clicking on "new ticket", I do get a login screen as well.

TicketDesk 2.1

My AD setup domain: domain.local
AD user I am using: domain.local\users\administrator
AD user password: Password123

I have a OU under domain.local called TicketDesk. In there I have 3 security groups called admin, staff, and submit. That AD admin user is added to all 3 groups. I have the 3 roles link as well.

Actual config section from web.config:
<add key="ActiveDirectoryDomain" value="domain.local"/>
<add key="ActiveDirectoryUser" value="domain.local\users\administrator"/>
<add key="ActiveDirectoryUserPassword" value="Password123"/>

<add key="TicketSubmittersRoleName" value="domain.local\ticketdesk\submit"/>
<add key="HelpDeskStaffRoleName" value="domain.local\ticketdesk\staff"/>
<add key="AdministrativeRoleName" value="domain.local\ticketdesk\admin"/>

<add key="SecurityMode" value="AD" />
<add key="ClientValidationEnabled" value="false" />
<add key="UnobtrusiveJavaScriptEnabled" value="false" />

No matter what I do or how long I wait for the first "trip" to the site, the AD User tables never get set in the DB. I know the DB is at least reading correctly because I manually changed some settings in the DB and the site adjusted.

What am I missing?
Dec 19, 2014 at 3:16 PM
Found it ... confusing in the instructions .... I will change the default domain name to make it stand out a little better.

You do not need to specify the actual OU location for the roles ... just the name of them.

<add key="ActiveDirectoryDomain" value="mysite.local"/>
<add key="ActiveDirectoryUser" value="mysite\Administrator"/>
<add key="ActiveDirectoryUserPassword" value="Password123"/>

<add key="TicketSubmittersRoleName" value="mysite\Submit"/>
<add key="HelpDeskStaffRoleName" value="mysite\Staff"/>
<add key="AdministrativeRoleName" value="mysite\Admin"/>

<add key="SecurityMode" value="AD" />
<add key="ClientValidationEnabled" value="false" />
<add key="UnobtrusiveJavaScriptEnabled" value="false" />
Dec 19, 2014 at 3:42 PM
Ok - not so fast ... I have things setup and working now - except the actual login part. I see the AD table is populated now and I can enter an appropriate user in the login box. But, now it gives an error of "Value: Null" ...

Oh - and I did have to add the OU in the role fields:
<add key="TicketSubmittersRoleName" value="mysite\TicketDesk\Submit"/>
<add key="HelpDeskStaffRoleName" value="mysite\TicketDesk\Staff"/>
<add key="AdministrativeRoleName" value="mysite\TicketDesk\Admin"/>

Now what?

Server Error in '/' Application.
Value cannot be null.
Parameter name: value
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentNullException: Value cannot be null.
Parameter name: value

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[ArgumentNullException: Value cannot be null.
Parameter name: value]
System.Runtime.Caching.MemoryCacheEntry..ctor(String key, Object value, DateTimeOffset absExp, TimeSpan slidingExp, CacheItemPriority priority, Collection1 dependencies, CacheEntryRemovedCallback removedCallback, MemoryCache cache) +89042
System.Runtime.Caching.MemoryCache.AddOrGetExistingInternal(String key, Object value, CacheItemPolicy policy) +771
System.Runtime.Caching.ObjectCache.Add(String key, Object value, CacheItemPolicy policy, String regionName) +25
TicketDesk.Domain.Services.AdSecurityCacheService.SetCache(ObjectCache cache, String key, Object value, CacheItemPolicy policy) +49
TicketDesk.Domain.Services.AdSecurityCacheService.GetRoleMembers(String groupName) +491
TicketDesk.Domain.Repositories.AdSecurityRepository.IsUserInRoleName(String userName, String roleName) +61
TicketDesk.Domain.Services.UserSettingsService.VerifyDefaultTicketCenterLists(UserDisplayPreferences preferences) +341
TicketDesk.Domain.Services.UserSettingsService.GetDisplayPreferences() +43
1 page, String listName) +89
lambda_method(Closure , ControllerBase , Object[] ) +173
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +274
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
2 parameters) +39
System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +120
System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +452
System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +452
System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult) +15
System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +33
System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +240
System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +28
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
Dec 19, 2014 at 5:42 PM
First, let me start by pointing out that AD is a very customizable data store. It is also exceedingly difficult to write generic code that can successfully query AD in every possible configuration without having extensive foreknowledge of what those custom structures look like. This is one of the biggest drawbacks to LDAP, and probably the most frustrating as well. This is also why so few pre-packaged software systems integrate with AD directly. It is also the reason that future versions of TicketDesk, starting with TD 2.5, will no longer support direct integration with AD. Instead, you will need an intermediary like ADFS or IdentityServer... which solve this problem by normalizing query and result formats, while providing the means to let admins map between their particular internal AD structure, and the standardized formats used externally.

I can not guarantee that TicketDesk can correctly query AD correctly in all possible configurations. TicketDesk can usually query most default AD environments --ones that do not use custom OUs, for example. It might be able to query some AD setups that deviate from the standard defaults, but I didn't put much testing into that since there is almost an infinite number of possible issues to account for.

In order to test if TicketDesk works with the specific configuration you describe, you would have to debug and test against an AD server setup the way you describe (be it your production AD, or a test AD setup similarly. If TD can't query it using the code as it is now, then you could probably customize the security repository to correctly account for the custom OUs, but, those customization would only work for environments very similar to your own, and would break in other configurations.

I would recommend that you start by seeing if you can get it working with top-level user groups that are not part of a custom OU. That would prove that it works. Then, if you really wanted to handle custom OUs you could experiment with settings to see if you can get that to work, and if not you could then dive into the code to see why not.

Second, I want to clarify that the purpose of querying AD and caching some of the data locally in the SQL database has nothing to do with login or permission checks. The actual security stuff is done through the standard windows security providers, and doesn't make any use of the AD data cached in the SQL database. The cached AD data is used only to provide valid email addresses for each user, and to build the dropdown lists for selecting a user (filters in ticketcenter, and owner/assignTo fields in the ticket editor). This is information that you cannot obtain from the standard security providers that ship with the only way to get it is to query AD directly... again, this is the main reason most systems don't attempt AD integration.

To be honest, I wish I hadn't ever done it myself. It's nice that TD can integrate with AD, but it probably wasn't worth the sheer number of hours I've spent beating my head against AD's insanely obtuse design... that that was just to get it working with "most" standard AD setups.
Dec 19, 2014 at 5:44 PM
Edited Dec 19, 2014 at 5:56 PM
Thank you Stephen - I completely understand.

"I would recommend that you start by seeing if you can get it working with top-level user groups that are not part of a custom OU. That would prove that it works. Then, if you really wanted to handle custom OUs you could experiment with settings to see if you can get that to work, and if not you could then dive into the code to see why not. "
  • you mean put the security groups at the root of the domain or at least in the default "Users" OU?
Dec 19, 2014 at 6:01 PM
Yup, that's exactly right.
Dec 19, 2014 at 6:25 PM
Ok - getting closer ... I can actually get a login prompt for my AD user. I can log in and get to the ticketcenter, etc. Now, when I click on "Administration", it asks me for another login and no matter what I put, I can't get in.
Dec 20, 2014 at 5:27 AM
In web.config, find the section below system.web called <location path="Admin">. Make sure the authorization settings there are correct for your configuration.
Dec 22, 2014 at 1:02 PM
Right now the setting looks like this:
<allow roles="domain\ticketdeskadmin" />

In the actual userroles table, the roles are:
Administrators, Helpdesk, TicketSubmitters

I've never set roles for AD before so I've never had to include the "domain" part. Normally, I would set this as:
<allow roles="Administrators" />

What should it be set like?
Dec 22, 2014 at 1:21 PM
Aaaaahhhhhhhhhaaaaaaa - got it!

The local admin roles section needs to be set to the same security group setting that is set for the ad administrativerole name like so:
from app setting:
<add key="AdministrativeRoleName" value="mysite\Admin"/>

update the roles section to:
<allow roles="mysite\Admin" />

Might want to update the documentation on this part to include the role setting.