Office365-REST-Python-Client 2.5.13__py3-none-any.whl → 2.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/METADATA +2 -2
  2. {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/RECORD +324 -169
  3. office365/admin/admin.py +69 -0
  4. office365/admin/microsoft365_apps.py +5 -0
  5. office365/admin/people_settings.py +5 -0
  6. office365/admin/report_settings.py +5 -0
  7. office365/{onedrive → admin}/sharepoint.py +1 -1
  8. office365/azure_env.py +60 -0
  9. office365/booking/business/business.py +13 -0
  10. office365/booking/business/collection.py +8 -4
  11. office365/communications/callrecords/collection.py +42 -0
  12. office365/communications/callrecords/direct_routing_log_row.py +5 -0
  13. office365/communications/cloud_communications.py +2 -3
  14. office365/directory/applications/app_ids.py +6 -0
  15. office365/directory/applications/application.py +16 -2
  16. office365/directory/applications/required_resource_access.py +23 -0
  17. office365/directory/applications/resource_access.py +26 -0
  18. office365/directory/authentication/authentication.py +16 -0
  19. office365/directory/authentication/method_target.py +2 -1
  20. office365/directory/authentication/methods/details.py +29 -0
  21. office365/directory/authentication/methods/microsoft_authenticator.py +6 -0
  22. office365/directory/authentication/methods/root.py +19 -0
  23. office365/directory/authentication/methods/sms.py +9 -0
  24. office365/directory/certificates/self_signed.py +31 -2
  25. office365/directory/identities/conditional_access_root.py +14 -0
  26. office365/directory/identitygovernance/privilegedaccess/approval.py +8 -0
  27. office365/directory/identitygovernance/privilegedaccess/group.py +30 -0
  28. office365/directory/identitygovernance/privilegedaccess/group_assignment_schedule_instance.py +7 -0
  29. office365/directory/identitygovernance/privilegedaccess/unified_role_assignment_schedule_request.py +7 -0
  30. office365/directory/identitygovernance/userconsent/request_collection.py +10 -0
  31. office365/directory/identitygovernance/workflow/__init__.py +0 -0
  32. office365/directory/identitygovernance/workflow/base.py +5 -0
  33. office365/directory/permissions/scope.py +15 -3
  34. office365/directory/policies/authentication_strength.py +21 -0
  35. office365/directory/policies/cross_tenant_access.py +13 -0
  36. office365/directory/policies/feature_rollout.py +16 -0
  37. office365/directory/policies/root.py +39 -23
  38. office365/directory/policies/template.py +5 -0
  39. office365/directory/policies/update_allowed_combinations_result.py +5 -0
  40. office365/directory/protection/threatassessment/email_file_request.py +20 -0
  41. office365/directory/protection/threatassessment/request.py +25 -0
  42. office365/directory/rolemanagement/application.py +15 -0
  43. office365/directory/rolemanagement/resource_action.py +8 -4
  44. office365/directory/rolemanagement/role_permission.py +3 -3
  45. office365/directory/security/alerts/collection.py +49 -0
  46. office365/directory/security/alerts/evidence.py +2 -1
  47. office365/directory/security/alerts/malware_evidence.py +5 -0
  48. office365/directory/security/alerts/process_evidence.py +5 -0
  49. office365/directory/security/attacksimulations/user.py +5 -0
  50. office365/directory/security/attacksimulations/user_coverage.py +3 -0
  51. office365/directory/security/attacksimulations/users/details.py +6 -1
  52. office365/directory/security/scorecontrol/__init__.py +0 -0
  53. office365/directory/security/scorecontrol/profile.py +6 -0
  54. office365/directory/security/security.py +17 -4
  55. office365/directory/serviceprincipals/service_principal.py +112 -55
  56. office365/directory/tenantinformation/__init__.py +0 -0
  57. office365/directory/tenantinformation/multi_organization.py +11 -0
  58. office365/directory/tenantinformation/relationship.py +61 -0
  59. office365/directory/users/insights_settings.py +5 -0
  60. office365/graph_client.py +52 -132
  61. office365/graph_request.py +78 -19
  62. office365/intune/servicecommunications/health/health.py +1 -1
  63. office365/intune/servicecommunications/issues/issue.py +2 -2
  64. office365/onedrive/columns/definition.py +1 -1
  65. office365/onedrive/contenttypes/content_type.py +1 -1
  66. office365/onedrive/driveitems/driveItem.py +14 -2
  67. office365/onedrive/driveitems/retention_label.py +33 -0
  68. office365/onedrive/driveitems/retention_label_settings.py +7 -0
  69. office365/onedrive/drives/drive.py +1 -1
  70. office365/onedrive/filestorage/__init__.py +0 -0
  71. office365/onedrive/filestorage/container.py +7 -0
  72. office365/onedrive/filestorage/file_storage.py +20 -0
  73. office365/onedrive/listitems/field_value_set.py +1 -1
  74. office365/onedrive/listitems/list_item.py +1 -1
  75. office365/onedrive/lists/list.py +1 -1
  76. office365/onedrive/recyclebin/__init__.py +0 -0
  77. office365/onedrive/recyclebin/item.py +6 -0
  78. office365/onedrive/recyclebin/recyclebin.py +29 -0
  79. office365/onedrive/recyclebin/settings.py +13 -0
  80. office365/onedrive/shares/drive_item.py +1 -1
  81. office365/onedrive/sitepages/base.py +4 -1
  82. office365/onedrive/sitepages/canvas_layout.py +2 -2
  83. office365/onedrive/sitepages/collection.py +12 -0
  84. office365/onedrive/sitepages/sections/__init__.py +0 -0
  85. office365/onedrive/sitepages/{horizontal_section.py → sections/horizontal.py} +1 -1
  86. office365/onedrive/sitepages/site_page.py +9 -9
  87. office365/onedrive/sitepages/webparts/data.py +5 -0
  88. office365/onedrive/sitepages/webparts/position.py +5 -0
  89. office365/onedrive/sitepages/webparts/standard.py +9 -0
  90. office365/onedrive/sitepages/webparts/web_part.py +12 -0
  91. office365/onedrive/sites/archival_details.py +5 -0
  92. office365/onedrive/sites/site.py +1 -1
  93. office365/onedrive/sites/site_collection.py +10 -1
  94. office365/onedrive/storage/storage.py +10 -0
  95. office365/onedrive/workbooks/charts/axes.py +41 -1
  96. office365/onedrive/workbooks/charts/axis.py +5 -0
  97. office365/onedrive/workbooks/charts/chart.py +64 -5
  98. office365/onedrive/workbooks/charts/fill.py +5 -0
  99. office365/onedrive/workbooks/charts/font.py +5 -0
  100. office365/onedrive/workbooks/charts/legend/__init__.py +0 -0
  101. office365/onedrive/workbooks/charts/legend/format.py +5 -0
  102. office365/onedrive/workbooks/charts/legend/legend.py +26 -0
  103. office365/onedrive/workbooks/charts/point.py +5 -0
  104. office365/onedrive/workbooks/charts/series/__init__.py +0 -0
  105. office365/onedrive/workbooks/charts/series/format.py +5 -0
  106. office365/onedrive/workbooks/charts/series/series.py +31 -0
  107. office365/onedrive/workbooks/charts/title.py +5 -0
  108. office365/onedrive/workbooks/filter.py +10 -0
  109. office365/onedrive/workbooks/filter_criteria.py +3 -3
  110. office365/onedrive/workbooks/functions/functions.py +23 -0
  111. office365/onedrive/workbooks/ranges/fill.py +11 -1
  112. office365/onedrive/workbooks/ranges/range.py +26 -0
  113. office365/onedrive/workbooks/ranges/view.py +14 -0
  114. office365/onedrive/workbooks/sort_field.py +8 -3
  115. office365/onedrive/workbooks/tables/sort.py +20 -0
  116. office365/onedrive/workbooks/worksheets/worksheet.py +11 -0
  117. office365/partners/__init__.py +0 -0
  118. office365/partners/billing/__init__.py +0 -0
  119. office365/partners/billing/azure_usage.py +17 -0
  120. office365/partners/billing/billed_usage.py +21 -0
  121. office365/partners/billing/billing.py +17 -0
  122. office365/partners/billing/operation.py +5 -0
  123. office365/partners/partners.py +17 -0
  124. office365/planner/tasks/check_list_item.py +5 -1
  125. office365/reports/root.py +9 -0
  126. office365/reports/userregistration/feature_summary.py +5 -0
  127. office365/runtime/auth/auth_cookies.py +48 -0
  128. office365/runtime/auth/authentication_context.py +36 -19
  129. office365/runtime/auth/entra/__init__.py +0 -0
  130. office365/runtime/auth/entra/authentication_context.py +165 -0
  131. office365/runtime/auth/providers/acs_token_provider.py +12 -27
  132. office365/runtime/auth/providers/saml_token_provider.py +41 -54
  133. office365/runtime/auth/sts_profile.py +8 -8
  134. office365/runtime/auth/token_response.py +4 -0
  135. office365/runtime/client_object.py +15 -7
  136. office365/runtime/client_object_collection.py +2 -2
  137. office365/runtime/client_result.py +2 -0
  138. office365/runtime/client_value.py +1 -1
  139. office365/runtime/csom/request.py +11 -0
  140. office365/runtime/types/exceptions.py +18 -0
  141. office365/search/acronym.py +10 -0
  142. office365/search/aggregation_option.py +6 -0
  143. office365/search/answer.py +9 -0
  144. office365/search/entity.py +67 -14
  145. office365/search/entity_type.py +28 -0
  146. office365/search/request.py +32 -3
  147. office365/sharepoint/administration/custom_fonts_resource.py +5 -0
  148. office365/sharepoint/administration/sitemove/__init__.py +0 -0
  149. office365/sharepoint/administration/sitemove/service.py +68 -0
  150. office365/sharepoint/administration/sitemove/service_info.py +11 -0
  151. office365/sharepoint/apps/access_requests.py +5 -0
  152. office365/sharepoint/apps/management/__init__.py +0 -0
  153. office365/sharepoint/apps/management/principal_info.py +9 -0
  154. office365/sharepoint/authpolicy/events/collection.py +28 -0
  155. office365/sharepoint/authpolicy/events/role_assignment_resource_payload.py +4 -0
  156. office365/sharepoint/changes/item.py +15 -0
  157. office365/sharepoint/client_context.py +61 -37
  158. office365/sharepoint/directory/group.py +2 -0
  159. office365/sharepoint/directory/helper.py +2 -0
  160. office365/sharepoint/directory/provider/provider.py +6 -0
  161. office365/sharepoint/directory/user.py +20 -0
  162. office365/sharepoint/documentmanagement/document_id.py +28 -3
  163. office365/sharepoint/files/file.py +11 -4
  164. office365/sharepoint/files/publish/__init__.py +0 -0
  165. office365/sharepoint/files/publish/status.py +9 -0
  166. office365/sharepoint/files/versions/event.py +9 -0
  167. office365/sharepoint/flows/connector_result.py +17 -0
  168. office365/sharepoint/flows/permissions.py +34 -0
  169. office365/sharepoint/fontpackages/__init__.py +0 -0
  170. office365/sharepoint/fontpackages/collection.py +26 -0
  171. office365/sharepoint/fontpackages/creation_parameters.py +5 -0
  172. office365/sharepoint/fontpackages/font_package.py +5 -0
  173. office365/sharepoint/fontpackages/oob_settings.py +5 -0
  174. office365/sharepoint/forms/customization.py +26 -0
  175. office365/sharepoint/ir/__init__.py +0 -0
  176. office365/sharepoint/ir/migration.py +5 -0
  177. office365/sharepoint/listhome/favorite_item.py +9 -0
  178. office365/sharepoint/listitems/listitem.py +79 -4
  179. office365/sharepoint/listitems/update_parameters.py +4 -1
  180. office365/sharepoint/lists/data_parameters.py +5 -0
  181. office365/sharepoint/lists/exporter.py +73 -0
  182. office365/sharepoint/lists/list.py +177 -60
  183. office365/sharepoint/lists/render_data_parameters.py +31 -0
  184. office365/sharepoint/lists/version_policy_manager.py +5 -0
  185. office365/sharepoint/marketplace/app_metadata.py +12 -1
  186. office365/sharepoint/marketplace/app_metadata_collection.py +8 -0
  187. office365/sharepoint/marketplace/corporatecuratedgallery/addins/instance_info.py +22 -0
  188. office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_failed_info.py +5 -0
  189. office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_info.py +12 -0
  190. office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_response.py +15 -0
  191. office365/sharepoint/marketplace/corporatecuratedgallery/addins/principals_response.py +5 -0
  192. office365/sharepoint/marketplace/corporatecuratedgallery/app_request_information.py +9 -0
  193. office365/sharepoint/marketplace/corporatecuratedgallery/app_response_information.py +9 -0
  194. office365/sharepoint/marketplace/corporatecuratedgallery/available_addins_response.py +4 -0
  195. office365/sharepoint/marketplace/corporatecuratedgallery/card_design.py +9 -0
  196. office365/sharepoint/marketplace/corporatecuratedgallery/card_designs.py +9 -0
  197. office365/sharepoint/marketplace/corporatecuratedgallery/teams_package_download.py +14 -0
  198. office365/sharepoint/marketplace/tenant/appcatalog/accessor.py +62 -3
  199. office365/sharepoint/migration/copy_migration_options.py +5 -0
  200. office365/sharepoint/multigeo/services.py +14 -0
  201. office365/sharepoint/multigeo/storage_quota.py +9 -0
  202. office365/sharepoint/policy/license_utilities.py +27 -0
  203. office365/sharepoint/portal/groups/site_manager.py +32 -0
  204. office365/sharepoint/portal/project/__init__.py +9 -0
  205. office365/sharepoint/portal/userprofiles/documentsshared/__init__.py +0 -0
  206. office365/sharepoint/portal/userprofiles/documentsshared/with_group.py +38 -0
  207. office365/sharepoint/portal/userprofiles/documentsshared/with_person.py +9 -0
  208. office365/sharepoint/portal/userprofiles/sharedwithme/__init__.py +0 -0
  209. office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/document.py +1 -1
  210. office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/items.py +3 -1
  211. office365/sharepoint/principal/principal.py +6 -0
  212. office365/sharepoint/publishing/pages/coauth_state.py +8 -0
  213. office365/sharepoint/publishing/pages/page.py +11 -0
  214. office365/sharepoint/publishing/pages/stream_content.py +9 -0
  215. office365/sharepoint/publishing/pages/stream_data.py +8 -0
  216. office365/sharepoint/quotamanagement/consumer/non_quota_backfill_api.py +8 -0
  217. office365/sharepoint/request.py +98 -10
  218. office365/sharepoint/search/administration/document_crawl_log.py +16 -2
  219. office365/sharepoint/search/administration/site_content_processing_info_provider.py +11 -0
  220. office365/sharepoint/search/administration/tenant_crawl_versions_info_provider.py +1 -1
  221. office365/sharepoint/search/ranking_labeling.py +1 -0
  222. office365/sharepoint/search/reports/abandoned_queries.py +11 -1
  223. office365/sharepoint/search/reports/abandonedqueries/__init__.py +0 -0
  224. office365/sharepoint/search/reports/abandonedqueries/data.py +0 -0
  225. office365/sharepoint/search/reports/abandonedqueries/item.py +11 -0
  226. office365/sharepoint/search/reports/noresult/__init__.py +0 -0
  227. office365/sharepoint/search/reports/numberofqueries/__init__.py +0 -0
  228. office365/sharepoint/search/reports/top_queries.py +7 -0
  229. office365/sharepoint/search/reports/topqueries/__init__.py +0 -0
  230. office365/sharepoint/search/reports/topqueries/data.py +9 -0
  231. office365/sharepoint/search/reports/topqueries/item.py +15 -0
  232. office365/sharepoint/search/scs_endpoint.py +9 -0
  233. office365/sharepoint/securestore/target_application.py +8 -0
  234. office365/sharepoint/sharing/document_manager.py +3 -3
  235. office365/sharepoint/sharing/domain_restriction_settings.py +5 -0
  236. office365/sharepoint/sharing/information.py +12 -0
  237. office365/sharepoint/sharing/result.py +21 -0
  238. office365/sharepoint/sitehealth/result.py +4 -4
  239. office365/sharepoint/sitehealth/summary.py +5 -5
  240. office365/sharepoint/sites/copy_job_progress.py +5 -0
  241. office365/sharepoint/sites/copy_migration_iInfo.py +5 -0
  242. office365/sharepoint/sites/home/__init__.py +0 -0
  243. office365/sharepoint/sites/{sph_site.py → home/site.py} +1 -1
  244. office365/sharepoint/sites/html_field_security_setting.py +5 -0
  245. office365/sharepoint/sites/site.py +56 -2
  246. office365/sharepoint/sites/version_policy_manager.py +25 -0
  247. office365/sharepoint/sitescripts/metadata.py +28 -3
  248. office365/sharepoint/sitescripts/utility.py +17 -0
  249. office365/sharepoint/smartcache/__init__.py +0 -0
  250. office365/sharepoint/smartcache/item.py +9 -0
  251. office365/sharepoint/tenant/administration/app_service_principal_public.py +17 -0
  252. office365/sharepoint/tenant/administration/audit/data.py +12 -0
  253. office365/sharepoint/tenant/administration/audit/unified_record.py +18 -0
  254. office365/sharepoint/tenant/administration/coms/__init__.py +0 -0
  255. office365/sharepoint/tenant/administration/coms/messages_fields_data.py +5 -0
  256. office365/sharepoint/tenant/administration/coms/messages_service_proxy.py +16 -0
  257. office365/sharepoint/tenant/administration/copilot/__init__.py +0 -0
  258. office365/sharepoint/tenant/administration/copilot/adaptive_card_config.py +11 -0
  259. office365/sharepoint/tenant/administration/datagovernance/__init__.py +0 -0
  260. office365/sharepoint/tenant/administration/{internal/permission_grant.py → datagovernance/client_base.py} +4 -2
  261. office365/sharepoint/tenant/administration/datagovernance/insight_client.py +82 -0
  262. office365/sharepoint/tenant/administration/datagovernance/insight_metadata.py +5 -0
  263. office365/sharepoint/tenant/administration/default_time_zone_id.py +11 -0
  264. office365/sharepoint/tenant/administration/endpoints.py +53 -2
  265. office365/sharepoint/tenant/administration/insights/onedrive_site_sharing.py +4 -0
  266. office365/sharepoint/tenant/administration/insights/summary_response.py +8 -0
  267. office365/sharepoint/tenant/administration/internal/aad/__init__.py +0 -0
  268. office365/sharepoint/tenant/administration/internal/aad/permission_grant.py +32 -0
  269. office365/sharepoint/tenant/administration/internal/appservice/__init__.py +0 -0
  270. office365/sharepoint/tenant/administration/internal/appservice/permission_grant.py +5 -0
  271. office365/sharepoint/tenant/administration/internal/appservice/permission_request.py +13 -0
  272. office365/sharepoint/tenant/administration/internal/appservice/principal.py +104 -0
  273. office365/sharepoint/tenant/administration/malware/__init__.py +0 -0
  274. office365/sharepoint/tenant/administration/malware/file.py +18 -0
  275. office365/sharepoint/tenant/administration/modified_property.py +5 -0
  276. office365/sharepoint/tenant/administration/policies/app_billing_properties.py +21 -0
  277. office365/sharepoint/tenant/administration/policies/content_security_configuration.py +9 -0
  278. office365/sharepoint/tenant/administration/recent_action.py +9 -0
  279. office365/sharepoint/tenant/administration/reports/__init__.py +0 -0
  280. office365/sharepoint/tenant/administration/settings_service.py +42 -6
  281. office365/sharepoint/tenant/administration/sites/creation_source.py +8 -8
  282. office365/sharepoint/tenant/administration/sites/properties.py +78 -0
  283. office365/sharepoint/tenant/administration/sites/properties_collection.py +19 -0
  284. office365/sharepoint/tenant/administration/tenant.py +241 -8
  285. office365/sharepoint/tenant/administration/types.py +89 -2
  286. office365/sharepoint/tenant/cdn_api.py +3 -1
  287. office365/sharepoint/tenant/insights/report_manager.py +29 -0
  288. office365/sharepoint/tenant/management/office365_tenant.py +9 -4
  289. office365/sharepoint/tenant/settings.py +10 -0
  290. office365/sharepoint/translation/job_status.py +22 -0
  291. office365/sharepoint/userprofiles/user_profile.py +6 -0
  292. office365/sharepoint/utilities/utility.py +6 -0
  293. office365/sharepoint/viva/connections_page.py +8 -0
  294. office365/sharepoint/viva/dashboard_configuration.py +8 -0
  295. office365/sharepoint/viva/employee_engagement.py +39 -1
  296. office365/sharepoint/viva/resource_get_endpoint.py +8 -0
  297. office365/sharepoint/viva/resource_link.py +8 -0
  298. office365/sharepoint/webparts/tile_data.py +21 -0
  299. office365/sharepoint/webs/dataleakage_prevention_status_info.py +5 -0
  300. office365/sharepoint/webs/information.py +66 -1
  301. office365/sharepoint/webs/regional_settings.py +32 -0
  302. office365/sharepoint/webs/templates/__init__.py +0 -0
  303. office365/sharepoint/webs/time_zone.py +1 -1
  304. office365/sharepoint/webs/web.py +137 -0
  305. office365/sharepoint/workflow/task.py +5 -0
  306. office365/subscriptions/collection.py +16 -0
  307. office365/teams/chats/event_message_detail.py +8 -0
  308. office365/teams/deleted.py +24 -0
  309. office365/teams/work.py +35 -0
  310. office365/directory/tenant_relationship.py +0 -23
  311. office365/onedrive/admin.py +0 -32
  312. office365/onedrive/workbooks/charts/legend.py +0 -7
  313. office365/onedrive/workbooks/charts/series.py +0 -5
  314. office365/sharepoint/portal/userprofiles/documents_shared_with_group.py +0 -11
  315. office365/sharepoint/tenant/administration/internal/web_appservice_principal.py +0 -23
  316. {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/LICENSE +0 -0
  317. {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/WHEEL +0 -0
  318. {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/top_level.txt +0 -0
  319. /office365/{sharepoint/userprofiles/sharedwithme → admin}/__init__.py +0 -0
  320. /office365/{onedrive → admin}/sharepoint_settings.py +0 -0
  321. /office365/directory/{tenant_information.py → tenantinformation/information.py} +0 -0
  322. /office365/{base_item.py → onedrive/base_item.py} +0 -0
  323. /office365/onedrive/sitepages/{horizontal_section_column.py → sections/horizontal_column.py} +0 -0
  324. /office365/onedrive/sitepages/{vertical_section.py → sections/vertical.py} +0 -0
  325. /office365/sharepoint/portal/userprofiles/{documents_shared_with_me.py → documentsshared/with_me.py} +0 -0
  326. /office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/document_user.py +0 -0
  327. /office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/item_collection.py +0 -0
  328. /office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/view_item_removal_result.py +0 -0
  329. /office365/sharepoint/sites/{home_sites_details.py → home/details.py} +0 -0
  330. /office365/sharepoint/sites/{home_site_reference.py → home/reference.py} +0 -0
@@ -2,8 +2,9 @@ import json
2
2
  import sys
3
3
  from typing import Any, Callable
4
4
 
5
- from typing_extensions import Required, TypedDict
5
+ from typing_extensions import Required, Self, TypedDict
6
6
 
7
+ from office365.azure_env import AzureEnvironment
7
8
  from office365.runtime.auth.client_credential import ClientCredential
8
9
  from office365.runtime.auth.providers.acs_token_provider import ACSTokenProvider
9
10
  from office365.runtime.auth.providers.saml_token_provider import SamlTokenProvider
@@ -31,13 +32,20 @@ def _get_authorization_header(token):
31
32
  class AuthenticationContext(object):
32
33
  """Authentication context for SharePoint Online/OneDrive For Business"""
33
34
 
34
- def __init__(self, url):
35
+ def __init__(self, url, environment=None, allow_ntlm=False, browser_mode=False):
35
36
  """
36
37
  :param str url: SharePoint absolute web or site Url
38
+ :param str environment: The Office 365 Cloud Environment endpoint used for authentication
39
+ defaults to 'Azure Global'.
40
+ :param bool allow_ntlm: Flag indicates whether NTLM scheme is enabled. Disabled by default
41
+ :param bool browser_mode: Allow browser authentication
37
42
  """
38
43
  self.url = url.rstrip("/")
39
44
  self._authenticate = None
40
45
  self._cached_token = None
46
+ self._environment = environment
47
+ self._allow_ntlm = allow_ntlm
48
+ self._browser_mode = browser_mode
41
49
 
42
50
  def with_client_certificate(
43
51
  self,
@@ -71,7 +79,9 @@ class AuthenticationContext(object):
71
79
  private_key = f.read()
72
80
 
73
81
  def _acquire_token():
74
- authority_url = "https://login.microsoftonline.com/{0}".format(tenant)
82
+ authority_url = "{0}/{1}".format(
83
+ AzureEnvironment.get_login_authority(self._environment), tenant
84
+ )
75
85
  credentials = {
76
86
  "thumbprint": thumbprint,
77
87
  "private_key": private_key,
@@ -110,7 +120,9 @@ class AuthenticationContext(object):
110
120
 
111
121
  app = msal.PublicClientApplication(
112
122
  client_id,
113
- authority="https://login.microsoftonline.com/{0}".format(tenant),
123
+ authority="{0}/{1}".format(
124
+ AzureEnvironment.get_login_authority(self._environment), tenant
125
+ ),
114
126
  client_credential=None,
115
127
  )
116
128
  result = app.acquire_token_interactive(scopes=scopes)
@@ -136,7 +148,9 @@ class AuthenticationContext(object):
136
148
 
137
149
  app = msal.PublicClientApplication(
138
150
  client_id,
139
- authority="https://login.microsoftonline.com/{0}".format(tenant),
151
+ authority="{0}/{1}".format(
152
+ AzureEnvironment.get_login_authority(self._environment), tenant
153
+ ),
140
154
  client_credential=None,
141
155
  )
142
156
 
@@ -171,54 +185,56 @@ class AuthenticationContext(object):
171
185
  )
172
186
 
173
187
  self._authenticate = _authenticate
188
+ return self
174
189
 
175
- def with_credentials(self, credentials, **kwargs):
190
+ def with_credentials(self, credentials):
191
+ # type: (UserCredential | ClientCredential) -> "AuthenticationContext"
176
192
  """
177
193
  Initializes a client to acquire a token via user or client credentials
178
-
179
- :param UserCredential or ClientCredential credentials:
180
194
  """
181
195
  if isinstance(credentials, ClientCredential):
182
- environment = kwargs.get("environment")
183
196
  provider = ACSTokenProvider(
184
- self.url, credentials.clientId, credentials.clientSecret, environment
197
+ self.url,
198
+ credentials.clientId,
199
+ credentials.clientSecret,
200
+ self._environment,
185
201
  )
186
202
  elif isinstance(credentials, UserCredential):
187
- allow_ntlm = kwargs.get("allow_ntlm", False)
188
- if allow_ntlm:
203
+ if self._allow_ntlm:
189
204
  from office365.runtime.auth.providers.ntlm_provider import NtlmProvider
190
205
 
191
206
  provider = NtlmProvider(credentials.userName, credentials.password)
192
207
  else:
193
- browser_mode = kwargs.get("browser_mode", False)
194
- environment = kwargs.get("environment")
195
208
  provider = SamlTokenProvider(
196
209
  self.url,
197
210
  credentials.userName,
198
211
  credentials.password,
199
- browser_mode,
200
- environment,
212
+ self._browser_mode,
213
+ self._environment,
201
214
  )
202
215
  else:
203
216
  raise ValueError("Unknown credential type")
204
217
 
205
218
  def _authenticate(request):
219
+ # type: (RequestOptions) -> None
206
220
  provider.authenticate_request(request)
207
221
 
208
222
  self._authenticate = _authenticate
223
+ return self
209
224
 
210
- def acquire_token_for_user(self, username, password, browser_mode=False):
225
+ def acquire_token_for_user(self, username, password):
226
+ # type: (str, str) -> Self
211
227
  """
212
228
  Initializes a client to acquire a token via user credentials
213
229
  Status: deprecated!
214
230
 
215
231
  :param str password: The user password
216
232
  :param str username: Typically a UPN in the form of an email address
217
- :param bool browser_mode:
218
233
  """
219
- provider = SamlTokenProvider(self.url, username, password, browser_mode)
234
+ provider = SamlTokenProvider(self.url, username, password, self._browser_mode)
220
235
 
221
236
  def _authenticate(request):
237
+ # type: (RequestOptions) -> None
222
238
  provider.authenticate_request(request)
223
239
 
224
240
  self._authenticate = _authenticate
@@ -236,6 +252,7 @@ class AuthenticationContext(object):
236
252
  provider = ACSTokenProvider(self.url, client_id, client_secret)
237
253
 
238
254
  def _authenticate(request):
255
+ # type: (RequestOptions) -> None
239
256
  provider.authenticate_request(request)
240
257
 
241
258
  self._authenticate = _authenticate
File without changes
@@ -0,0 +1,165 @@
1
+ from typing import Optional
2
+
3
+ from office365.azure_env import AzureEnvironment
4
+ from office365.runtime.auth.token_response import TokenResponse
5
+
6
+
7
+ class AuthenticationContext(object):
8
+ """Provides authentication context for Microsoft Graph client"""
9
+
10
+ def __init__(
11
+ self,
12
+ tenant=None,
13
+ scopes=None,
14
+ token_cache=None,
15
+ environment=AzureEnvironment.Global,
16
+ ):
17
+ """
18
+ :param str tenant: Tenant name, for example: contoso.onmicrosoft.com
19
+ :param list[str] or None scopes: Scopes requested to access an API
20
+ :param Any token_cache: Default cache is in memory only,
21
+ Refer https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
22
+ """
23
+ self._tenant = tenant
24
+ if scopes is None:
25
+ scopes = [
26
+ "{0}/.default".format(AzureEnvironment.get_graph_authority(environment))
27
+ ]
28
+ self._scopes = scopes
29
+ self._token_cache = token_cache
30
+ self._token_callback = None
31
+ self._environment = environment
32
+
33
+ def acquire_token(self):
34
+ # type: () -> TokenResponse
35
+ """Acquire access token"""
36
+ if not self._token_callback:
37
+ raise ValueError("Token callback is not set.")
38
+ token_resp = self._token_callback()
39
+ token = TokenResponse.from_json(token_resp)
40
+ return token
41
+
42
+ def with_access_token(self, token_callback):
43
+ """"""
44
+ self._token_callback = token_callback
45
+ return self
46
+
47
+ def with_certificate(self, client_id, thumbprint, private_key):
48
+ """
49
+ Initializes the confidential client with client certificate
50
+
51
+ :param str client_id: The OAuth client id of the calling application.
52
+ :param str thumbprint: Thumbprint
53
+ :param str private_key: Private key
54
+ """
55
+ import msal
56
+
57
+ app = msal.ConfidentialClientApplication(
58
+ client_id,
59
+ authority=self.authority_url,
60
+ client_credential={
61
+ "thumbprint": thumbprint,
62
+ "private_key": private_key,
63
+ },
64
+ token_cache=self._token_cache, # Default cache is in memory only.
65
+ # You can learn how to use SerializableTokenCache from
66
+ # https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
67
+ )
68
+
69
+ def _acquire_token():
70
+ return app.acquire_token_for_client(scopes=self._scopes)
71
+
72
+ return self.with_access_token(_acquire_token)
73
+
74
+ def with_client_secret(self, client_id, client_secret):
75
+ # type: (str, str) -> "AuthenticationContext"
76
+ """
77
+ Initializes the confidential client with client secret
78
+
79
+ :param str client_id: The OAuth client id of the calling application.
80
+ :param str client_secret: Client secret
81
+ """
82
+ import msal
83
+
84
+ app = msal.ConfidentialClientApplication(
85
+ client_id,
86
+ authority=self.authority_url,
87
+ client_credential=client_secret,
88
+ token_cache=self._token_cache,
89
+ )
90
+
91
+ def _acquire_token():
92
+ return app.acquire_token_for_client(scopes=self._scopes)
93
+
94
+ return self.with_access_token(_acquire_token)
95
+
96
+ def with_token_interactive(self, client_id, username=None):
97
+ # type: (str, Optional[str]) -> "AuthenticationContext"
98
+ """
99
+ Initializes the client via user credentials
100
+ Note: only works if your app is registered with redirect_uri as http://localhost
101
+
102
+ :param str client_id: The OAuth client id of the calling application.
103
+ :param str username: Typically a UPN in the form of an email address.
104
+ """
105
+ import msal
106
+
107
+ app = msal.PublicClientApplication(client_id, authority=self.authority_url)
108
+
109
+ def _acquire_token():
110
+ # The pattern to acquire a token looks like this.
111
+ result = None
112
+
113
+ # Firstly, check the cache to see if this end user has signed in before
114
+ accounts = app.get_accounts(username=username)
115
+ if accounts:
116
+ chosen = accounts[0] # Assuming the end user chose this one to proceed
117
+ # Now let's try to find a token in cache for this account
118
+ result = app.acquire_token_silent(self._scopes, account=chosen)
119
+
120
+ if not result:
121
+ result = app.acquire_token_interactive(
122
+ self._scopes,
123
+ login_hint=username,
124
+ )
125
+ return result
126
+
127
+ return self.with_access_token(_acquire_token)
128
+
129
+ def with_username_and_password(self, client_id, username, password):
130
+ # type: (str, str, str) -> "AuthenticationContext"
131
+ """
132
+ Initializes the client via user credentials
133
+
134
+ :param str client_id: The OAuth client id of the calling application.
135
+ :param str username: Typically a UPN in the form of an email address.
136
+ :param str password: The password.
137
+ """
138
+ import msal
139
+
140
+ app = msal.PublicClientApplication(
141
+ authority=self.authority_url,
142
+ client_id=client_id,
143
+ )
144
+
145
+ def _acquire_token():
146
+ result = None
147
+ accounts = app.get_accounts(username=username)
148
+ if accounts:
149
+ result = app.acquire_token_silent(self._scopes, account=accounts[0])
150
+
151
+ if not result:
152
+ result = app.acquire_token_by_username_password(
153
+ username=username,
154
+ password=password,
155
+ scopes=self._scopes,
156
+ )
157
+ return result
158
+
159
+ return self.with_access_token(_acquire_token)
160
+
161
+ @property
162
+ def authority_url(self):
163
+ return "{0}/{1}".format(
164
+ AzureEnvironment.get_login_authority(self._environment), self._tenant
165
+ )
@@ -3,6 +3,7 @@ from typing import Optional
3
3
  import requests
4
4
 
5
5
  import office365.logger
6
+ from office365.azure_env import AzureEnvironment
6
7
  from office365.runtime.auth.authentication_provider import AuthenticationProvider
7
8
  from office365.runtime.auth.token_response import TokenResponse
8
9
  from office365.runtime.compat import urlparse
@@ -10,7 +11,7 @@ from office365.runtime.http.request_options import RequestOptions
10
11
 
11
12
 
12
13
  class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
13
- def __init__(self, url, client_id, client_secret, environment="commercial"):
14
+ def __init__(self, url, client_id, client_secret, environment=None):
14
15
  """
15
16
  Provider to acquire the access token from a Microsoft Azure Access Control Service (ACS)
16
17
 
@@ -18,7 +19,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
18
19
  :param str client_secret: Secret string that the application uses to prove its identity when requesting a token
19
20
  :param str url: SharePoint web or site url
20
21
  :param str environment: The Office 365 Cloud Environment endpoint used for authentication
21
- defaults to 'commercial'.
22
+ defaults to 'Azure Global'.
22
23
  """
23
24
  self.url = url
24
25
  self.redirect_url = None
@@ -26,18 +27,14 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
26
27
  self.SharePointPrincipal = "00000003-0000-0ff1-ce00-000000000000"
27
28
  self._client_id = client_id
28
29
  self._client_secret = client_secret
29
- self._cached_token = None
30
+ self._cached_token = None # type: Optional[TokenResponse]
30
31
  self._environment = environment
31
32
 
32
33
  def authenticate_request(self, request):
33
34
  # type: (RequestOptions) -> None
34
- self.ensure_app_only_access_token()
35
- request.set_header("Authorization", self._get_authorization_header())
36
-
37
- def ensure_app_only_access_token(self):
38
35
  if self._cached_token is None:
39
36
  self._cached_token = self.get_app_only_access_token()
40
- return self._cached_token and self._cached_token.is_valid
37
+ request.set_header("Authorization", self._cached_token.authorization_header)
41
38
 
42
39
  def get_app_only_access_token(self):
43
40
  """Retrieves an app-only access token from ACS"""
@@ -65,9 +62,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
65
62
  self.SharePointPrincipal, target_host, target_realm
66
63
  )
67
64
  principal_id = self.get_formatted_principal(self._client_id, None, target_realm)
68
- sts_url = self.get_security_token_service_url(
69
- target_realm, environment=self._environment
70
- )
65
+ sts_url = self.get_security_token_service_url(target_realm)
71
66
  oauth2_request = {
72
67
  "grant_type": "client_credentials",
73
68
  "client_id": principal_id,
@@ -86,11 +81,6 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
86
81
  def _get_realm_from_target_url(self):
87
82
  """Get the realm for the URL"""
88
83
  response = requests.head(url=self.url, headers={"Authorization": "Bearer"})
89
- return self.process_realm_response(response)
90
-
91
- @staticmethod
92
- def process_realm_response(response):
93
- # type: (requests.Response) -> Optional[str]
94
84
  header_key = "WWW-Authenticate"
95
85
  if header_key in response.headers:
96
86
  auth_values = response.headers[header_key].split(",")
@@ -105,20 +95,15 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
105
95
  return "{0}/{1}@{2}".format(principal_name, host_name, realm)
106
96
  return "{0}@{1}".format(principal_name, realm)
107
97
 
108
- @staticmethod
109
- def get_security_token_service_url(realm, environment):
110
- # type: (str, str) -> str
111
- if environment == "GCCH":
112
- return "https://login.microsoftonline.us/{0}/tokens/OAuth/2".format(realm)
98
+ def get_security_token_service_url(self, realm):
99
+ # type: (str) -> str
100
+ if self._environment:
101
+ return "{0}/{1}/tokens/OAuth/2".format(
102
+ AzureEnvironment.get_login_authority(self._environment), realm
103
+ )
113
104
  else:
114
105
  return (
115
106
  "https://accounts.accesscontrol.windows.net/{0}/tokens/OAuth/2".format(
116
107
  realm
117
108
  )
118
109
  )
119
-
120
- def _get_authorization_header(self):
121
- return "Bearer {0}".format(self._cached_token.accessToken)
122
-
123
- def get_last_error(self):
124
- return self.error
@@ -1,5 +1,7 @@
1
1
  import os
2
2
  import uuid
3
+ from datetime import datetime, timezone
4
+ from typing import Optional
3
5
  from xml.dom import minidom
4
6
  from xml.etree import ElementTree
5
7
 
@@ -7,6 +9,7 @@ import requests
7
9
  import requests.utils
8
10
 
9
11
  import office365.logger
12
+ from office365.runtime.auth.auth_cookies import AuthCookies
10
13
  from office365.runtime.auth.authentication_provider import AuthenticationProvider
11
14
  from office365.runtime.auth.sts_profile import STSProfile
12
15
  from office365.runtime.auth.user_realm_info import UserRealmInfo
@@ -20,23 +23,17 @@ def resolve_base_url(url):
20
23
  return parts[0] + "://" + host_name
21
24
 
22
25
 
23
- def xml_escape(s_val):
24
- s_val = s_val.replace("&", "&")
25
- s_val = s_val.replace("<", "&lt;")
26
- s_val = s_val.replace(">", "&gt;")
27
- s_val = s_val.replace('"', "&quot;")
28
- s_val = s_val.replace("'", "&apos;")
29
- return s_val
26
+ def string_escape(value):
27
+ value = value.replace("&", "&amp;")
28
+ value = value.replace("<", "&lt;")
29
+ value = value.replace(">", "&gt;")
30
+ value = value.replace('"', "&quot;")
31
+ value = value.replace("'", "&apos;")
32
+ return value
30
33
 
31
34
 
32
- def is_valid_auth_cookies(values):
33
- """
34
- Validates authorization cookies
35
- """
36
- return any(values) and (
37
- values.get("FedAuth", None) is not None
38
- or values.get("SPOIDCRL", None) is not None
39
- )
35
+ def datetime_escape(value):
36
+ return value.isoformat("T")[:-9] + "Z"
40
37
 
41
38
 
42
39
  class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
@@ -60,7 +57,7 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
60
57
  self.error = ""
61
58
  self._username = username
62
59
  self._password = password
63
- self._cached_auth_cookies = None
60
+ self._cached_auth_cookies = None # type: Optional[AuthCookies]
64
61
  self.__ns_prefixes = {
65
62
  "S": "{http://www.w3.org/2003/05/soap-envelope}",
66
63
  "s": "{http://www.w3.org/2003/05/soap-envelope}",
@@ -82,24 +79,20 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
82
79
  Authenticate request handler
83
80
  """
84
81
  logger = self.logger(self.authenticate_request.__name__)
85
- self.ensure_authentication_cookie()
86
- logger.debug_secrets(self._cached_auth_cookies)
87
- cookie_header_value = "; ".join(
88
- [
89
- "=".join([key, str(val)])
90
- for key, val in self._cached_auth_cookies.items()
91
- ]
92
- )
93
- request.set_header("Cookie", cookie_header_value)
94
82
 
95
- def ensure_authentication_cookie(self):
96
- if self._cached_auth_cookies is None:
83
+ request_time = datetime.now(timezone.utc)
84
+ if (
85
+ self._cached_auth_cookies is None
86
+ or request_time >= self._sts_profile.expires
87
+ ):
88
+ self._sts_profile.reset()
97
89
  self._cached_auth_cookies = self.get_authentication_cookie()
98
- return True
90
+ logger.debug_secrets(self._cached_auth_cookies)
91
+ request.set_header("Cookie", self._cached_auth_cookies.cookie_header)
99
92
 
100
93
  def get_authentication_cookie(self):
101
94
  """Acquire authentication cookie"""
102
- logger = self.logger(self.ensure_authentication_cookie.__name__)
95
+ logger = self.logger(self.get_authentication_cookie.__name__)
103
96
  logger.debug("get_authentication_cookie called")
104
97
 
105
98
  try:
@@ -132,9 +125,6 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
132
125
  return info
133
126
  return None
134
127
 
135
- def get_last_error(self):
136
- return self.error
137
-
138
128
  def _acquire_service_token_from_adfs(self, adfs_url):
139
129
  logger = self.logger(self._acquire_service_token_from_adfs.__name__)
140
130
 
@@ -143,10 +133,10 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
143
133
  {
144
134
  "auth_url": adfs_url,
145
135
  "message_id": str(uuid.uuid4()),
146
- "username": xml_escape(self._username),
147
- "password": xml_escape(self._password),
148
- "created": self._sts_profile.created,
149
- "expires": self._sts_profile.expires,
136
+ "username": string_escape(self._username),
137
+ "password": string_escape(self._password),
138
+ "created": datetime_escape(self._sts_profile.created),
139
+ "expires": datetime_escape(self._sts_profile.expires),
150
140
  "issuer": self._sts_profile.tokenIssuer,
151
141
  },
152
142
  )
@@ -195,11 +185,11 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
195
185
  "SAML.xml",
196
186
  {
197
187
  "auth_url": self._sts_profile.authorityUrl,
198
- "username": xml_escape(self._username),
199
- "password": xml_escape(self._password),
188
+ "username": string_escape(self._username),
189
+ "password": string_escape(self._password),
200
190
  "message_id": str(uuid.uuid4()),
201
- "created": self._sts_profile.created,
202
- "expires": self._sts_profile.expires,
191
+ "created": datetime_escape(self._sts_profile.created),
192
+ "expires": datetime_escape(self._sts_profile.expires),
203
193
  "issuer": self._sts_profile.tokenIssuer,
204
194
  },
205
195
  )
@@ -300,9 +290,9 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
300
290
  },
301
291
  )
302
292
  logger.debug_secrets("session.cookies: %s", session.cookies)
303
- cookies = requests.utils.dict_from_cookiejar(session.cookies)
293
+ cookies = AuthCookies(requests.utils.dict_from_cookiejar(session.cookies))
304
294
  logger.debug_secrets("cookies: %s", cookies)
305
- if not is_valid_auth_cookies(cookies):
295
+ if not cookies.is_valid:
306
296
  self.error = (
307
297
  "An error occurred while retrieving auth cookies from {0}".format(
308
298
  self._sts_profile.signin_page_url
@@ -312,19 +302,16 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
312
302
  raise ValueError(self.error)
313
303
  return cookies
314
304
 
315
- @staticmethod
316
- def _prepare_request_from_template(template_name, params):
305
+ def _prepare_request_from_template(self, template_name, params):
317
306
  """Construct the request body to acquire security token from STS endpoint"""
318
- logger = SamlTokenProvider.logger()
307
+ logger = self.logger(self._prepare_request_from_template.__name__)
319
308
  logger.debug_secrets("params: %s", params)
320
- f = open(
321
- os.path.join(os.path.dirname(__file__), "templates", template_name),
322
- encoding="utf8",
309
+
310
+ template_path = os.path.join(
311
+ os.path.dirname(__file__), "templates", template_name
323
312
  )
324
- try:
313
+
314
+ with open(template_path, encoding="utf8") as f:
325
315
  data = f.read()
326
- for key in params:
327
- data = data.replace("{" + key + "}", str(params[key]))
328
- return data
329
- finally:
330
- f.close()
316
+
317
+ return data.format(**params)
@@ -5,9 +5,7 @@ from office365.runtime.compat import timezone, urlparse
5
5
 
6
6
  class STSProfile(object):
7
7
  def __init__(self, authority_url, environment):
8
- """
9
- :type authority_url: str
10
- """
8
+ # type: (str, str) -> None
11
9
  self.authorityUrl = authority_url
12
10
  if environment == "GCCH":
13
11
  self.serviceUrl = "https://login.microsoftonline.us"
@@ -16,13 +14,15 @@ class STSProfile(object):
16
14
  self.securityTokenServicePath = "extSTS.srf"
17
15
  self.userRealmServicePath = "GetUserRealm.srf"
18
16
  self.tokenIssuer = "urn:federation:MicrosoftOnline"
19
- now = datetime.now(tz=timezone.utc)
20
- self.created = now.astimezone(timezone.utc).isoformat("T")[:-9] + "Z"
21
- self.expires = (now + timedelta(minutes=10)).astimezone(timezone.utc).isoformat(
22
- "T"
23
- )[:-9] + "Z"
17
+ self.created = datetime.now(tz=timezone.utc)
18
+ self.expires = self.created + timedelta(minutes=30)
24
19
  self.signInPage = "_forms/default.aspx?wa=wsignin1.0"
25
20
 
21
+ def reset(self):
22
+ """Renew the expiration time."""
23
+ self.created = datetime.now(tz=timezone.utc)
24
+ self.expires = self.created + timedelta(minutes=30)
25
+
26
26
  @property
27
27
  def tenant(self):
28
28
  return urlparse(self.authorityUrl).netloc
@@ -9,6 +9,10 @@ class TokenResponse(object):
9
9
  def is_valid(self):
10
10
  return self.accessToken is not None and self.tokenType == "Bearer"
11
11
 
12
+ @property
13
+ def authorization_header(self):
14
+ return "Bearer {0}".format(self.accessToken)
15
+
12
16
  @staticmethod
13
17
  def from_json(value):
14
18
  error = value.get("error", None)