Skip to content

Commit 789da26

Browse files
authored
Merge pull request #794 from DEADSCOP/master
Full SharePoint authentication support with GCC High Environments
2 parents 41fb3a8 + 185ba12 commit 789da26

File tree

4 files changed

+45
-19
lines changed

4 files changed

+45
-19
lines changed

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ pip install Office365-REST-Python-Client
2727

2828
### Note
2929
>
30-
3130
>Alternatively the _latest_ version could be directly installed via GitHub:
3231
>```
3332
>pip install git+https://github.com/vgrem/Office365-REST-Python-Client.git
@@ -175,6 +174,20 @@ The list of examples:
175174

176175
Refer [examples section](examples/sharepoint) for another scenarios
177176

177+
### Support for non-standard SharePoint Online Environments
178+
179+
Support for non-standard SharePoint Environments is currently being implemented. Currently supported:
180+
- GCC High
181+
182+
To enable authentication to GCC High endpoints, add the `environment='GCCH'` parameter when calling the
183+
`ClientContext class` with `.with_user_credentials`, `.with_client_credentials`, or `.with_credentials`
184+
185+
Example:
186+
```python
187+
client_credentials = ClientCredential('{client_id}','{client_secret}')
188+
ctx = ClientContext('{url}').with_credentials(client_credentials, environment='GCCH')
189+
```
190+
178191
# Working with Outlook API
179192

180193
The list of supported APIs:

office365/runtime/auth/authentication_context.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,9 @@ def with_credentials(self, credentials, **kwargs):
173173
:param UserCredential or ClientCredential credentials:
174174
"""
175175
if isinstance(credentials, ClientCredential):
176+
environment = kwargs.get("environment")
176177
provider = ACSTokenProvider(
177-
self.url, credentials.clientId, credentials.clientSecret
178+
self.url, credentials.clientId, credentials.clientSecret, environment
178179
)
179180
elif isinstance(credentials, UserCredential):
180181
allow_ntlm = kwargs.get("allow_ntlm", False)

office365/runtime/auth/providers/acs_token_provider.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010

1111

1212
class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
13-
def __init__(self, url, client_id, client_secret):
13+
def __init__(self, url, client_id, client_secret, environment='commercial'):
1414
"""
1515
Provider to acquire the access token from a Microsoft Azure Access Control Service (ACS)
1616
1717
:param str client_id: The OAuth client id of the calling application.
1818
:param str client_secret: Secret string that the application uses to prove its identity when requesting a token
1919
:param str url: SharePoint web or site url
20+
:param str environment: The Office 365 Cloud Environment endpoint used for authentication
21+
defaults to 'commercial'.
2022
"""
2123
self.url = url
2224
self.redirect_url = None
@@ -25,6 +27,7 @@ def __init__(self, url, client_id, client_secret):
2527
self._client_id = client_id
2628
self._client_secret = client_secret
2729
self._cached_token = None
30+
self._environment = environment
2831

2932
def authenticate_request(self, request):
3033
# type: (RequestOptions) -> None
@@ -62,7 +65,7 @@ def _get_app_only_access_token(self, target_host, target_realm):
6265
self.SharePointPrincipal, target_host, target_realm
6366
)
6467
principal_id = self.get_formatted_principal(self._client_id, None, target_realm)
65-
sts_url = self.get_security_token_service_url(target_realm)
68+
sts_url = self.get_security_token_service_url(target_realm, environment=self._environment)
6669
oauth2_request = {
6770
"grant_type": "client_credentials",
6871
"client_id": principal_id,
@@ -101,10 +104,15 @@ def get_formatted_principal(principal_name, host_name, realm):
101104
return "{0}@{1}".format(principal_name, realm)
102105

103106
@staticmethod
104-
def get_security_token_service_url(realm):
105-
return "https://accounts.accesscontrol.windows.net/{0}/tokens/OAuth/2".format(
106-
realm
107-
)
107+
def get_security_token_service_url(realm, environment):
108+
if environment == "GCCH":
109+
return "https://login.microsoftonline.us/{0}/tokens/OAuth/2".format(
110+
realm
111+
)
112+
else:
113+
return "https://accounts.accesscontrol.windows.net/{0}/tokens/OAuth/2".format(
114+
realm
115+
)
108116

109117
def _get_authorization_header(self):
110118
return "Bearer {0}".format(self._cached_token.accessToken)

office365/sharepoint/client_context.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def with_client_certificate(
8181
thumbprint,
8282
cert_path=None,
8383
private_key=None,
84-
scopes=None,
84+
scopes=None
8585
):
8686
# type: (str, str, str, Optional[str], Optional[str], Optional[List[str]]) -> Self
8787
"""
@@ -93,7 +93,6 @@ def with_client_certificate(
9393
:param str thumbprint: Hex encoded thumbprint of the certificate.
9494
:param str client_id: The OAuth client id of the calling application.
9595
:param list[str] or None scopes: Scopes requested to access a protected API (a resource)
96-
9796
"""
9897
self.authentication_context.with_client_certificate(
9998
tenant, client_id, thumbprint, cert_path, private_key, scopes
@@ -139,15 +138,15 @@ def with_access_token(self, token_func):
139138
def with_user_credentials(
140139
self, username, password, allow_ntlm=False, browser_mode=False, environment='commercial'
141140
):
142-
# type: (str, str, bool, bool, str) -> Self
141+
# type: (str, str, bool, bool, Optional[str]) -> Self
143142
"""
144143
Initializes a client to acquire a token via user credentials.
145144
:param str username: Typically, a UPN in the form of an email address
146145
:param str password: The password
147146
:param bool allow_ntlm: Flag indicates whether NTLM scheme is enabled. Disabled by default
148147
:param bool browser_mode:
149-
:param str environment: The Office 365 Cloud Environment endpoint used for authentication.
150-
By default, this will be set to commercial ('commercial', 'GCCH')
148+
:param str environment: The Office 365 Cloud Environment endpoint used for authentication
149+
defaults to 'commercial'.
151150
"""
152151
self.authentication_context.with_credentials(
153152
UserCredential(username, password),
@@ -157,8 +156,8 @@ def with_user_credentials(
157156
)
158157
return self
159158

160-
def with_client_credentials(self, client_id, client_secret):
161-
# type: (str, str) -> Self
159+
def with_client_credentials(self, client_id, client_secret, environment='commercial'):
160+
# type: (str, str, Optional[str]) -> Self
162161
"""
163162
Initializes a client to acquire a token via client credentials (SharePoint App-Only)
164163
@@ -167,19 +166,24 @@ def with_client_credentials(self, client_id, client_secret):
167166
168167
:param str client_id: The OAuth client id of the calling application
169168
:param str client_secret: Secret string that the application uses to prove its identity when requesting a token
169+
:param str environment: The Office 365 Cloud Environment endpoint used for authentication
170+
defaults to 'commercial'.
170171
"""
171172
self.authentication_context.with_credentials(
172-
ClientCredential(client_id, client_secret)
173+
ClientCredential(client_id, client_secret),
174+
environment=environment
173175
)
174176
return self
175177

176-
def with_credentials(self, credentials):
177-
# type: (UserCredential|ClientCredential) -> Self
178+
def with_credentials(self, credentials, environment='commercial'):
179+
# type: (UserCredential|ClientCredential, Optional[str]) -> Self
178180
"""
179181
Initializes a client to acquire a token via user or client credentials
180182
:type credentials: UserCredential or ClientCredential
183+
:param str environment: The Office 365 Cloud Environment endpoint used for authentication
184+
defaults to 'commercial'.
181185
"""
182-
self.authentication_context.with_credentials(credentials)
186+
self.authentication_context.with_credentials(credentials, environment=environment)
183187
return self
184188

185189
def execute_batch(self, items_per_batch=100, success_callback=None):

0 commit comments

Comments
 (0)