So, you want to delete users with the Azure AD Graph API? Good luck with that!

You might think that deleting users using the Azure AD Graph API would be pretty straightforward right?  You already have a registered application that succeeds in updating and creating new users.  This link doesn’t provide any warnings about hidden dragons or secret pitfalls.

Rest assured, there is at least one gotcha that’s primed to eat your lunch when it comes to deleting users.  Fortunately for you, True Believers, I’m here to show you how you too can quickly overcome this less than obvious configuration issue.

According the the Azure AD Graph Reference deleting user the is a simple operation.  All you have to do is send the HTTP Verb “DELETE” to the URL of the user you want to delete.


The user_id can be the UserPrincipalName. In other words, the E-mail address of the user.

As an example, I will delete a pesky AD user named “John Doe”.  This John Doe character has got to go!


I use PostMan to to get my API calls properly formatted.  It also helps to ferret out problems with permissions or configurations. This helps me to *know* that it works before I write my first line of application code.

Note: Notice that I have an OAuth Bearer token specified in the header.  I won’t cover how I got this token in this post.  If you want to know more about how I acquire tokens for Console Applications send me an E-mail!


Assuming you have your tenant ID, user ID, and OAuth token all set correctly then all you need to do is click “Send”.  Your user is deleted as expected… right?

NOPE! you encounter the following JSON error response:

“odata.error”: {
“code”: “Authorization_RequestDenied”,
“message”: {
“lang”: “en”,
“value”: “Insufficient privileges to complete the operation.”

Your first reaction may be verify that your application registration is assigned the proper permissions on the AD Graph.  However, there is no permission that allows you to delete. You can only get variations of Reading and Writing.


What do you do?  If you Google Bing around a bit you will find that your Application needs to be assigned an administrative role in Azure. It needs a ServicePrincipal.  So, off you go searching the competing, overlapping, portals of Azure trying to figure out how to assign an application roles within a resource.  You may even be successful.  We weren’t.

I had to use remote PowerShell to add my application to the appropriate role in order to delete users from AD.


I used instructions from this MSDN article to download and install the Azure AD Module.  First I downloaded the Microsoft Online Services Sign-In Assistant for IT Professionals RTW.  Next, I grabbed the Active Directory Module for Windows PowerShell (64-bit version).  Once I had my PowerShell environment up and running, I cobbled together a quick script to Add my Application registration to the “User Account Administration” role.  Here is how I did it!


# Log me into my MSDN tenant using an account I set up as “global admin”.
$tenantUser = ‘’
$tenantPass = convertto-securestring ‘Hawa5835!’ -asplaintext -force
$tenantCreds = new-object -typename System.Management.Automation.PSCredential -argumentlist $tenantUser, $tenantPass

Connect-MsolService -Credential $tenantCreds

# Get the Object ID of the application I want to add as a SPN.
$displayName = “MyAppRegistrationName”
$objectId = (Get-MsolServicePrincipal -SearchString $displayName).ObjectId

# Set the Role name and the Add the Application as a member of the Role.
$roleName = “User Account Administrator”
Add-MsolRoleMember -RoleName $roleName -RoleMemberType ServicePrincipal -RoleMemberObjectId $objectId


If you execute the PowerShell above (and it’s successful) then you can attempt to invoke the API again.  Click Send!


Notice this time PostMan returns an HTTP status of 204 (no content).  This is the appropriate response for a DELETE.  Let’s check our tenant to ensure Jon Snow is dead or rather John Doe is deleted.


He’s gone!  You are good to go.


Azure is a dynamic, new technology.  Documentation is changing almost daily. It can be frustrating to navigate the changing landscape of marketing terms and portals.

All the information you need to sort out this error is out there. However, I found it to be scattered and not exactly applicable to what I was doing.  The PowerShell snippets existed in parts, one to log in to a remote tenant, one to add the role.  This post simply serves to bring the information together so you can quickly get past this problem and on to writing more code.





So, you want to delete users with the Azure AD Graph API? Good luck with that!

Reading a SharePoint Online (Office 365) List from a Console Application (the easy way)

In a previous post I talked about our strategy of using scheduled console applications to perform tasks that are often performed by SharePoint timer jobs.

As we march “zealously” to the cloud we find ourselves needing to update our batch jobs so that they communicate with our SharePoint Online tenant.  We must update our applications because the authentication flow between on premise SharePoint 2013 and SharePoint Online are completely different.

Fortunately for us, we found the only change needed to adapt our list accessing code was to swap instances of  the NetworkCredentials class for the SharePointOnlineCredentials class.

Imagine that this is your list reading code:

using (var client = new WebClient())
client.Headers.Add(“X-FORMS_BASED_AUTH_ACCEPTED”, “f”);
client.Credentials = _credentials;  //NetworkCredentials
client.Headers.Add(HttpRequestHeader.ContentType, “application/json;odata=nometadata”);
client.Headers.Add(HttpRequestHeader.Accept, “application/json;odata=nometadata”);

/* make the rest call */
var endpointUri = $”{_site}/_api/web/lists/getbytitle(‘{_listName}’)/Items({itemId})”;
var apiResponse= client.DownloadString(endpointUri);

/* deserielize the result */
return _deserializer.Deserialize(apiResponse);

The chances are your _credentials object is created like this:

_credentials= new NetworkCredentials(username,password,domain);

Here, the username and password are those of a service account specifically provisioned a for SharePoint list access.

In order to swap the NetworkCredentails class for SharePointOnlineCredentails first, you  need to download and install the latest version of the SharePoint Online Client Components SDK here (

Once the SDK is installed  add a reference to the Microsoft.SharePoint.Client and Microsoft.SharePoint.Client.Runtime libraries.  Assuming a default installation, these binaries can be found here: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\.

Be certain to reference the version of the dlls.  If you get the version (which is currently the version in NUGet) your code may not work!

Now you can “new up” your _credentials like this:

_credentails = new SharePointOnlineCredentials(username,password);

But “TV Timeout!” (as a colleague likes to say after a couple brews at the pub) the password argument is a SecureString rather than the garden variety string.  You will need a helper method to transform your plain old string into a SecureString.  Here is how we do it:

public static SecureString GetSecureString(string myString)
var secureString = new SecureString();
foreach (var c in myString)
return secureString;

One last thing to note; the SharePointOnlineCredentials class implements the System.Net.ICredentials interface. That’s what allows us to simple swap one class for another.

Therefore,  if you are following the SOLID principles and using dependency injection then the extent of your code changes may look like this:

var securePassword = SecureStringService

=> new SharePointOnlineCredentials(username, securePassword));

Now that is cool!

Cheers and Happy Coding!


Reading a SharePoint Online (Office 365) List from a Console Application (the easy way)