Microsoft Graph Security API Response Integration via API

Purpose

This guide explains how to connect Microsoft Graph Security API to Logsign as a Response integration, so an analyst can look up and triage Microsoft Graph security alerts, and look up Microsoft Entra ID (Azure AD) user records, directly from a Logsign Incident. This is a query/action integration, not a log collection poller: it does not pull alerts into Logsign on a schedule. It only runs when an analyst calls one of its methods from Settings > Integrations > Responses > +Device.

Do not confuse this with the separate Azure Graph Security data collection (poller) integration, which ingests alerts as Logsign events on a schedule and is configured under Settings > Integrations > Data Collection. The two use the same underlying Microsoft Graph Security alert data, but they are configured in different places, use different credentials entries, and this Response integration additionally exposes Microsoft Entra ID user lookups that the poller does not.

Alerts API version: the alert methods in this integration (list-alerts, get-alert, update-alert) call Microsoft's /security/alerts_v2 endpoint. Microsoft retired the legacy /security/alerts endpoint on October 15, 2026, and it no longer returns usable data. Older Logsign versions still call the legacy endpoint, so their alert methods fail or return no alerts. Contact Logsign Support to confirm that your version includes the alerts_v2 update. The alerts_v2 resource has a different set of properties and different update fields than the legacy one; the method sections below describe the current behavior.

Prerequisites

You need a Microsoft Entra ID (Azure AD) tenant and permission to register an application and grant admin consent to it (Cloud Application Administrator or Global Administrator, or an equivalent custom role; see Step 1). You also need to know which of the five methods below you actually plan to use, because the Graph application permissions differ between the alert methods and the user methods, and Microsoft's own guidance is to grant only what a specific method needs.

This integration authenticates entirely with the OAuth 2.0 client credentials grant (an application identity, not a signed-in user), against the global Microsoft cloud only. It does not support delegated (signed-in user) authentication, and it is hardcoded to call https://login.microsoftonline.com for the token and https://graph.microsoft.com/v1.0 for the API itself. If your organization operates in a Microsoft national cloud (US Government GCC High/DoD, or the China cloud operated by 21Vianet), this integration will not work: those clouds use different login and Graph endpoints entirely (for example login.microsoftonline.us and graph.microsoft.us for US Government), and this integration has no field to change them. This was confirmed by reading the integration's source code, not by testing against a national cloud tenant.

Step 1: Register an Azure AD application with least-privilege Graph permissions

Do not reuse an application that already holds broad Microsoft Graph permissions for something else. Register a dedicated application for this integration so its permission grant stays auditable and minimal.

  1. Sign in to the Azure Portal (or the Microsoft Entra admin center) with an account that can register applications. Registering the application itself does not require a tenant admin.
  2. Go to Microsoft Entra ID > App registrations > New registration. Give it a descriptive name, for example "Logsign Graph Security Response", leave the default single-tenant account type unless your organization specifically needs otherwise, and click Register.
  3. On the application's Overview page, copy and securely store the Application (client) ID and the Directory (tenant) ID. You will enter both in Logsign in Step 2.
  4. Go to Certificates & secrets > Client secrets > New client secret. Give it a description and an expiration period, then click Add. Copy the secret's Value immediately; Azure only displays it once. Set a calendar reminder before the expiration date, since an expired secret fails authentication with no advance warning from Logsign.
  5. Go to API permissions > Add a permission > Microsoft Graph > Application permissions, and add only the permissions for the methods you plan to use, from the table below. Application permissions (not delegated) are required because this integration authenticates as the app itself, with no signed-in user.
If you plan to use Add this Graph application permission Notes
list-alerts, get-alert (read-only alert lookup) SecurityAlert.Read.All Least privileged application permission for reading alerts_v2 per Microsoft's permissions reference. Do not add SecurityAlert.ReadWrite.All unless you also need update-alert. SecurityEvents.Read.All applied only to the retired legacy alerts endpoint and is not needed.
update-alert SecurityAlert.ReadWrite.All Required to update alerts_v2 alerts. This permission also covers list-alerts/get-alert, so if you need update-alert you do not need to add SecurityAlert.Read.All separately. SecurityEvents.ReadWrite.All applied only to the legacy endpoint and is not needed.
list-users, get-user (user lookup) User.Read.All Least privileged application permission that can enumerate arbitrary directory users (not just the calling identity). Do not grant User.ReadWrite.All or Directory.ReadWrite.All: this integration never writes to user objects, so a write-capable permission is unnecessary exposure.

After adding the permissions, click Grant admin consent for <your tenant>. This step requires a Global Administrator, Privileged Role Administrator, or Cloud Application Administrator; a user without one of those roles can add the permission requests but cannot approve them. Application permissions are inert until admin consent is granted, so skipping this step is the most common reason this integration authenticates (gets a token) but then fails every actual API call with a 403.

If you set up this integration before the alerts_v2 update, the app registration probably holds only SecurityEvents.Read.All or SecurityEvents.ReadWrite.All. Add the matching SecurityAlert permission from the table above and grant admin consent again, otherwise the alert methods fail with 403.

Step 2: Configure the integration in Logsign

In Logsign, go to Settings > Integrations > Responses, search for Microsoft Graph Security API, click Configure, then +Device.

Field Required Value / Notes
Tenant ID Yes The Directory (tenant) ID copied from the application's Overview page in Step 1, for example 72f988bf-86f1-41af-91ab-2d7cd011db47. The integration inserts this directly into the token request URL, https://login.microsoftonline.com/<Tenant ID>/oauth2/v2.0/token, so an incorrect value fails at the authentication step before any Graph call is attempted.
Client ID Yes The Application (client) ID from the same Overview page, for example 3fa1b2c4-.... Identifies which app registration is authenticating.
Client Secret Yes The client secret Value generated in Step 1 (not the Secret ID). Stored encrypted by Logsign. If it was regenerated or has expired, update this field with the new value; the integration has no way to detect an expiring secret in advance.

There is no Base URL or Scope field on this integration, and that is intentional, not a missing field. Both values are fixed in the integration's code rather than left for you to fill in:

  • Base URL is always https://graph.microsoft.com/v1.0, the Microsoft Graph global commercial cloud endpoint. There is no regional or per-tenant variation to configure for Microsoft Graph the way there is for some other cloud APIs; every commercial-cloud tenant is reached through this same host. The only situation where this matters is the national cloud limitation described under Prerequisites: because the host is hardcoded, tenants in US Government or China clouds cannot use this integration at all, regardless of what credentials they enter.
  • Scope is always https://graph.microsoft.com/.default. In the OAuth 2.0 client credentials flow, .default is not a single permission, it is a shorthand meaning "request a token for whatever application permissions have already been granted admin consent on this app registration." In practice this means the actual access your Logsign integration gets is entirely determined by which permissions you added and consented to in Step 1, not by anything you configure in Logsign. If a call fails with 403 Forbidden, the fix is almost always back in the Azure Portal (add the missing permission and grant consent again), not in this Scope value, because there is no Scope field to change.

For comparison, some other Microsoft Graph-based Response integrations in Logsign, such as Microsoft Entra ID Response Integration, do expose a visible Scope field where you paste in the same fixed value manually. This integration does not; the equivalent value is simply built into the code. Functionally the two approaches end up requesting the same kind of token, an application-only token scoped to whatever was admin-consented, this integration just does not surface that as an editable field.

Save the device, then use Test to confirm the integration can obtain an access token from login.microsoftonline.com with the credentials entered. Based on a review of the integration's code, the test call only exercises the token request; it does not call a real Graph endpoint such as /security/alerts_v2 or /users, so a successful test confirms your Tenant ID, Client ID and Client Secret are valid together, but does not confirm that the app has been granted (and consented to) the specific permission a given method needs. Run an actual method, for example list-alerts or list-users, after saving to confirm permissions end to end. This was not independently verified against a live Logsign UI for this guide.

Separately, the integration's underlying configuration structure includes an optional proxy URL field in the Go source code, but that field is not declared in the current asset manifest that drives the Logsign UI form. In practice this means there is currently no way to set an outbound proxy for this integration from the standard configuration screen, even though the code has a code path that would use one if it were populated. Flag this to Logsign support if your environment requires the integration to call Microsoft Graph through a proxy.

Available Methods

Every method below is invoked from within an Incident's Responses panel by selecting the configured Microsoft Graph Security API device and the method name.

list-alerts

Lists Microsoft Graph security alerts (aggregated across connected Microsoft security products such as Microsoft Defender for Endpoint, Microsoft Defender for Cloud Apps, Microsoft Entra ID Protection and Microsoft Sentinel) via GET /security/alerts_v2. Requires application permission SecurityAlert.Read.All (or SecurityAlert.ReadWrite.All, which also covers this). Each returned alert uses the alerts_v2 property names, for example tenantId, actorDisplayName, classification, determination and resolvedDateTime, instead of the legacy azureTenantId, activityGroupName and closedDateTime. Update any playbook that reads the legacy property names.

Parameter Type Required Notes
filter string No OData $filter expression, for example severity eq 'high' or status eq 'new'. The legacy provider keywords (such as "MCAS" or "IPC") belong to the retired endpoint; check Microsoft's alerts_v2 reference for the properties that support filtering.
select string No OData $select, a comma-separated list of alert properties to return instead of the default set, for example assignedTo,category,severity.
order_by string No OData $orderby, for example createdDateTime asc. alerts_v2 returns the newest alerts first when no order is given.
top integer No OData $top, the page size. Logsign's own Azure Graph Security poller uses 1000. The exact maximum Microsoft accepts on alerts_v2 was not verified for this guide.
skip integer No OData $skip. Prefer following the response's @odata.nextLink over manually incrementing skip, if your workflow supports it.
count boolean No OData $count.

get-alert

Retrieves a single alert by ID via GET /security/alerts_v2/{alertId}. Requires application permission SecurityAlert.Read.All (or SecurityAlert.ReadWrite.All).

Parameter Type Required Notes
alert_id string Yes The alert's unique ID, as returned by list-alerts. IDs of the legacy alerts API are not valid on alerts_v2.

update-alert

Updates editable properties on an existing alert (assignment, status, classification and determination) via PATCH /security/alerts_v2/{alertId}. Requires application permission SecurityAlert.ReadWrite.All.

Parameter Type Required Notes
alert_id string Yes The alert's unique ID.
status string, enum new / inProgress / resolved No Alert lifecycle status. A playbook that still sends the legacy value newAlert keeps working, because the integration converts it to new.
classification string, enum unknown / falsePositive / truePositive / informationalExpectedActivity No Analyst verdict on the alert. Replaces the legacy feedback field.
determination string, enum unknown / apt / malware / securityPersonnel / securityTesting / unwantedSoftware / other / multiStagedAttack / compromisedAccount / phishing / maliciousUserActivity / notMalicious / notEnoughDataToValidate / confirmedActivity / lineOfBusinessApplication No The reason for the classification.
assigned_to string No Name of the analyst the alert is assigned to.

The legacy update fields closed_date_time, comments, feedback, tags, vendor_provider, vendor_provider_version, vendor_sub_provider and vendor_name have no equivalent on alerts_v2. If a playbook still sends a non-empty value for any of them, the integration does not call Microsoft and returns an error such as update-alert: "feedback" is not supported by alerts_v2; use status, classification, determination or assigned_to. Remove these fields from the playbook and use the fields in the table above.

list-users

Lists Microsoft Entra ID user objects via GET /users. Requires application permission User.Read.All.

Parameter Type Required Notes
search string No OData $search. Microsoft Graph requires the request header ConsistencyLevel: eventual whenever $search (or certain $filter/$count combinations) is used against the /users endpoint's advanced query capabilities. Based on a review of the integration's code, it does not set this header on any request. If Microsoft enforces this requirement for your tenant, calls to list-users with the search parameter populated may fail with 400 Bad Request. Not independently verified against a live tenant for this guide; if you hit this, test list-users without the search parameter (using filter instead) as a workaround while this is confirmed with Logsign support.
filter string No OData $filter, for example startswith(displayName,'A').
select string No OData $select, comma-separated property list.
count boolean No OData $count. Same ConsistencyLevel caveat as search above may apply.

get-user

Retrieves a single user by ID or userPrincipalName via GET /users/{id}. Requires application permission User.Read.All.

Parameter Type Required Notes
user_id_or_principal_name string Yes Either the user's object ID (a GUID) or their userPrincipalName, for example jane.doe@contoso.com.

Notes and Limits

  • This is a query/action integration, not a log collector. It does not ingest Graph Security alerts or Entra ID user data into Logsign's event store on its own; each call returns data only for the specific request an analyst makes at that moment.
  • The alert methods (list-alerts, get-alert, update-alert) use Microsoft's alerts_v2 API. Microsoft retired the legacy alerts API on October 15, 2026. Playbooks built against the legacy API must use the alerts_v2 property names and update fields described above.
  • Throttling: Microsoft Graph enforces service-specific and tenant-level rate limits and returns HTTP 429 Too Many Requests with a Retry-After header (in seconds) when exceeded. Based on a review of the integration's code, it does not read or honor the Retry-After header and does not retry automatically; a throttled call simply returns as a failed response to Logsign. If you run a high volume of calls (for example, bulk alert lookups from a playbook loop), build a delay into the playbook itself rather than relying on this integration to back off automatically. Microsoft's exact numeric limits for the Security API and for /users are not published as fixed per-minute figures and can vary by tenant and licensing; this was not independently load-tested for this guide.
  • Authentication is entirely OAuth 2.0 client credentials against the Microsoft global commercial cloud. There is no support for delegated (signed-in user) auth, and no support for Microsoft national clouds (US Government, China), because both the token endpoint and the Graph base URL are hardcoded in the integration.
  • The client secret has an expiration date you set in Azure. This integration has no mechanism to warn you before it expires; an expired secret fails every call with an authentication error until you generate a new secret in Azure and update the Client Secret field in Logsign.
  • A proxy URL field exists in the integration's underlying configuration structure but is not exposed in the current asset manifest, so it cannot currently be set from the standard Logsign configuration screen. See Step 2.

Troubleshooting

Symptom / Code Likely Cause What to Check
401 Unauthorized (at Test / token step) Wrong Tenant ID, Client ID, or Client Secret, or the client secret has expired. Re-copy the Tenant ID and Client ID from the app registration's Overview page in Azure. Check Certificates & secrets for the secret's expiration date; generate a new secret if it has expired and update the Client Secret field.
403 Forbidden (Test succeeds, but a method call fails) The token was issued successfully, but the app registration was never granted (or never had admin consent granted for) the specific Graph permission that method needs. An app set up for the legacy API often has only SecurityEvents permissions, which do not cover alerts_v2. In Azure, go to API permissions on the app registration and confirm the permission listed for that method in Step 1's table is present and shows "Granted" under the Status column, not just "Not granted". Click Grant admin consent again if it shows as requested but not granted.
update-alert returns "is not supported by alerts_v2" The playbook sends one of the legacy update fields (closed_date_time, comments, feedback, tags or a vendor_* field). Remove the legacy field from the playbook and use status, classification, determination or assigned_to instead. See the update-alert notes above.
400 Bad Request on list-users with search populated Possibly a missing ConsistencyLevel: eventual header, which Microsoft Graph requires for $search on /users and which this integration's code does not appear to set. Not independently confirmed for this guide. Retry the same lookup using the filter parameter instead of search. If that succeeds, the ConsistencyLevel header is the likely cause; report this to Logsign support.
429 Too Many Requests Microsoft Graph's rate limit was exceeded for your tenant or for the specific Security/Users service. Reduce call frequency, especially inside playbook loops. This integration does not automatically retry or back off, so repeated bursts will keep failing until the rate limit window resets.
404 Not Found on get-alert or update-alert The alert ID does not exist, or it is an ID from the legacy alerts API, which is not valid on alerts_v2. Re-run list-alerts to get the current alerts_v2 ID of the alert.
Alert methods fail or return no data since October 15, 2026 The installed Logsign version still calls the retired legacy /security/alerts endpoint. Contact Logsign Support to update the integration to the alerts_v2 version.
Empty alert list from list-alerts with no error The app has read permission but no alerts match the current filter. Retry without a filter first to confirm alerts exist at all.
get-user or list-users returns fewer fields than expected Microsoft Graph's /users endpoint returns only a default subset of properties (businessPhones, displayName, givenName, id, jobTitle, mail, mobilePhone, officeLocation, preferredLanguage, surname, userPrincipalName) unless a $select is specified. Use the select parameter to explicitly request additional properties you need.
Was this article helpful?
0 out of 0 found this helpful

Articles in this section

See more
Become a Certified Logsign User/Administrator
Sign-up for Logsign Academy and take the courses to learn about Logsign USO Platform in detail. Enjoy the courses, and get your badges and certificates. In these courses, you'll learn how to use Logsign in your work and add value to your career.
Visit Our Blog
Our Logsign USO Platform illustrate our expertise. So do the blog. Through our blog posts, deepen your knowledge on various SecOps topics or get updated about important news & modern approaches for cybersecurity. Get into the habit of reading valuable information provided by Logsign. Be a step ahead.