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.
- {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/METADATA +2 -2
- {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/RECORD +324 -169
- office365/admin/admin.py +69 -0
- office365/admin/microsoft365_apps.py +5 -0
- office365/admin/people_settings.py +5 -0
- office365/admin/report_settings.py +5 -0
- office365/{onedrive → admin}/sharepoint.py +1 -1
- office365/azure_env.py +60 -0
- office365/booking/business/business.py +13 -0
- office365/booking/business/collection.py +8 -4
- office365/communications/callrecords/collection.py +42 -0
- office365/communications/callrecords/direct_routing_log_row.py +5 -0
- office365/communications/cloud_communications.py +2 -3
- office365/directory/applications/app_ids.py +6 -0
- office365/directory/applications/application.py +16 -2
- office365/directory/applications/required_resource_access.py +23 -0
- office365/directory/applications/resource_access.py +26 -0
- office365/directory/authentication/authentication.py +16 -0
- office365/directory/authentication/method_target.py +2 -1
- office365/directory/authentication/methods/details.py +29 -0
- office365/directory/authentication/methods/microsoft_authenticator.py +6 -0
- office365/directory/authentication/methods/root.py +19 -0
- office365/directory/authentication/methods/sms.py +9 -0
- office365/directory/certificates/self_signed.py +31 -2
- office365/directory/identities/conditional_access_root.py +14 -0
- office365/directory/identitygovernance/privilegedaccess/approval.py +8 -0
- office365/directory/identitygovernance/privilegedaccess/group.py +30 -0
- office365/directory/identitygovernance/privilegedaccess/group_assignment_schedule_instance.py +7 -0
- office365/directory/identitygovernance/privilegedaccess/unified_role_assignment_schedule_request.py +7 -0
- office365/directory/identitygovernance/userconsent/request_collection.py +10 -0
- office365/directory/identitygovernance/workflow/__init__.py +0 -0
- office365/directory/identitygovernance/workflow/base.py +5 -0
- office365/directory/permissions/scope.py +15 -3
- office365/directory/policies/authentication_strength.py +21 -0
- office365/directory/policies/cross_tenant_access.py +13 -0
- office365/directory/policies/feature_rollout.py +16 -0
- office365/directory/policies/root.py +39 -23
- office365/directory/policies/template.py +5 -0
- office365/directory/policies/update_allowed_combinations_result.py +5 -0
- office365/directory/protection/threatassessment/email_file_request.py +20 -0
- office365/directory/protection/threatassessment/request.py +25 -0
- office365/directory/rolemanagement/application.py +15 -0
- office365/directory/rolemanagement/resource_action.py +8 -4
- office365/directory/rolemanagement/role_permission.py +3 -3
- office365/directory/security/alerts/collection.py +49 -0
- office365/directory/security/alerts/evidence.py +2 -1
- office365/directory/security/alerts/malware_evidence.py +5 -0
- office365/directory/security/alerts/process_evidence.py +5 -0
- office365/directory/security/attacksimulations/user.py +5 -0
- office365/directory/security/attacksimulations/user_coverage.py +3 -0
- office365/directory/security/attacksimulations/users/details.py +6 -1
- office365/directory/security/scorecontrol/__init__.py +0 -0
- office365/directory/security/scorecontrol/profile.py +6 -0
- office365/directory/security/security.py +17 -4
- office365/directory/serviceprincipals/service_principal.py +112 -55
- office365/directory/tenantinformation/__init__.py +0 -0
- office365/directory/tenantinformation/multi_organization.py +11 -0
- office365/directory/tenantinformation/relationship.py +61 -0
- office365/directory/users/insights_settings.py +5 -0
- office365/graph_client.py +52 -132
- office365/graph_request.py +78 -19
- office365/intune/servicecommunications/health/health.py +1 -1
- office365/intune/servicecommunications/issues/issue.py +2 -2
- office365/onedrive/columns/definition.py +1 -1
- office365/onedrive/contenttypes/content_type.py +1 -1
- office365/onedrive/driveitems/driveItem.py +14 -2
- office365/onedrive/driveitems/retention_label.py +33 -0
- office365/onedrive/driveitems/retention_label_settings.py +7 -0
- office365/onedrive/drives/drive.py +1 -1
- office365/onedrive/filestorage/__init__.py +0 -0
- office365/onedrive/filestorage/container.py +7 -0
- office365/onedrive/filestorage/file_storage.py +20 -0
- office365/onedrive/listitems/field_value_set.py +1 -1
- office365/onedrive/listitems/list_item.py +1 -1
- office365/onedrive/lists/list.py +1 -1
- office365/onedrive/recyclebin/__init__.py +0 -0
- office365/onedrive/recyclebin/item.py +6 -0
- office365/onedrive/recyclebin/recyclebin.py +29 -0
- office365/onedrive/recyclebin/settings.py +13 -0
- office365/onedrive/shares/drive_item.py +1 -1
- office365/onedrive/sitepages/base.py +4 -1
- office365/onedrive/sitepages/canvas_layout.py +2 -2
- office365/onedrive/sitepages/collection.py +12 -0
- office365/onedrive/sitepages/sections/__init__.py +0 -0
- office365/onedrive/sitepages/{horizontal_section.py → sections/horizontal.py} +1 -1
- office365/onedrive/sitepages/site_page.py +9 -9
- office365/onedrive/sitepages/webparts/data.py +5 -0
- office365/onedrive/sitepages/webparts/position.py +5 -0
- office365/onedrive/sitepages/webparts/standard.py +9 -0
- office365/onedrive/sitepages/webparts/web_part.py +12 -0
- office365/onedrive/sites/archival_details.py +5 -0
- office365/onedrive/sites/site.py +1 -1
- office365/onedrive/sites/site_collection.py +10 -1
- office365/onedrive/storage/storage.py +10 -0
- office365/onedrive/workbooks/charts/axes.py +41 -1
- office365/onedrive/workbooks/charts/axis.py +5 -0
- office365/onedrive/workbooks/charts/chart.py +64 -5
- office365/onedrive/workbooks/charts/fill.py +5 -0
- office365/onedrive/workbooks/charts/font.py +5 -0
- office365/onedrive/workbooks/charts/legend/__init__.py +0 -0
- office365/onedrive/workbooks/charts/legend/format.py +5 -0
- office365/onedrive/workbooks/charts/legend/legend.py +26 -0
- office365/onedrive/workbooks/charts/point.py +5 -0
- office365/onedrive/workbooks/charts/series/__init__.py +0 -0
- office365/onedrive/workbooks/charts/series/format.py +5 -0
- office365/onedrive/workbooks/charts/series/series.py +31 -0
- office365/onedrive/workbooks/charts/title.py +5 -0
- office365/onedrive/workbooks/filter.py +10 -0
- office365/onedrive/workbooks/filter_criteria.py +3 -3
- office365/onedrive/workbooks/functions/functions.py +23 -0
- office365/onedrive/workbooks/ranges/fill.py +11 -1
- office365/onedrive/workbooks/ranges/range.py +26 -0
- office365/onedrive/workbooks/ranges/view.py +14 -0
- office365/onedrive/workbooks/sort_field.py +8 -3
- office365/onedrive/workbooks/tables/sort.py +20 -0
- office365/onedrive/workbooks/worksheets/worksheet.py +11 -0
- office365/partners/__init__.py +0 -0
- office365/partners/billing/__init__.py +0 -0
- office365/partners/billing/azure_usage.py +17 -0
- office365/partners/billing/billed_usage.py +21 -0
- office365/partners/billing/billing.py +17 -0
- office365/partners/billing/operation.py +5 -0
- office365/partners/partners.py +17 -0
- office365/planner/tasks/check_list_item.py +5 -1
- office365/reports/root.py +9 -0
- office365/reports/userregistration/feature_summary.py +5 -0
- office365/runtime/auth/auth_cookies.py +48 -0
- office365/runtime/auth/authentication_context.py +36 -19
- office365/runtime/auth/entra/__init__.py +0 -0
- office365/runtime/auth/entra/authentication_context.py +165 -0
- office365/runtime/auth/providers/acs_token_provider.py +12 -27
- office365/runtime/auth/providers/saml_token_provider.py +41 -54
- office365/runtime/auth/sts_profile.py +8 -8
- office365/runtime/auth/token_response.py +4 -0
- office365/runtime/client_object.py +15 -7
- office365/runtime/client_object_collection.py +2 -2
- office365/runtime/client_result.py +2 -0
- office365/runtime/client_value.py +1 -1
- office365/runtime/csom/request.py +11 -0
- office365/runtime/types/exceptions.py +18 -0
- office365/search/acronym.py +10 -0
- office365/search/aggregation_option.py +6 -0
- office365/search/answer.py +9 -0
- office365/search/entity.py +67 -14
- office365/search/entity_type.py +28 -0
- office365/search/request.py +32 -3
- office365/sharepoint/administration/custom_fonts_resource.py +5 -0
- office365/sharepoint/administration/sitemove/__init__.py +0 -0
- office365/sharepoint/administration/sitemove/service.py +68 -0
- office365/sharepoint/administration/sitemove/service_info.py +11 -0
- office365/sharepoint/apps/access_requests.py +5 -0
- office365/sharepoint/apps/management/__init__.py +0 -0
- office365/sharepoint/apps/management/principal_info.py +9 -0
- office365/sharepoint/authpolicy/events/collection.py +28 -0
- office365/sharepoint/authpolicy/events/role_assignment_resource_payload.py +4 -0
- office365/sharepoint/changes/item.py +15 -0
- office365/sharepoint/client_context.py +61 -37
- office365/sharepoint/directory/group.py +2 -0
- office365/sharepoint/directory/helper.py +2 -0
- office365/sharepoint/directory/provider/provider.py +6 -0
- office365/sharepoint/directory/user.py +20 -0
- office365/sharepoint/documentmanagement/document_id.py +28 -3
- office365/sharepoint/files/file.py +11 -4
- office365/sharepoint/files/publish/__init__.py +0 -0
- office365/sharepoint/files/publish/status.py +9 -0
- office365/sharepoint/files/versions/event.py +9 -0
- office365/sharepoint/flows/connector_result.py +17 -0
- office365/sharepoint/flows/permissions.py +34 -0
- office365/sharepoint/fontpackages/__init__.py +0 -0
- office365/sharepoint/fontpackages/collection.py +26 -0
- office365/sharepoint/fontpackages/creation_parameters.py +5 -0
- office365/sharepoint/fontpackages/font_package.py +5 -0
- office365/sharepoint/fontpackages/oob_settings.py +5 -0
- office365/sharepoint/forms/customization.py +26 -0
- office365/sharepoint/ir/__init__.py +0 -0
- office365/sharepoint/ir/migration.py +5 -0
- office365/sharepoint/listhome/favorite_item.py +9 -0
- office365/sharepoint/listitems/listitem.py +79 -4
- office365/sharepoint/listitems/update_parameters.py +4 -1
- office365/sharepoint/lists/data_parameters.py +5 -0
- office365/sharepoint/lists/exporter.py +73 -0
- office365/sharepoint/lists/list.py +177 -60
- office365/sharepoint/lists/render_data_parameters.py +31 -0
- office365/sharepoint/lists/version_policy_manager.py +5 -0
- office365/sharepoint/marketplace/app_metadata.py +12 -1
- office365/sharepoint/marketplace/app_metadata_collection.py +8 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/instance_info.py +22 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_failed_info.py +5 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_info.py +12 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_response.py +15 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/principals_response.py +5 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/app_request_information.py +9 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/app_response_information.py +9 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/available_addins_response.py +4 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/card_design.py +9 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/card_designs.py +9 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/teams_package_download.py +14 -0
- office365/sharepoint/marketplace/tenant/appcatalog/accessor.py +62 -3
- office365/sharepoint/migration/copy_migration_options.py +5 -0
- office365/sharepoint/multigeo/services.py +14 -0
- office365/sharepoint/multigeo/storage_quota.py +9 -0
- office365/sharepoint/policy/license_utilities.py +27 -0
- office365/sharepoint/portal/groups/site_manager.py +32 -0
- office365/sharepoint/portal/project/__init__.py +9 -0
- office365/sharepoint/portal/userprofiles/documentsshared/__init__.py +0 -0
- office365/sharepoint/portal/userprofiles/documentsshared/with_group.py +38 -0
- office365/sharepoint/portal/userprofiles/documentsshared/with_person.py +9 -0
- office365/sharepoint/portal/userprofiles/sharedwithme/__init__.py +0 -0
- office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/document.py +1 -1
- office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/items.py +3 -1
- office365/sharepoint/principal/principal.py +6 -0
- office365/sharepoint/publishing/pages/coauth_state.py +8 -0
- office365/sharepoint/publishing/pages/page.py +11 -0
- office365/sharepoint/publishing/pages/stream_content.py +9 -0
- office365/sharepoint/publishing/pages/stream_data.py +8 -0
- office365/sharepoint/quotamanagement/consumer/non_quota_backfill_api.py +8 -0
- office365/sharepoint/request.py +98 -10
- office365/sharepoint/search/administration/document_crawl_log.py +16 -2
- office365/sharepoint/search/administration/site_content_processing_info_provider.py +11 -0
- office365/sharepoint/search/administration/tenant_crawl_versions_info_provider.py +1 -1
- office365/sharepoint/search/ranking_labeling.py +1 -0
- office365/sharepoint/search/reports/abandoned_queries.py +11 -1
- office365/sharepoint/search/reports/abandonedqueries/__init__.py +0 -0
- office365/sharepoint/search/reports/abandonedqueries/data.py +0 -0
- office365/sharepoint/search/reports/abandonedqueries/item.py +11 -0
- office365/sharepoint/search/reports/noresult/__init__.py +0 -0
- office365/sharepoint/search/reports/numberofqueries/__init__.py +0 -0
- office365/sharepoint/search/reports/top_queries.py +7 -0
- office365/sharepoint/search/reports/topqueries/__init__.py +0 -0
- office365/sharepoint/search/reports/topqueries/data.py +9 -0
- office365/sharepoint/search/reports/topqueries/item.py +15 -0
- office365/sharepoint/search/scs_endpoint.py +9 -0
- office365/sharepoint/securestore/target_application.py +8 -0
- office365/sharepoint/sharing/document_manager.py +3 -3
- office365/sharepoint/sharing/domain_restriction_settings.py +5 -0
- office365/sharepoint/sharing/information.py +12 -0
- office365/sharepoint/sharing/result.py +21 -0
- office365/sharepoint/sitehealth/result.py +4 -4
- office365/sharepoint/sitehealth/summary.py +5 -5
- office365/sharepoint/sites/copy_job_progress.py +5 -0
- office365/sharepoint/sites/copy_migration_iInfo.py +5 -0
- office365/sharepoint/sites/home/__init__.py +0 -0
- office365/sharepoint/sites/{sph_site.py → home/site.py} +1 -1
- office365/sharepoint/sites/html_field_security_setting.py +5 -0
- office365/sharepoint/sites/site.py +56 -2
- office365/sharepoint/sites/version_policy_manager.py +25 -0
- office365/sharepoint/sitescripts/metadata.py +28 -3
- office365/sharepoint/sitescripts/utility.py +17 -0
- office365/sharepoint/smartcache/__init__.py +0 -0
- office365/sharepoint/smartcache/item.py +9 -0
- office365/sharepoint/tenant/administration/app_service_principal_public.py +17 -0
- office365/sharepoint/tenant/administration/audit/data.py +12 -0
- office365/sharepoint/tenant/administration/audit/unified_record.py +18 -0
- office365/sharepoint/tenant/administration/coms/__init__.py +0 -0
- office365/sharepoint/tenant/administration/coms/messages_fields_data.py +5 -0
- office365/sharepoint/tenant/administration/coms/messages_service_proxy.py +16 -0
- office365/sharepoint/tenant/administration/copilot/__init__.py +0 -0
- office365/sharepoint/tenant/administration/copilot/adaptive_card_config.py +11 -0
- office365/sharepoint/tenant/administration/datagovernance/__init__.py +0 -0
- office365/sharepoint/tenant/administration/{internal/permission_grant.py → datagovernance/client_base.py} +4 -2
- office365/sharepoint/tenant/administration/datagovernance/insight_client.py +82 -0
- office365/sharepoint/tenant/administration/datagovernance/insight_metadata.py +5 -0
- office365/sharepoint/tenant/administration/default_time_zone_id.py +11 -0
- office365/sharepoint/tenant/administration/endpoints.py +53 -2
- office365/sharepoint/tenant/administration/insights/onedrive_site_sharing.py +4 -0
- office365/sharepoint/tenant/administration/insights/summary_response.py +8 -0
- office365/sharepoint/tenant/administration/internal/aad/__init__.py +0 -0
- office365/sharepoint/tenant/administration/internal/aad/permission_grant.py +32 -0
- office365/sharepoint/tenant/administration/internal/appservice/__init__.py +0 -0
- office365/sharepoint/tenant/administration/internal/appservice/permission_grant.py +5 -0
- office365/sharepoint/tenant/administration/internal/appservice/permission_request.py +13 -0
- office365/sharepoint/tenant/administration/internal/appservice/principal.py +104 -0
- office365/sharepoint/tenant/administration/malware/__init__.py +0 -0
- office365/sharepoint/tenant/administration/malware/file.py +18 -0
- office365/sharepoint/tenant/administration/modified_property.py +5 -0
- office365/sharepoint/tenant/administration/policies/app_billing_properties.py +21 -0
- office365/sharepoint/tenant/administration/policies/content_security_configuration.py +9 -0
- office365/sharepoint/tenant/administration/recent_action.py +9 -0
- office365/sharepoint/tenant/administration/reports/__init__.py +0 -0
- office365/sharepoint/tenant/administration/settings_service.py +42 -6
- office365/sharepoint/tenant/administration/sites/creation_source.py +8 -8
- office365/sharepoint/tenant/administration/sites/properties.py +78 -0
- office365/sharepoint/tenant/administration/sites/properties_collection.py +19 -0
- office365/sharepoint/tenant/administration/tenant.py +241 -8
- office365/sharepoint/tenant/administration/types.py +89 -2
- office365/sharepoint/tenant/cdn_api.py +3 -1
- office365/sharepoint/tenant/insights/report_manager.py +29 -0
- office365/sharepoint/tenant/management/office365_tenant.py +9 -4
- office365/sharepoint/tenant/settings.py +10 -0
- office365/sharepoint/translation/job_status.py +22 -0
- office365/sharepoint/userprofiles/user_profile.py +6 -0
- office365/sharepoint/utilities/utility.py +6 -0
- office365/sharepoint/viva/connections_page.py +8 -0
- office365/sharepoint/viva/dashboard_configuration.py +8 -0
- office365/sharepoint/viva/employee_engagement.py +39 -1
- office365/sharepoint/viva/resource_get_endpoint.py +8 -0
- office365/sharepoint/viva/resource_link.py +8 -0
- office365/sharepoint/webparts/tile_data.py +21 -0
- office365/sharepoint/webs/dataleakage_prevention_status_info.py +5 -0
- office365/sharepoint/webs/information.py +66 -1
- office365/sharepoint/webs/regional_settings.py +32 -0
- office365/sharepoint/webs/templates/__init__.py +0 -0
- office365/sharepoint/webs/time_zone.py +1 -1
- office365/sharepoint/webs/web.py +137 -0
- office365/sharepoint/workflow/task.py +5 -0
- office365/subscriptions/collection.py +16 -0
- office365/teams/chats/event_message_detail.py +8 -0
- office365/teams/deleted.py +24 -0
- office365/teams/work.py +35 -0
- office365/directory/tenant_relationship.py +0 -23
- office365/onedrive/admin.py +0 -32
- office365/onedrive/workbooks/charts/legend.py +0 -7
- office365/onedrive/workbooks/charts/series.py +0 -5
- office365/sharepoint/portal/userprofiles/documents_shared_with_group.py +0 -11
- office365/sharepoint/tenant/administration/internal/web_appservice_principal.py +0 -23
- {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/LICENSE +0 -0
- {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/WHEEL +0 -0
- {Office365_REST_Python_Client-2.5.13.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/top_level.txt +0 -0
- /office365/{sharepoint/userprofiles/sharedwithme → admin}/__init__.py +0 -0
- /office365/{onedrive → admin}/sharepoint_settings.py +0 -0
- /office365/directory/{tenant_information.py → tenantinformation/information.py} +0 -0
- /office365/{base_item.py → onedrive/base_item.py} +0 -0
- /office365/onedrive/sitepages/{horizontal_section_column.py → sections/horizontal_column.py} +0 -0
- /office365/onedrive/sitepages/{vertical_section.py → sections/vertical.py} +0 -0
- /office365/sharepoint/portal/userprofiles/{documents_shared_with_me.py → documentsshared/with_me.py} +0 -0
- /office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/document_user.py +0 -0
- /office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/item_collection.py +0 -0
- /office365/sharepoint/{userprofiles → portal/userprofiles}/sharedwithme/view_item_removal_result.py +0 -0
- /office365/sharepoint/sites/{home_sites_details.py → home/details.py} +0 -0
- /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 = "
|
|
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="
|
|
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="
|
|
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
|
|
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,
|
|
197
|
+
self.url,
|
|
198
|
+
credentials.clientId,
|
|
199
|
+
credentials.clientSecret,
|
|
200
|
+
self._environment,
|
|
185
201
|
)
|
|
186
202
|
elif isinstance(credentials, UserCredential):
|
|
187
|
-
|
|
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
|
-
|
|
200
|
-
|
|
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
|
|
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,
|
|
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=
|
|
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 '
|
|
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
|
-
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return
|
|
26
|
+
def string_escape(value):
|
|
27
|
+
value = value.replace("&", "&")
|
|
28
|
+
value = value.replace("<", "<")
|
|
29
|
+
value = value.replace(">", ">")
|
|
30
|
+
value = value.replace('"', """)
|
|
31
|
+
value = value.replace("'", "'")
|
|
32
|
+
return value
|
|
30
33
|
|
|
31
34
|
|
|
32
|
-
def
|
|
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
|
-
|
|
96
|
-
if
|
|
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
|
-
|
|
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.
|
|
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":
|
|
147
|
-
"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":
|
|
199
|
-
"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
|
|
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
|
-
|
|
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 =
|
|
307
|
+
logger = self.logger(self._prepare_request_from_template.__name__)
|
|
319
308
|
logger.debug_secrets("params: %s", params)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
309
|
+
|
|
310
|
+
template_path = os.path.join(
|
|
311
|
+
os.path.dirname(__file__), "templates", template_name
|
|
323
312
|
)
|
|
324
|
-
|
|
313
|
+
|
|
314
|
+
with open(template_path, encoding="utf8") as f:
|
|
325
315
|
data = f.read()
|
|
326
|
-
|
|
327
|
-
|
|
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
|
-
|
|
20
|
-
self.
|
|
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)
|