graph_signins.py python script
Overview
Microsoft Graph User Sign-in Audit Tool is a Python utility for SOC analysts, incident responders and Entra ID admins. It pulls the authentication events of one account from the Microsoft Graph API (/auditLogs/signIns) using interactive PKCE login, exports a CSV report and builds a self-contained HTML dashboard.
Key features
- No app registration needed: uses the public Microsoft Azure CLI client ID (
04b07795-8ddb-461a-bbee-02f9e1bf7b46) with browser-based PKCE login. - Account picker forced (
prompt="select_account") to switch between analyst identities easily. - Email normalization: trims spaces and lowercases the target user for accurate OData queries.
- Custom time window with
-d/--days(default: last 15 days). - Automatic pagination following
@odata.nextLinkuntil every log is collected. - Error code translation: common Entra ID codes (
50126,50053,53003…) turned into readable explanations. - Two console modes: quiet progress bars by default, or event-by-event colored output with
-v. - CSV export (UTF-8-BOM) and an interactive HTML dashboard with live search and All / Success / Failures filters.
- Corporate proxy ready: works behind SSL/TLS inspection.
How it works
- Authentication: MSAL creates a
PublicClientApplicationand requestsAuditLog.Read.All; your browser opens to sign in and complete MFA. - Query: a UTC cutoff is calculated from the day offset and an OData filter is built.
- Retrieval: GET requests to
https://graph.microsoft.com/v1.0/auditLogs/signIns, paginating while@odata.nextLinkexists. - Parsing: date, app, IP and location, OS and browser, status with error explanation and Conditional Access results.
- Reports: summary in the console plus
.csvand.htmlfiles.
text
userPrincipalName eq '<user>' and createdDateTime ge <UTC_DATE>Requirements
- Python 3.8+ (standard Python or Anaconda).
- Libraries:
msal,requests,urllib3. - Microsoft Entra ID P1 or P2 (or Microsoft 365 E3/E5).
- Delegated permission:
AuditLog.Read.All.
The analyst account must have one of these roles:
- Security Reader (recommended for SOC analysts)
- Reports Reader
- Global Reader
- Security Administrator
- Global Administrator
Installation
bash
pip install msal requests urllib3With Anaconda: conda install requests and then pip install msal urllib3.
Usage
bash
# Default: last 15 days, quiet progress mode
python graph_signins.py -u user@company.com
# Custom time window
python graph_signins.py -u user@company.com -d 7
python graph_signins.py -u user@company.com -d 30
# Verbose, event by event
python graph_signins.py -u user@company.com -d 30 -v| Argument | Default | Required | Description |
|---|---|---|---|
-u, --user | — | Yes | Target UserPrincipalName or email. |
-d, --days | 15 | No | Number of past days to inspect. |
-v, --verbose | False | No | Event-by-event output in the terminal. |
Outputs
text
=====================================================================================
SIGN-IN EVENTS SUMMARY (15 DAYS) | UNIQUE IPs CHECKED: 3
=====================================================================================
Total Logins : 25
Successful : 23
Failed : 2
Unique IPs : 3
=====================================================================================signins_<user>_<days>d_<timestamp>.csv— full export for Excel or a SIEM (date, user, app, status, error code and meaning, IP, location, OS, browser, Conditional Access).signins_<user>_<days>d_<timestamp>.html— standalone dashboard with metric cards, instant search, one-click filters and error explanations.
Corporate proxy & SSL
Behind a corporate proxy doing SSL/TLS inspection, Python HTTPS calls can fail with CERTIFICATE_VERIFY_FAILED. The script handles it by silencing urllib3 warnings and using verify=False on outbound requests:
python
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
requests.get(url, headers=headers, verify=False)