Skip to content

Instantly share code, notes, and snippets.

@atodev
Last active February 28, 2025 12:01
Show Gist options
  • Select an option

  • Save atodev/6bc23783b1e1764fab4e6ba8d48a2acd to your computer and use it in GitHub Desktop.

Select an option

Save atodev/6bc23783b1e1764fab4e6ba8d48a2acd to your computer and use it in GitHub Desktop.
[MSGRAPH]
import requests
from OpenSSL import crypto
# Set base URL for Microsoft Graph API
BASE_URL = "https://login.microsoftonline.com"
# Set API endpoint for token
ENDPOINT = "/{tenant_id}/oauth2/v2.0/token"
# Set tenant ID
TENANT_ID = "tenant_id_here"
# Set client ID
CLIENT_ID = "client_id_here"
# Set certificate path
CERT_PATH = "certificate.pem"
# Set certificate password
CERT_PASS = "password_here"
# Set scopes
SCOPES = "https://graph.microsoft.com/.default"
# Load certificate
cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(CERT_PATH, "rb").read())
# Get certificate thumbprint
thumbprint = cert.digest("sha1").decode("utf-8").replace(":", "").upper()
# Set URL for token endpoint
url = BASE_URL + ENDPOINT.format(tenant_id=TENANT_ID)
# Set request data
data = {
"client_id": CLIENT_ID,
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": thumbprint,
"grant_type": "client_credentials",
"scope": SCOPES
}
# Send request to API
response = requests.post(url, data=data)
# Check if request was successful
if response.status_code == 200:
# Get access token from response
access_token = response.json()["access_token"]
# Print access token
print(access_token)
else:
# Print error message if request was not successful
print(f"Error: {response.json()['error_description']}")
-------------------------------------------------------------------------------
In this example, we are using the /{tenant_id}/oauth2/v2.0/token endpoint to retrieve an access token from the Microsoft Graph API. The tenant ID, client ID, and certificate path are set in the corresponding variables. The certificate is loaded and the thumbprint is calculated and used as the client assertion in the request. The request is sent to the API and the response is checked for success. If the request was successful, the access token is extracted from the response and printed. If the request was not successful, an error message is printed.
--- with cache
import json
import requests
from cryptography.hazmat.backends import default_backend
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.primitives import serialization
# Set tenant ID, client ID, and resource URL
TENANT_ID = "tenant_id_here"
CLIENT_ID = "client_id_here"
RESOURCE = "https://graph.microsoft.com"
# Set path to certificate file and password
CERT_FILE = "certificate.pem"
CERT_PASS = "certificate_password_here"
# Set cache file name and expiration time
CACHE_FILE = "token_cache.json"
EXPIRATION_TIME = 3600 # 1 hour in seconds
# Load certificate
with open(CERT_FILE, "rb") as f:
cert_data = f.read()
cert = load_pem_x509_certificate(cert_data, default_backend())
# Get certificate thumbprint
thumbprint = cert.fingerprint(hashes.SHA1()).hex()
# Get certificate public key
public_key = cert.public_key()
pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# Set request URL
url = f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/token"
# Set request headers and payload
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
payload = {
"grant_type": "client_credentials",
"client_id": CLIENT_ID,
"client_secret": pem.decode("utf-8"),
"resource": RESOURCE
}
# Check if cache file exists
try:
# Load cache file
with open(CACHE_FILE, "r") as f:
cache = json.load(f)
# Check if cache is still valid
if cache["expires_on"] > time.time():
# Use cached token if it is still valid
token = cache["access_token"]
else:
# Request new token if cache has expired
response = requests.post(url, headers=headers, data=payload)
# Check if request was successful
if response.status_code == 200:
# Get token from response
token = response.json()["access_token"]
# Save token to cache file
with open(CACHE_FILE, "w") as f:
json.dump({
"access_token": token,
"expires_on": time.time() + EXPIRATION_TIME
}, f)
else:
# Print error message if request was not successful
print(f"Error: {response.json()['error_description']}")
except FileNotFoundError:
# Request new token if cache file does not exist
response = requests.post(url, headers=
-- powershell with msal
https://blogs.aaddevsup.xyz/2020/07/using-msal-net-to-perform-the-client-credentials-flow-with-a-certificate-instead-of-a-client-secret-in-a-netcore-console-appliction/
with Postman
https://blogs.aaddevsup.xyz/2020/10/how-to-use-postman-to-perform-a-client-credentials-grant-flow-with-a-certificate/
$cert=New-SelfSignedCertificate -Subject "CN=DaemonConsoleCert" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature
create the cert
https://www.youtube.com/watch?v=Q620JbCsq1I
https://github.com/erik-de-bont/debontonline/blob/main/azure/msgraphapi/part_3/Create-SelfSignedCertificate.ps1
with python
https://github.com/mattfeltonma/python-msal-cert-authentication-demo
https://blogs.aaddevsup.xyz/2020/07/using-msal-net-to-perform-the-client-credentials-flow-with-a-certificate-instead-of-a-client-secret-in-a-netcore-console-appliction/
import requests
def auth_o365():
# Auth call
req_token_body = {
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret,
"scope": "https://graph.microsoft.com/.default",
}
response = requests.post(
"https://login.microsoftonline.com/{}/oauth2/v2.0/token".format(tenant_name),
json=req_token_body,
)
return response.json()
def read_calendar(token):
# Loop all users
api = "https://graph.microsoft.com/v1.0/users"
users = requests.get(
api,
headers={
"Authorization": "Bearer {}".format(token["access_token"]),
"Content-Type": "application/json",
},
).json()
for u in users["value"]:
# All events for user
# upn = '[email protected]'
upn = u["value"][0]["userPrincipalName"]
# upn = users["value"][0]["userPrincipalName"] # changed to user
api = (
"https://graph.microsoft.com/v1.0/users/{}/events"
"?$top=999"
"&$filter=start/dateTime ge '2022-01-01' and end/dateTime le '2022-11-17'"
).format(upn)
print(api)
events = requests.get(
api,
headers={
"Authorization": "Bearer {}".format(token["access_token"]),
"Content-Type": "application/json",
},
).json()
while True:
for r in events["value"]:
# Properties
event_id = r["id"]
subject = r["subject"]
body_preview = r["bodyPreview"]
start = r["start"]["dateTime"]
end = r["end"]["dateTime"]
attendees_count = len(r["attendees"])
organizer_name = r["organizer"]["emailAddress"]["name"]
organizer_address = r["organizer"]["emailAddress"]["address"]
print("EVENT: Start={} End={} Id={}".format(start, end, event_id))
if "@odata.nextLink" in events:
events = requests.get(
events["@odata.nextLink"],
headers={
"Authorization": "Bearer {}".format(token["access_token"]),
"Content-Type": "application/json",
},
).json()
else:
break
def main():
token = auth_o365()
print(token)
read_calendar(token)
main()
https://oofhours.com/2020/09/05/using-microsoft-graph-from-python/
https://medium.com/@marian.reha/query-ms-graph-api-in-python-e8e04490b04e
# Import the required modules
import requests
import json
# Set the base URL for the Microsoft Graph API
base_url = 'https://graph.microsoft.com/v1.0/'
# Set the URL for the desired endpoint, including any query parameters
endpoint_url = base_url + 'me/messages?$top=100'
# Set the authorization headers
auth_headers = {
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
}
# Set a flag to track whether there are more pages of results
more_pages = True
# Set a counter to track the number of pages processed
page_count = 0
# Set an empty list to store the results
results = []
while more_pages:
# Make the GET request
response = requests.get(endpoint_url, headers=auth_headers)
# Convert the response to JSON
data = response.json()
# Check for errors
if 'error' in data:
print(f'Error: {data["error"]["message"]}')
break
# Add the items from the current page to the results list
results += data['value']
# Check if there is a 'nextLink' in the response
if '@odata.nextLink' in data:
# If there is, update the URL for the next request
endpoint_url = data['@odata.nextLink']
else:
# If there is not, set the flag to False to stop the loop
more_pages = False
# Increment the page counter
page_count += 1
# Print a status update
print(f'Processed page {page_count}')
# Print the number of items in the results list
print(f'Number of items: {len(results)}')
This code will make requests to the specified Microsoft Graph API endpoint, using the $top query parameter to specify the number of items to include in each page of results. It will then continue to make requests and append the results to the results list until there are no more pages of results, indicated by the absence of a @odata.nextLink in the response.
https://chat.openai.com/chat
import requests
import json
Set the base URL for the Microsoft Graph API
base_url = "https://graph.microsoft.com"
Set the endpoint for the user's messages
endpoint = "/v1.0/me/messages"
Set the access token
access_token = "<YOUR_ACCESS_TOKEN>"
Set the initial URL for the pagination loop
url = base_url + endpoint
Set a flag to indicate whether there are more pages of data
more_pages = True
Set a counter to keep track of the number of pages
page_count = 0
Set a limit on the number of pages to retrieve
page_limit = 10
Set the request headers
headers = {
"Authorization": "Bearer " + access_token,
"Content-Type": "application/json"
}
Set the request parameters
params = {
"top": 100, # Set the number of records per page
"select": "subject,receivedDateTime" # Set the properties to retrieve
}
Start the pagination loop
while more_pages and page_count < page_limit:
# Make the GET request
response = requests.get(url, headers=headers, params=params)
-------------------------------------------------------------------
# Check for a successful response
if response.status_code == 200:
# Increment the page counter
page_count += 1
# Get the data from the response
data = response.json()
# Loop through the messages in the page
for message in data["value"]:
# Print the message details
print("Subject:", message["subject"])
print("Received:", message["receivedDateTime"])
print()
# Check if there is a next page of data
if "nextLink" in data:
# Set the URL for the next page
url = data["nextLink"]
else:
# Set the flag to indicate there are no more pages
more_pages = False
else:
# Print the error message
print("Error:", response.text)
break
import requests
# Set base URL for Microsoft Graph API
BASE_URL = "https://graph.microsoft.com"
# Set API endpoint for paginated results
ENDPOINT = "/v1.0/me/messages"
# Set API access token
TOKEN = "access_token_here"
# Set initial URL for paginated results
url = BASE_URL + ENDPOINT
# Set initial page and page size
page = 0
page_size = 100
# Set initial list for messages
messages = []
# Set flag to check if more pages exist
has_more_pages = True
while has_more_pages:
# Set URL parameters for pagination
params = {
"$top": page_size,
"$skip": page * page_size
}
# Set request headers
headers = {
"Authorization": f"Bearer {TOKEN}"
}
# Send request to API
response = requests.get(url, params=params, headers=headers)
# Check if request was successful
if response.status_code == 200:
# Get messages from response
response_messages = response.json()["value"]
# Append messages to list
messages += response_messages
# Check if more pages exist
if "@odata.nextLink" in response.json():
# Set URL for next page
url = response.json()["@odata.nextLink"]
# Increment page number
page += 1
else:
# Set flag to False if no more pages exist
has_more_pages = False
else:
# Set flag to False if request was not successful
has_more_pages = False
# Print final list of messages
print(messages)
-------------------------------------------------
In this example, we are paginating through the results of the /v1.0/me/messages endpoint to retrieve a list of messages. The $top and $skip URL parameters are used to control the page size and the starting index of each page of results. The @odata.nextLink property in the response is checked to determine if there are more pages of results to retrieve. If there are, the URL for the next page is set and the page number is incremented. If there are no more pages, the loop is exited. The final list of messages is printed at the end.
https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-create-self-signed-certificate
##$certname = "{certificateName}" ## Replace {certificateName}
$certname = "test"
$cert = New-SelfSignedCertificate -Subject "CN=$certname" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256
Export-Certificate -Cert $cert -FilePath "D:\Pfizer\Code\$certname.cer"
https://www.youtube.com/watch?v=7Bkv9J9mVr0
PowerShell script to create self signed certificate.
$FilePath = 'C:\Users\Dipes\Desktop\certificates\abc'
$StoreLocation = 'CurrentUser' # be aware that LocalMachine requires elevated privileges
$expirationYears = 1
$SubjectName = $tenant_id + '.' + $client_id
$cert_password = $client_id
$pfxFileName = $SubjectName + '.pfx'
$cerFileName = $SubjectName + '.cer'
$PfxFilePath = $FilePath + $pfxFileName
$CerFilePath = $FilePath + $cerFileName
$CertBeginDate = Get-Date
$CertExpiryDate = $CertBeginDate.AddYears($expirationYears)
$SecStringPw= ConvertTo-SecureString -String $cert_password -Force -AsPlainText
$Cert = New-elfSignedCertificate -DnsName $SubjectName -CertStoreLocation "cert:\$StoreLocation\My" -NotBefore $CertBeginDate -NotAfter $CertExpiryDate -KeySpec Signature
Export-PfxCetificate -cert $Cert -FilePath $PFXFilePath -Password $SecStringPw
Export-Certificate -cert $Cert -FilePath $CerFilePath
Connect Microsoft Graph
Connect-MgGraph -ClientID YOUR_APP_ID -TenantId YOUR_TENANT_ID -CertificateThumbprint ""
https://blog.darrenjrobinson.com/microsoft-graph-using-msal-with-python-and-certificate-authentication/
--god one
https://www.youtube.com/watch?v=Q620JbCsq1I
and
https://www.youtube.com/watch?v=KWKiwpK-L5o
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment