Skip to content

Consolidated credential report — every app's passwords and certificates with

their expiry status.

This is the starting point for credential hygiene: it shows, in one view, which app registrations have client secrets or certificates, when they expire, and which ones are already past their end date (the usual cause of the AADSTS7000222 error).

Usage:

python credentials_report.py                  # every app, warn below 30 days
python credentials_report.py --warn-days 60
python credentials_report.py --expired-only   # only already-expired credentials

Reference:

Permissions

Requires application permission Directory.Read.All (delegated Application.Read.All also works).

Reference

View source

from __future__ import annotations

import argparse

from office365.graph_client import GraphClient
from tests.settings import client_id, client_secret, tenant

DEFAULT_WARN_DAYS = 30


def _client() -> GraphClient:
    return (
        GraphClient(tenant=tenant)
        .with_client_secret(client_id, client_secret)
        .require_application_permission("Directory.Read.All")
    )


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--warn-days", type=int, default=DEFAULT_WARN_DAYS, help="warn below this many days")
    parser.add_argument("--expired-only", action="store_true", help="only show apps with expired credentials")
    args = parser.parse_args()

    client = _client()
    listed = 0

    for app in client.applications.get_all().execute_query():
        creds = list(app.password_credentials or []) + list(app.key_credentials or [])
        if not creds or (args.expired_only and not any(c.is_expired for c in creds)):
            continue

        print(f"\n{app.display_name}  (app_id={app.app_id})")
        for cred in creds:
            # ``cred.kind`` is "Password"/"Certificate"; ``expiry_status`` is a printable label.
            print(f"  [{cred.kind}] {cred.expiry_status(args.warn_days)}")
            listed += 1

    print(f"\n{listed} credential(s) listed.")


if __name__ == "__main__":
    main()

← Back to Application Registration & Permissions