How to use Office 365 Management Activity API - Netwoven

How to use Office 365 Management Activity API

By Vikash Kumar Pathak  •  November 12, 2019  •  14379 Views

How to use Office 365 Management Activity API

The Office 365 Management Activity API provides information about various user, admin, system, and policy actions and events from Office 365 and Azure Active Directory activity logs which can help in tracking all types of activity and based on that data a detailed report can be prepared and visualized.

Here I am using my personal developer tenant for this article and will create a sample .Net Core console application.

Following are the key steps to follow before starting API access implementation.

1. Register Application in Azure AD

  • Login to your azure portal and make sure you are in the right directory in which you are going to register your application.
  • Click on Azure Active Directory.
  • From left navigation panel click on App Registration and then New Registration.
    How to use Office 365 Management Activity API
  • Please enter display name in Name box and select any Supported account types.
    How to use Office 365 Management Activity API
  • Click on Register.
  • Once application is registered, perform following options to generate client secret.
  • Click on Certificate and secrets.
  • Then click New client secret and enter a certificate description and then click Add
    How to use Office 365 Management Activity API
  • It displays a hashed client secret and copy it somewhere because later we cannot, and we need it when configuring App client call.
  • Click on API permissions below Certificates and secrets and then click Add a permission, this will open a new blade showing different API available to use.
    How to use Office 365 Management Activity API
  • Click on Office 365 Management APIs, it opens another popup blade showing the type of permissions as Delegated and Application, since here we are using console as sample application then we can use Application permission and same apply for background services as well.
    How to use Office 365 Management Activity API
  • After clicking Application permissions, it shows a list of permission.
  • Since we are using O365 Activity API, first we need to give permission related to Activity Feed and expand the same ActivityFeed and then select checkbox as below.
    How to use Office 365 Management Activity API
  • Then click Add Permissions
  • Next click on Grant admin consent for {Tenant Name}, it will ask confirmation and then click on Yes.
  • Click on the Overview from left navigation and copy Application ID, Tenant ID in a separate file which we need when making API call.
    How to use Office 365 Management Activity API

3. Request access tokens from Azure AD:

Please follow below steps to set up client application with App ID, Tenant ID, Client Secrets.

  • Create a sample .Net Core console application.
  • Install package “Microsoft.IdentityModel.Clients.ActiveDirectory”, this is the only package we need for getting Azure AD auth tokens.
  • Store client Id, tenant id and client secret in a class level variable as shown below.
static string tenantId = "tenant123";
        		static string clientId = "client123";
   	static string secret = "S:9Wol6hg6ds;8d787d7asdn:das/78dn:/rDf";
  • Use AuthenticationContext class to acquire an access token from Azure AD. For this, I have defined a class named OAuthMessageHandler which implements DelegatingHandler and automates the process of getting access tokens and overrides SendAsync method to send request to the server as given below.
public class OAuthMessageHandler : DelegatingHandler
        {
            private AuthenticationHeaderValue authHeader;
            public OAuthMessageHandler(string tenantId, string clientId, string secret, HttpMessageHandler innerHandler)
                : base(innerHandler)
            {                
                var authenticationContext = new AuthenticationContext("https://login.windows.net/" + tenantId, false);                
                ClientCredential clientCred = new ClientCredential(clientId, secret);
                AuthenticationResult authenticationResult = null;
                Task runTask = Task.Run(async () => authenticationResult = await authenticationContext.AcquireTokenAsync("https://manage.office.com", clientCred));
                runTask.Wait();
                string token = authenticationResult.AccessToken;

                authHeader = new AuthenticationHeaderValue("Bearer", token);
            }

            protected override Task<HttpResponseMessage> SendAsync(
                     HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
            {
                request.Headers.Authorization = authHeader;
                return base.SendAsync(request, cancellationToken);
            }
        }

4. Make Office 365 Management Activity APIs Call:

Before making APIs call, we need to turn office log to on/off. To do this please check this link https://docs.microsoft.com/en-us/microsoft-365/compliance/turn-audit-log-search-on-or-off. Once the audit log turned on, lets see how different activity log has been classified into following content type.

  • Audit.AzureActiveDirectory
  • Audit.Exchange
  • Audit.SharePoint
  • Audit.General
  • DLP.All

Currently describing each of these content types is beyond the scope of this blog and we are going to proceed only with Audit.SharePoint. Follow the steps below.

1. We need to start the subscription related to content type for which we are going to retrieve/list contents.

var messageHandler = new OAuthMessageHandler(tenantId, clientId, secret, new HttpClientHandler());
            using (HttpClient httpClient = new HttpClient(messageHandler))
            {
                httpClient.BaseAddress = new Uri("https://manage.office.com");
                httpClient.Timeout = new TimeSpan(0, 2, 0);

                string endpoint = $"/api/v1.0/{tenantId}/activity/feed/subscriptions/start?contentType=Audit.Exchange";
                HttpRequestMessage message = new HttpRequestMessage(new HttpMethod("POST"), endpoint);

                var resp = httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead).Result;                
                if (resp.Result.IsSuccessStatusCode)
                {
                    Console.WriteLine("Processing completed");
                } 
     }

2. Once subscription started related to content types then check whether content types got enable or not using list subscription APIs. Below APIs call can be made to get list of subscribed content types.

testResponse = httpClient.GetAsync($"https://manage.office.com/api/v1.0/{tenantId}/activity/feed/subscriptions/list");

Sample Response =>
[{"contentType":"Audit.Sharepoint","status":"enabled","webhook":null}]

3. Now let’s try to retrieve the content URL of SharePoint activity. Below is the APIs call and the sample response.

testResponse = httpClient.GetAsync($"https://manage.office.com/api/v1.0/{tenantId}/activity/feed/subscriptions/content?contentType=Audit.SharePoint&PublisherIdentifier={tenantId}");

Sample Response=> 
[{"contentUri":"https://manage.office.com/api/v1.0/442343crca-df36-423a-ae01-329af93d424d27/activity/feed/audit/20191028111653970085558$20191028122221900037718$audit_azureactivedirectory$Audit_AzureActiveDirectory$apac0013",
"contentId":"20191028111653970085558$20191028122221900037718$audit_azureactivedirectory$Audit_SharePoint$apac0013",
"contentType":"Audit.AzureActiveDirectory","contentCreated":"2019-10-28T12:22:21.900Z", "contentExpiration":"2019-11-04T11:16:53.970Z"}]

4. Then make another request reading the contentUri from the previous sample JSON response and this will return the actual activity log contents.

testResponse = httpClient.GetAsync($"https://manage.office.com/api/v1.0/f34d4d34eca-df36-423a-ae01-329d4234507e7/activity/feed/audit/ 20191028111653970085558$20191028122221900037718$audit_sharepoint$Audit_SharePoint$apac0013",
"contentId":"20191028111653970085558$20191028122221900037718$audit_sharepoint$Audit_SharePoint$apac0013");

Sample Response => 
[{"CreationTime":"2019-11-03T07:32:24","Id":"sasa2s-32d3f464-43ef-e668-08d7602ff8c4","Operation":"PageViewed","OrganizationId":"2d4241eca-df36-423a-ae01-329af93507e7","RecordType":4, "UserKey":"i:0h.f|membership|100320004c287005@live.com","UserType":0,"Version":1,"Workload":"SharePoint","ClientIP":"223.237.241.166","ObjectId":"https:\/\/vttest.sharepoint.com\/sites\/tests\/Shared Documents\/Forms\/AllItems.aspx","UserId":"test@test.onmicrosoft.com","CorrelationId":"ab25149f-50e2-0032-436a-bdc5f9ce9761", "CustomUniqueId":false,"EventSource":"SharePoint","ItemType":"Page","ListId":"1b0aa9c8-8b329-4229-a5b9-43d15467ef96", "ListItemUniqueId":"ed53239b1-2afb-4a3b-a20c-b56e333f8c","Site":"8x32x949d-e59b-45df-b6ba-2e4720d8ddec","UserAgent":"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/77.0.3865.90 Safari\/537.36","WebId":"59d95fcb-9cfd-4dsd33-8899-4d54c196ccbf"}]

Complete code has been given below.

class Program
    {
        static string tenantId = "tenanr123";
        static string clientId = "client123";
        static string secret = "S:9Wol6h$%^$&#*dsjdnsdds-=H-PC:/rDf";
        static OAuthMessageHandler messageHandler;
        static Program()
        {
            messageHandler = new OAuthMessageHandler(tenantId, clientId, secret, new HttpClientHandler());
        }
        static void Main(string[] args)
        {
            StartSubscription();
            ListSubscription();
            RetrieveContent();
        }
        static void StartSubscription()
        {
            using (HttpClient httpClient = new HttpClient(messageHandler))
            {
                httpClient.BaseAddress = new Uri("https://manage.office.com");
                httpClient.Timeout = new TimeSpan(0, 2, 0);

                string endpoint = $"/api/v1.0/{tenantId}/activity/feed/subscriptions/start?contentType=Audit.Exchange";
                HttpRequestMessage message = new HttpRequestMessage(new HttpMethod("POST"), endpoint);

                var resp = httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead).Result;
                if (resp.IsSuccessStatusCode)
                {
                    Console.WriteLine("Processing completed");
                }
            }
        }
        static void ListSubscription()
        {
            using (HttpClient httpClient = new HttpClient(messageHandler))
            {
                httpClient.BaseAddress = new Uri("https://manage.office.com");
                httpClient.Timeout = new TimeSpan(0, 2, 0);

                var testResponse = httpClient.GetAsync($"https://manage.office.com/api/v1.0/{tenantId}/activity/feed/subscriptions/list");
                if (testResponse.Result.IsSuccessStatusCode)
                {
                    string json = testResponse.Result.Content.ReadAsStringAsync().Result;
                    Console.WriteLine("Processing completed");
                }
            }
        }
        static void RetrieveContent()
        {
            using (HttpClient httpClient = new HttpClient(messageHandler))
            {
                httpClient.BaseAddress = new Uri("https://manage.office.com");
                httpClient.Timeout = new TimeSpan(0, 2, 0);

                var testResponse = httpClient.GetAsync($"https://manage.office.com/api/v1.0/{tenantId}/activity/feed/subscriptions/content?contentType=Audit.SharePoint&PublisherIdentifier={tenantId}&amp;startTime=2018-12-12&amp;endTime=2019-12-12");
                if (testResponse.Result.IsSuccessStatusCode)
                {
                    string json = testResponse.Result.Content.ReadAsStringAsync().Result;
                    Console.WriteLine("Processing completed");
                }
            }
        }
    }

	public class OAuthMessageHandler : DelegatingHandler
    {
        private AuthenticationHeaderValue authHeader;
        public OAuthMessageHandler(string tenantId, string clientId, string secret, HttpMessageHandler innerHandler)
            : base(innerHandler)
        {
            var authenticationContext = new AuthenticationContext("https://login.windows.net/" + tenantId, false);
            ClientCredential clientCred = new ClientCredential(clientId, secret);
            AuthenticationResult authenticationResult = null;
            Task runTask = Task.Run(async () => authenticationResult = await authenticationContext.AcquireTokenAsync("https://manage.office.com", clientCred));
            runTask.Wait();
            string token = authenticationResult.AccessToken;

            authHeader = new AuthenticationHeaderValue("Bearer", token);
        }

        protected override Task<HttpResponseMessage> SendAsync(
                 HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            request.Headers.Authorization = authHeader;
            return base.SendAsync(request, cancellationToken);
        }
    }

In this Article, I have shown how to access Office 365 management activity API by using a sample console application and making a call to APIs and getting request but the same process can be automated using webhook approach and Web API which I am going to explain in my next blog. By then cheers! And have a happy coding.

4 comments

  1. Found a glitch here:
    var resp = httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead).Result;
    if (resp.Result.IsSuccessStatusCode)
    // should be if (resp.IsSuccessStatusCode)
    {
    Console.WriteLine(“Processing completed”);
    }

  2. Nice Article. Is there a way to get event form Teams created or teams deleted. Which activity log teams are classified into Audi.Sharepoint or General.

Leave a comment

Your email address will not be published. Required fields are marked *

Microsoft Partner
Microsoft Partner
Microsoft Partner
Microsoft Partner
Microsoft Partner
Microsoft Partner
Microsoft Fast Track
Microsoft Partner
MISA
MISA
Unravel The Complex
Stay Connected

Subscribe and receive the latest insights

Netwoven Inc. - Microsoft Solutions Partner

Get involved by tagging Netwoven experiences using our official hashtag #UnravelTheComplex