-
-
Notifications
You must be signed in to change notification settings - Fork 369
Expand file tree
/
Copy pathmigrate_from_saml_to_cert.py
More file actions
157 lines (138 loc) · 6.2 KB
/
Copy pathmigrate_from_saml_to_cert.py
File metadata and controls
157 lines (138 loc) · 6.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
"""
Migrate from legacy SAML auth to Azure AD certificate auth.
Microsoft retired SAML/WS-Federation for SharePoint Online in May 2026
(MC1184649). The old with_user_credentials() method no longer works
for SharePoint Online.
This example covers the migration path to Azure AD app-only with a
certificate, which is the recommended replacement.
Prerequisites:
- An app registered in Azure AD (or update an existing one)
- openssl (for certificate generation)
- Admin consent for SharePoint API permissions
See https://learn.microsoft.com/en-us/sharepoint/dev/security/saml-auth-retirement
See https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread
"""
# ===========================================================================
# Step 1 -- Generate a self-signed certificate (run in terminal)
# ===========================================================================
#
# # Create private key and self-signed certificate (365-day validity)
# openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
# -keyout private_key.pem -out cert.pem \
# -subj "/CN=SharePointApp"
#
# # Extract thumbprint (needed below)
# openssl x509 -in cert.pem -fingerprint -noout \
# | sed 's/.*=//' | sed 's/://g'
#
# # Alternatively, convert an existing PFX from Azure:
# openssl pkcs12 -in myapp.pfx -nocerts -nodes \
# | openssl pkcs8 -topk8 -nocrypt -out private_key.pem
# openssl pkcs12 -in myapp.pfx -nokeys -out cert.pem
# ===========================================================================
# Step 2 -- Register / update an app in Azure AD
# ===========================================================================
#
# Option A -- Create a new app registration:
# 1. Go to https://entra.microsoft.com/ -> App registrations -> New registration
# 2. Name: e.g. "SharePoint Python Client"
# 3. Supported account types: "Accounts in this organizational directory only"
# 4. Do not set a redirect URI (this is app-only)
# 5. Click Register and note the Application (client) ID and Directory (tenant) ID
#
# Option B -- Update an existing app:
# 1. Same app works -- just add a certificate credential under "Certificates & secrets"
# 2. No need to create a new app registration
# ===========================================================================
# Step 3 -- Grant SharePoint API permissions
# ===========================================================================
#
# IMPORTANT: Grant SharePoint permissions, not Microsoft Graph permissions.
# ClientContext uses the SharePoint REST API, which requires SharePoint
# resource permissions.
#
# 1. In your app registration -> "API permissions"
# 2. Click "Add a permission" -> "APIs my organization uses"
# 3. Search for and select "SharePoint"
# 4. Select "Application permissions"
# 5. Choose at minimum: Sites.Read.All or Sites.FullControl.All
# 6. Click "Add permissions"
# 7. Click "Grant admin consent for [tenant]" and confirm
#
# Verify that "SharePoint" (not "Microsoft Graph") appears among configured
# permissions.
# ===========================================================================
# Step 4 -- Upload the certificate to the app registration
# ===========================================================================
#
# 1. In your app registration -> "Certificates & secrets"
# 2. Click "Upload certificate"
# 3. Select the cert.pem file from Step 1
# 4. Click "Add"
# 5. Copy the Thumbprint value (hex string, no colons)
# ===========================================================================
# Step 5 -- Connect and verify
# ===========================================================================
import argparse
from office365.sharepoint.client_context import ClientContext
from tests.settings import client_id, site_url, tenant
def main():
parser = argparse.ArgumentParser(description="Migrate from legacy SAML auth to Azure AD certificate auth")
parser.add_argument(
"--thumbprint",
default="AABBCCDDEEFF00112233445566778899AABBCCDD",
help="certificate thumbprint",
)
parser.add_argument("--cert-path", default="./private_key.pem", help="path to the private key PEM file")
args = parser.parse_args()
ctx = ClientContext(site_url).with_client_certificate(
tenant=tenant,
client_id=client_id,
thumbprint=args.thumbprint,
cert_path=args.cert_path,
)
web = ctx.web.get().execute_query()
print("Connected to: {0}".format(web.url))
print("Site title: {0}".format(web.title))
if __name__ == "__main__":
main()
# ===========================================================================
# What changed from the old SAML approach
# ===========================================================================
#
# OLD (retired -- do not use):
# ctx = ClientContext(url).with_user_credentials(username, password)
#
# NEW (recommended):
# ctx = ClientContext(url).with_client_certificate(
# tenant, client_id, thumbprint, cert_path
# )
#
# Benefits of certificate auth over SAML:
# - No username/password to rotate
# - No MFA or conditional access issues (app-only)
# - Aligned with Microsoft's long-term auth strategy
# - Works with Sovereign clouds (GCC High, 21Vianet, etc.)
# ===========================================================================
# Alternative: MSAL ROPC (requires delegated user context)
# ===========================================================================
#
# If your code needs user-specific (delegated) access rather than app-only:
#
# from office365.sharepoint.client_context import ClientContext
# from tests.settings import client_id, site_url, tenant, username
#
# ctx = ClientContext(site_url).with_username_and_password(
# tenant=tenant,
# client_id=client_id,
# username=username,
# password="***",
# )
#
# Limitations of ROPC flow:
# - Does not support MFA
# - May be blocked by conditional access policies
# - Tenant must allow public client flows in the app manifest
# - Microsoft recommends certificate or interactive flows instead
#
# See https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc