Where Microsoft.SharePoint.PowerShell.dll Is

I had this come up with a developer at a client that was trying to build some administrative tooling for their internal development environment. After looking all through the SharePoint environment, I found it actually doesn’t exist anywhere besides the GAC by default. If you need to export it, you can just open a command prompt, navigate to c:\windows\assembly\gac, go into the GAC_64 directory, open the directory for the PowerShell assembly, then run a copy command to your desired directory.

Share

SharePoint Claims Based Authentication Architectures Explained Part 5 SharePoint Identity Across Realms

We have already talked about claims based identity and how to design a claims based application where the issuer is able to authenticate the users directly. You can actually take all of this one step further though. The process allows you to expand the capabilities of your issuer to accept a security token from another issuer. This means the user won’t have to directly authenticate it. Now the issuer is able to issue security tokens and to accept them from other issuers that it trusts.

As a result you will be able to have identity with other realms in spite of the fact that they are separate domains of security. This is a powerful ability that offers plenty of benefits. The process is accomplished by using the IT staff. They get to determine how issuers are going to be configured. You do need to understand these possibilities because they are the entry way to even more features for your application. You won’t have to change your application in any way though. Some of the different possibilities can offer some flexibility for your application design too.

Being able to maintain an identity database doesn’t have to be a difficult task. You can have a simple database that keeps the usernames and passwords that you need to manage in place. However, it is common for users to forget such information frequently. Chances are you have a high level of security in place for your business. Therefore it isn’t acceptable for you to just email those individuals new passwords.

It is very difficult to successfully manage a database for remote users. Lets say that you work for a partner company with a purchasing application. An IT staff make changes to your account as you work in the purchasing department. The IT staff gives you the role of purchaser so you are given permission to use the application. How are people with a different company going to learn about you being transferred to the sales department? What happens if you decide to quit your job for the company?

The changes will need to be found out, but don’t count on the human resources department to send out any type of notification. It should be something that the company you were employed with would need to manage. Storing information for remote users is often looked upon as a liability so keep that in mind. Any data that you store about remote users could turn out to be a liability for your business.

Over the course of time the data stored with a remote user will become old. There are some safe ways that you can expose applications so that a partner business will be able to use them. One of these methods involves decentralizing the process. You won’t have an issuer that authenticates remote users directly. Instead you will set up a trust relationship with an issuer that is part of another company.

Your issuer trusts their issuer to authenticate the users that are in the realm. These employees are satisfied because they don’t need any type of special credentials in order to be able to use your application. They will use the same single sign on ability that they used in their own company. Your application will work for them due to the came pass to get in. The claims you have to get the boarding pass for the remote users will be less powerful though because they aren’t really employees of your company.

It will be the responsibility of your issuer to determine those assignments. Your application won’t need to change either when new organizations are added as partners. This is a huge benefit of using claims because it allows your configuration of only one issuer to be accessed by so many new users out there.

It is possible to use claims to decentralize identity. This is going to eliminate data from becoming stale for remote users. Another benefit is that the claims will allow you to logically be able to store data about your users. The data can be stored with authority and be convenient to access and to use. Through the use of federation, many of the road blocks out there are removed so that new users can come in.

Your company will need to decide which realms to allow access to your claims based application. Your IT staff will be able to set up the relationships that need to be in place for them. They can get employees in a business that use Java to access your application but they won’t need to issue new passwords. They will only need to have a Java based issuer. Also, anyone with a Windows Live ID would be able to use your application.

Share

Free SharePoint Redirection WebPart – Programming SharePoint WebParts With LINQ to Active Directory – Part 1

The real power of LINQ lies in the ambiguity to query collections of all Types, as long as they implement the IQueryable interface. Since Active Directory is essentially a collection of users, one should be able to use a LINQ-esque fashion to manipulate objects out of that particular store as well.

This is where LINQ to AD is awesome! It allows a wrapper to exist around System.DirectoryServices to allow more contemporary, succinct language constructs to be used while developing AD DS integrated tooling. Since I do a lot of security software that exploits AD DS, I wanted to give it a shot!

And it’s pretty impressive. As you can see in the code being explained, there are some quirks, but it’s a pretty cool approach that I believe I am going to use more frequently because I enjoy the layer of abstraction and really, really enjoy being able to use the LINQ code approach.

I have to break this up into two posts because it is exhaustively long. The second post has the download link.

So, for a test project let’s go through building a Redirection WebPart that will satisfy a couple requirements:

  1. Get a reference to the current user
  2. Query into AD DS, find that user, and retrieve the department property
  3. Using the department property, query into a pre-existing SPList, match it, and retrieve a corresponding URL
  4. Redirect the current context to that returned URL

First things first, you have to do download the LINQ to Active Directory project.

Firstly, the appropriate references have to be made, notably to the LINQ to Active Directory project as a referenced project or a compiled assembly. As well, the Active DS Type Library must be referenced so that the IADs interface is exposed. You will see why this is important shortly, but needless to say if not referenced you will get a somewhat cryptic error about an “unspecified error” occurring which is a pain in the ass.

This is what my project structure looks like following:

10-27-2009 1-43-04 PM

As you can see, there are two references out of some pretty orthodox ones being made. The Bds.DirectoryServices.Linq project is referenced, along with the ActiveDs assembly like discussed previously.

The WebPart consists of only two classes. The first one, User, is meant to structure a User object with the properties that should be queried during the AD iterations. For my particular requirement I am only interested in getting the account name and the corresponding department entry. The class and property decorations are provided to specify targets,  DirectoryAttribute for example correlates to the underlying LDAP property to query.

[csharp]

[DirectorySchema(“user”, typeof(IADsUser))]
public class User
{
[DirectoryAttribute(“sAMAccountName”)]
public string AccountName { get; set; }

[DirectoryAttribute(“Department”, DirectoryAttributeType.ActiveDs)]
public string Department { get; set; }
}

[/csharp] 

I am going to throw on some generic properties now into the WebPart class to keep some of the more mutable values dynamic. Just four of them, one a URL string to hyrdate a SPSite object where the SPList exists, a string to represent which SPList to get, a third string to allow the column name to be specified, and a fourth string for the AD DS domain name.

[csharp]

        [Personalizable, WebBrowsable(true),
         WebDescription(“The Url Where The Redirection List Exists”),
         Category(“Global Mode Configuration”),
         WebPartStorage(Storage.Shared),
         DefaultValue(“”),
         WebDisplayName(“URL Of Redirection List Site”)]
        public string Url { get; set; }

        [Personalizable, WebBrowsable(true),
         WebDescription(“Redirection List”),
         Category(“Global Mode Configuration”),
         WebPartStorage(Storage.Shared),
         DefaultValue(“”),
         WebDisplayName(“Redirection List”)]
        public string List { get; set; }

        [Personalizable, WebBrowsable(true),
         WebDescription(“URL List Property”),
         Category(“Global Mode Configuration”),
         WebPartStorage(Storage.Shared),
         DefaultValue(“”),
         WebDisplayName(“Field Name That Contains URL Values”)]
        public string UrlProperty { get; set; }

        [Personalizable, WebBrowsable(true),
         WebDescription(“Active Directory Domain Name To Use”),
         Category(“Global Mode Configuration”),
         WebPartStorage(Storage.Shared),
         DefaultValue(“”),
         WebDisplayName(“AD DS Domain name”)]
        public string DomainName { get; set; }

[/csharp]

Getting the users department from AD using LINQ to Active Directory is a breeze as illustrated in the GetCurrentUserDepartment method below. The _entry global field is a DirectoryEntry object which is intialized OnLoad to the domain string literal specified as a WebPart property (the DomainName auto-property), using some brief string massaging to make it an agreeable DirectoryEntry constructor parameter format-wise.

[csharp]
protected override void OnLoad(EventArgs e)
{
if (!_error)
{
try
{
base.OnLoad(e);
if (!string.IsNullOrEmpty(DomainName))
{
_entry = new DirectoryEntry(string.Format(“LDAP://{0}”, DomainName));
}
else
{
HandleException(new Exception(“Please Set A Domain Name!”));
}
}
catch (Exception ex)
{
HandleException(ex);
}
}
}

[/csharp]

The second SearchScope parameter will specify the tranversal rules for the query, since I want to recur the whole substree I am going to use SearchScope.Subtree.

Following, the current SPContext is going to be used to get a the current SPUser.Login name, which passed into a regular expression to clean it as to match the account name return from Active Directory. An IQueryable<User> collection is built by executing a LINQ Where clause against the previously created DirectorySource object, matching the current SharePoint user to their record in Active Directory. Following, this collection is pushed to a List<User> typed collection using AddRange with the department set off the User.Department property. If no department is returned, it is set to a global string literal that represents a broken (no return) query, used later in conditional statements. Probably should use a String.Compare instead of the equality operator but you get the idea.

[csharp]
private static string GetCurrentUserDepartment()
{
string department = string.Empty;
SPSecurity.RunWithElevatedPrivileges(delegate
{
var usersDs = new DirectorySource(_entry,SearchScope.Subtree);
var cleanUserName = Regex.Replace(SPContext.Current.Web.CurrentUser.LoginName,”.*\\\\(.*)”, “$1”, RegexOptions.None);
IQueryable users = usersDs.Where(usr => usr.AccountName == cleanUserName);
// put in to fix LINQ to AD Bug
var userList = new List();
userList.AddRange(users);
if (userList.Count > 0)
{
User curUser = userList.FirstOrDefault();
department = curUser.Department;
}
else
{
department = _breakStatement;
}
});
return department;
}

[/csharp]

Next Section >> Part II – Building The Remainder Of The WebPart Class

Share