16
16
Get the configured third-party storage providers for a given mailbox.
17
17
. Description
18
18
Using Exchange Web Services, any third-party storage providers configured for a mailbox (which can be
19
- configured via Outlook on the web) will be retrieved, including the account name
20
- configured for a given provider.
21
-
22
- Important: Requires the EWS Managed API to be installed on the local machine.
19
+ configured via Outlook on the web) will be retrieved, including the account name configured
20
+ for a given provider. Supports client secret and certificate authentication .
21
+
22
+ * Important: Requires the EWS Managed API to be installed on the local machine.
23
23
1. Run PowerShell as Administrator
24
24
2. Run the following: Install-Package Microsoft.Exchange.Webservices
25
- Note: If NuGet is not a registered package source: https://learn.microsoft.com/en-us/powershell/gallery/powershellget/supported-repositories
26
- Important: Requires the authenticated account to have impersonation access to the mailbox: https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-configure-impersonation
27
- Important: Requires an Entra ID app registration with delegated permission for EWS.AccessAsUser.All.
28
- Details for registering an app and adding the delegated permission:
25
+ Note: If NuGet is not a registered package source:
26
+ https://learn.microsoft.com/en-us/powershell/gallery/powershellget/supported-repositories
27
+ * Important: Requires an Entra ID app registration configured for app-only authentication
28
+ with EWS.AccessAsApp (full_access_as_app).
29
+ Details for registering an app and adding the role to the manifest:
29
30
https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth#register-your-application
30
31
Note: Enter the application ID and tenant's default routing domain in the variables at the top of the begin block.
32
+ * Important: Requires the corresponding enterprise application (service principal) to have a role assignment
33
+ with the "Application EWS.AccessAsApp" role (and a scope that includes the desired mailboxes).
34
+ Details for creating the service principal link and management role assignment in EXO:
35
+ https://learn.microsoft.com/en-us/exchange/permissions-exo/application-rbac
31
36
. Parameter EmailAddress
32
37
Email address of the mailbox from which to retrieve the configuration. Supports pipeline input
33
38
of email addresses or objects with an EmailAddress or PrimarySMTPAddress property, such as
34
39
with Get-Mailbox.
35
40
. Parameter Cloud
36
41
Office 365 environment which hosts the mailboxes. Valid values are Commercial, USGovGCC, China.
37
42
Default value is Commercial. The feature is not available in GCC High and DoD. Unknown if available in China.
43
+ . Parameter CertificateAuthentication
44
+ Use a certificate for authentication instead of a client secret. The app registration must have a
45
+ certificate uploaded, installed on the local machine in Current User\Personal\Certificates,
46
+ and the thumbprint specified in the variables region below.
38
47
. Example
39
- Get-MailboxOWAStorageProvider johndoe@contoso.com
40
- Get-Mailbox -RecipientTypeDetails UserMailbox -ResultSize unlimited | Get-MailboxOWAStorageProvider
48
+ .\ Get-MailboxOWAStorageProvider johndoe@contoso.com
49
+ Get-Mailbox -RecipientTypeDetails UserMailbox -ResultSize unlimited | .\ Get-MailboxOWAStorageProvider
41
50
. Notes
42
- Version: 1.1
43
- Date: January 7 , 2025
51
+ Version: 1.2
52
+ Date: July 30 , 2025
44
53
#>
45
54
46
55
[CmdletBinding ()]
47
56
param (
48
57
[Parameter (Mandatory = $true , ValueFromPipelinebyPropertyName = $true , Position = 0 )][Alias (' PrimarySMTPAddress' )][string ]$EmailAddress ,
49
- [ValidateSet (' Commercial' , ' USGovGCC' , ' China' )][string ]$Cloud = ' Commercial'
58
+ [ValidateSet (' Commercial' , ' USGovGCC' , ' China' )][string ]$Cloud = ' Commercial' ,
59
+ [switch ]$CertificateAuthentication
50
60
)
51
61
52
62
begin {
53
63
# Variables
54
- $tenantDomain = ' tenantname.onmicrosoft.com' # Default routing domain of the tenant
55
- $appId = ' 00000000-0000-0000-0000-000000000000' # Application ID of the app registration in Entra ID with EWS permission
64
+ $tenantDomain = ' tenantname.onmicrosoft.com' # Default routing domain of the tenant
65
+ $appId = ' 00000000-0000-0000-0000-000000000000' # Application ID of the app registration in Entra ID with EWS permission
66
+ $certThumbprint = ' ' # Thumbprint of the certificate to use for authentication if CertificateAuthentication switch is used
56
67
# End variables
57
68
58
69
if ($tenantDomain -like " tenantname*" -or $appId -like " 00000000*" ) {
59
70
Write-Error " The tenant domain or application ID has not been specified in the Variables section of the `" begin`" block."
60
71
break
61
72
}
73
+ if ($CertificateAuthentication -and -not $certThumbprint ) {
74
+ Write-Error " The certificate thumbprint has not been specified in the Variables section of the `" begin`" block."
75
+ break
76
+ }
62
77
63
78
# Check for EWS API installed via NuGet
64
79
# If already loaded, save time by reusing the loaded type
@@ -87,7 +102,7 @@ begin {
87
102
}
88
103
89
104
# Import MSAL from Exchange Online module
90
- if (-not (' Microsoft.Identity.Client.PublicClientApplicationBuilder ' -as [type ])) {
105
+ if (-not (' Microsoft.Identity.Client.ConfidentialClientApplicationBuilder ' -as [type ])) {
91
106
Write-Verbose ' Loading the MSAL from EXO module installation...'
92
107
if ($PSEdition -eq ' Core' ) {$folder = ' netCore' } else { $folder = ' NetFramework' }
93
108
$ExoModule = Get-Module - Name ExchangeOnlineManagement - ListAvailable | Sort-Object - Property Version - Descending | Select-Object - First 1
@@ -103,17 +118,32 @@ begin {
103
118
' USGovGCC' { $base = ' https://login.microsoftonline.com/' ;$ewsUrl = ' https://outlook.office365.com' }
104
119
' China' { $base = ' https://login.partner.microsoftonline.cn/' ;$ewsUrl = ' https://partner.outlook.cn' }
105
120
}
106
- # Build public client app and get access token
121
+ # Build client app and get access token
107
122
$replyUri = $base + ' common/oauth2/nativeclient'
108
- $authority = $base + $tenantDomain
109
123
$capabilities = New-Object System.Collections.Generic.List[string ]
110
124
# cp1 indicates support for CAE, which will result in an access token that is valid for 29 hours
111
125
# (This helps collecting from all mailboxes in a large org without needing to include support for token expiration.)
112
126
$capabilities.Add (' cp1' )
113
- $publicClient = [Microsoft.Identity.Client.PublicClientApplicationBuilder ]::Create($appId ).WithRedirectUri($replyUri ).WithAuthority($authority ).WithClientCapabilities($capabilities ).Build()
127
+ if ($CertificateAuthentication ) {
128
+ # Use certificate authentication
129
+ $cert = Get-Item " Cert:\CurrentUser\My\$certThumbprint "
130
+ if (-not $cert ) {
131
+ Write-Error " The certificate with thumbprint $certThumbprint was not found in the CurrentUser\My store."
132
+ break
133
+ }
134
+ $confidentialClient = [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder ]::Create($appId ).WithRedirectUri($replyUri ).WithCertificate($cert ).WithTenantId($tenantDomain ).WithClientCapabilities($capabilities ).Build()
135
+ }
136
+ else {
137
+ # Use client secret authentication
138
+ $ssAppSecret = (Get-Credential - Message " Enter the app registration's client secret in the password field." - UserName " EWS Application" ).Password
139
+ $bstr = [System.Runtime.InteropServices.Marshal ]::SecureStringToBSTR($ssAppSecret )
140
+ $appSecret = [System.Runtime.InteropServices.Marshal ]::PtrToStringBSTR($bstr )
141
+ [System.Runtime.InteropServices.Marshal ]::ZeroFreeBSTR($bstr )
142
+ $confidentialClient = [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder ]::Create($appId ).WithRedirectUri($replyUri ).WithClientSecret($appSecret ).WithTenantId($tenantDomain ).WithClientCapabilities($capabilities ).Build()
143
+ }
114
144
$scope = New-Object System.Collections.Generic.List[string ]
115
- $scope.Add (" $ewsUrl /EWS.AccessAsUser.All " )
116
- $token = $publicClient .AcquireTokenInteractive ($scope ).ExecuteAsync().GetAwaiter().GetResult()
145
+ $scope.Add (" $ewsUrl /.default " )
146
+ $token = $confidentialClient .AcquireTokenForClient ($scope ).ExecuteAsync().GetAwaiter().GetResult()
117
147
}
118
148
119
149
process {
@@ -154,5 +184,8 @@ process {
154
184
}
155
185
}
156
186
end {
187
+ if (-not $CertificateAuthentication ) {
188
+ Remove-Variable - Name appSecret, ssAppSecret - ErrorAction SilentlyContinue
189
+ }
157
190
Write-Progress - Activity ' Getting OWA storage provider settings' - Completed
158
191
}
0 commit comments