The ultimate goal is to create a script that connects to the Microsoft O365 API.

Getting Started

Before I started writing the script I had to do a couple things to get me set up.

The creation of a Microsoft office 365 account was needed. It had to be a business account in order for you to have admin capabilities. They offer a free trial if you just want to test it out first.

Using your new account, sign up for Azure Portal here. This is where you can build, manage, and monitor your cloud applications. This is also where we will create the new application to show how to connect to the Microsoft O365 API.

Once I got into azure portal, I had to go through the process of registering a new application.

Register your Application

  1. Go to "App Registrations" on the left side bar.

  2. Create a new app, set the name to whatever you desire.

  3. "Accounts in any organizational directory and personal Microsoft accounts (e.g. Skype, Xbox, Outlook.com)" is the best option since it supports all account types.

  4. Set the redirect uri (Web) to: https://login.microsoftonline.com/common/oauth2/nativeclient and click register.

  5. Now I made sure to write down the Client and Tenant ID down, since they will be needed in the future.

  6. Under "Certificates & secrets", generate a new client secret. Set the expiration to never. Write down the value of the client secret created now. It will be hidden later on.

  7. In the sidebar to the left you should see "API permission". This will give us permission to access what we desire from the API. In the table you should see "microsoft graph", click on it and you should see 2 types of permissions. They include delegated and application. For this part, all we need is one permission from delegated.

    • Delegated : add "offline_access
      off-acc
  8. Everytime I was done setting new permissions, I had to click on the "Grant admin consent". This must be done.
    Consent_pic-1

Python vs Powershell

When writing scripts for Microsoft API's, their documentaion wants you to use powershell, but many prefer python. In this project, I use Python as well.

Python is a general-purpose programming language which can be used for a variety of purposes ranging from administration, web development to even machine learning. Whereas PowerShell is a scripting language and task automation framework aimed to automate administrative tasks.

Python goes way beyond scripting and goes a step ahead by providing iterative constructs, conditional statements and easy to work with syntax. Python works best when working on linux based environments.

PowerShell is a better fit for administrative purposes. It is an efficient and versatile monitoring tool used to keep a track of all the Windows boxes. It has the power of .Net along with many MS product features such as Exchange, Active Directory, etc. .Net is a framework, which is used for developing software applications. Powershell is most efficient when using windows.

Features

Python Powershell
Methods Background jobs
Expressions Powershell remoting
Cross Compilers to other languages Script debugging
The extensive set of Libraries Integrated Scripting Environment (ISE)
API documentation generators Nestable here-strings

Connecting to MS 0365

First thing I did was download the O365 module:

pip install O365

The necessary dependencies come with it.

I started up my text editor Sublime Text and created a Python file.

The next thing I did was go through the authentication process which was basically setting up my connection to the API. There are multiple methods, so the one I chose was authenticating with my own identity. This means I'll be using my own identity with my client credentials.

Here is the authentication process in code:

from O365 import Account

credentials = ('my_client_id', 'my_client_secret')


account = Account(credentials, auth_flow_type='credentials', tenant_id='my-tenant-id')
if account.authenticate():
   print('Authenticated!')

For this project the API Key are your credentials, which is needed to access the Microsoft Graph API
Here we import a dependency called "Account" from 0365. Then Instantiate an Account object with the credentials (client id and client secret), specifying the parameter auth_flow_type to "credentials". I also had to provide my 'tenant_id'.

Next, with the object I call the authenticate function. This call will request a token for you and store it in the backend. No user interaction is needed. The method will store the token in the backend and return true if the authentication succeeded.

Once this authentication step is done and I received my access token, I was finally able to make requests from the API.

Getting list of Users

If you log into your office 365 account you should see a button called Admin. When I go here, there is an option in the left navigation bar called "Users". This will show you the list of active users.

active_users

Now the question is, how can we get this list using a script. The 0365 library provides us with a Directory object and User instance. This allows us to retrieve the users from your account directory.

This can be seen here:

directory = account.directory()
for user in directory.get_users():
    print(user)

When I ran the script I had gotten an error that looked like this.

directory_error

The error message said "Insufficient privileges to complete the operation."

As I researched the problem I realized it had to do with my permissions in azure portal. But I wasn't sure which permissions I needed. On the command line it shows the endpoint(https://graph.microsoft.com/v1.0/users?%24top=100 ) that's being called which gave me a clue. Microsoft has documentation regarding their graph API and how to list the users, although it's not in python.
You can find it here.

What helped me was not just the fact I noticed the same endpoint was being used, but it also showed me which permissions I needed to authorize. For this part, we will add permissions for delegated and application.

  • Delegated: Under Directory add Directory.Read.All, Directory.ReadWrite.All, Directory.AccessAsUser.All
    del-dir

  • Application: Under Directory add Directory.Read.All, Directory.ReadWrite.All

app-dir

Reminder: click on "Grant admin consent" to soildify the changes.

Once this was done I went back, hopped on the terminal, and ran the script. This gave me the list of users.

AUT

You can see the full script from this tutorial on the HacWare GitHub account.


Pierce Taylor, Software Engineer Intern at HacWare. HacWare measures risky cybersecurity behaviors and automates security education to help MSPs combat phishing attacks.

Learn more about HacWare at hacware.com