Anonymous CreateTerm leads to UnauthorizedAccessException and ArgumentNullException

Today is time for new post, new hack inside of SharePoint environment 🙂

Let’s imagine that we want to create new Term inside of specific Term Set within specific Term Store. But we want to create it as anonymous user, because we want to make this functionality available inside of some public page without login needs.

We could make this possible with code which runs inside of RunWithElevatedPrivileges scope. But creating term process differs from other creating processes inside of SharePoint (list item creation, file upload etc.).

Let’s take a look to this topic.

We could simply add our CreateTerm() code into RunWithElevatedPrivileges scope like example below:

SPSecurity.RunWithElevatedPrivileges(delegate ()
{
	using (SPSite site = new SPSite(rootUrl))
	{
		TaxonomySession taxonomySession = new TaxonomySession(site);
		TermStore termStore = taxonomySession.DefaultSiteCollectionTermStore;

		Group group = termStore.Groups["Session Group"];
		TermSet termSet = group.TermSets["Speakers Termset"];

		Term term1;

		var cTerm = termSet.Terms.Where(s => s.Name == termFullName);
		if (cTerm.Count() > 0)
			term1 = termSet.Terms[termFullName];
		else
			term1 = termSet.CreateTerm(termFullName, 1033, Guid.NewGuid());

		termStore.CommitAll();
	}   
});

In that case you get UnauthorizedAccessException error:

In that case you could set Submission Policy on Term Set to Open.

But that is not solution if you have anonymous access. After that you get ArgumentNullException error:

But why? The reason is in get_CurrentUserName() function which is called in CreateTerm() function.

If you go deeply into get_CurrentUserName() function you could see that it checks HttpContext.Current.User but there is no user information if we go anonymous.

So we could do here a little hack in a way that we have to clear all datas from HttpContext.Current. In that case get_CurrentUserName() function go around and check user from WindowsIdentity.GetCurrent().

So, solution is here:

HttpContext oldContext = null;
string termFullName = Name + " " + LastName;

try
{
	oldContext = HttpContext.Current;
	HttpContext.Current = null;
	SPSecurity.RunWithElevatedPrivileges(delegate ()
	{
		using (SPSite site = new SPSite(rootUrl))
		{
			TaxonomySession taxonomySession = new TaxonomySession(site);
			TermStore termStore = taxonomySession.DefaultSiteCollectionTermStore;

			Group group = termStore.Groups["Session Group"];
			TermSet termSet = group.TermSets["Speakers Termset"];

			Term term1;

			var cTerm = termSet.Terms.Where(s => s.Name == termFullName);
			if (cTerm.Count() > 0)
				term1 = termSet.Terms[termFullName];
			else
				term1 = termSet.CreateTerm(termFullName, 1033, Guid.NewGuid());

			termStore.CommitAll();
		}   
	});
}
catch (Exception _ex)
{
	Logger.ToLog(_ex, "Error SpeakerSubmission_SaveItem CreateTerm");

	serviceResult = ServiceResult<bool>.Error(_ex.Message);
	return serviceResult;
}
finally
{
	HttpContext.Current = oldContext;
}

Happy hacking folks!

Cheers!
Gašper Rupnik

{End.}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Powered by WordPress.com.

Up ↑

%d bloggers like this: