Powershell + EWS Impersonation insufficient permission - powershell

I get the following error -
Exception calling "Bind" with "2" argument(s): "The server to which the application is connected cannot impersonate the requested user due to insufficient permission."
Using the following code -
## Load Exchange web services DLL
## Download here if not present: http://go.microsoft.com/fwlink/?LinkId=255472
$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"
Import-Module $dllpath
## Creating Service Object
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
## Setting up Admin Credentials with Impersonated Role Group rights
$user = "serviceAccount"
$pass = "P#55w0rd"
$service.Credentials = New-Object System.Net.NetworkCredential -ArgumentList $user, $pass
## Set the URL of the CAS (Client Access Server)
#$service.AutodiscoverUrl($AccountWithImpersonationRights ,{$true})
$EWSurl = "https://server.domain.ca/EWS/Exchange.asmx"
$service.URL = $EWSurl
## Setting up ImperSonated User
$service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, "mailbox#domain.com")
#Connect to the Inbox and display basic statistics
$InboxFolder= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox, "mailbox#domain.com")
$Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$InboxFolder)
Write-Host 'Total Item count for Inbox:' $Inbox.TotalCount
Write-Host 'Total Items Unread:' $Inbox.UnreadCount
Currently I'm just trying to do a simple connect. The intention is then to download an attachment.

The error is telling you that the Service Account your using "serviceAccount" doesn't have rights to Impersonate the user your trying to access. EWS Impersonation rights need to granted via RBAC see https://msdn.microsoft.com/EN-US/library/office/dn722376(v=exchg.150).aspx
Cheers
Glen

Related

How to remove all list item permissions using PnP Powershell

I would like to remove all permissions of a list item using PnP Powershell
I have tried this command:
Set-PnPListItemPermission -Identity $item.id -User 'user#contoso.com' -AddRole "Contribute"
However the user running the script/command was also added with Full Control permissions.
Is there any other way to remove all existing permissions for a list item using PnP Powershell ?
Thanks
I tested to connect to SharePoint Online site with a read permission user in PnP PowerShell and then run the Set-PnPListItemPermission command, it will throw Access Denied error instead of adding with Full Control Permissions:
In Summary, to set permssions for list item, it's expecetd to have the Full Control Permission on the site level for the user who is running the script. Otherwise, the Access Denied error will throw.
The Full Control permissions should be applied with the site group, in the list, try to break permission inheritance and remove the group:
# Provide credentials over here
$creds = (New-Object System.Management.Automation.PSCredential "<<UserName>>",(ConvertTo-SecureString "<<Password>>" -AsPlainText -Force))
# Provide URL of the Site over here
# If you do not wish to pass credentials hard coded then you can use: -Credentials (Get-Credential). This will prompt to enter credentials
Connect-PnPOnline -Url http://MyServer/sites/MySiteCollection -Credentials $creds
# Get Context
$clientContext = Get-PnPContext
$targetWeb = Get-PnPWeb
# Get the list object
$targetList = $targetWeb.Lists.GetByTitle("List Name")
# Load List object
$clientContext.Load($targetList)
$clientContext.ExecuteQuery()
# This method will work only if the role inheritence is broken(list has unique role assignments) on the list
$targetList.RoleAssignments.Groups.RemoveByLoginName("test Visitors")
$clientContext.ExecuteQuery()
Disconnect-PnPOnline

Accessing a shared office365 mailbox via powershell

I have shared mailbox on office365 which doesnt have a user account associated with it i.e. I cant login to it via the office 365 portal. I access to it via Outlook as a shared mailbox hence my account has permission to view the inbox.
I have used the powershell script found here and I have barely amended it except to change the $mail and $password.
If I use my own account credentials I can loop through the foreach loop and observe it accessing my emails which is great. I want to however access a shared mailbox called shared#mailbox.com instead of myAccount#mailbox.com.
To attempt to do this I added a username variable and passed this to $service.credentials and passed the $mail variable to $service.autodiscover. See code below.
This did not work....
Can anyone help?
$username="myAccount#mailbox.com"
$password="myPassword"
$mail = "shared#mailbox.com"
# Set the path to your copy of EWS Managed API
$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
# Load the Assemply
[void][Reflection.Assembly]::LoadFile($dllpath)
# Create a new Exchange service object
$service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService
#These are your O365 credentials
$Service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($username,$password)
# this TestUrlCallback is purely a security check
$TestUrlCallback = {
param ([string] $url)
if ($url -eq "https://autodiscover-s.outlook.com/autodiscover/autodiscover.xml") {$true} else {$false}
}
# Autodiscover using the mail address set above
$service.AutodiscoverUrl($mail,$TestUrlCallback)

Using Powershell to get Azure AD Token (jwt)

I am trying to get a jwt token from AAD using Powershell using Username/Password authentication.
I am writing a powershell script that will to call an API using a bearer token. What I have works if I copy & paste the token from an SPA that uses the API. I am looking for a way to retrieve the token from my powershell.
This looks really promising: https://github.com/Azure-Samples/active-directory-dotnet-native-headless/blob/master/TodoListClient/Program.cs
I feel like I'm smacking my head against a wall trying to create a 'UserPasswordCredential' object. Any clues to how I can do this would be super-helpful.
I have Add-Type-ed:
- Microsoft.IdentityModel.Clients.ActiveDirectory.dll
- Microsoft.IdentityModel.Clients.ActiveDirectory.platform.dll (adds nothing?)
- Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll
- Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll
The docs page for 'UserPasswordCredential' :
https://learn.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.clients.activedirectory.userpasswordcredential
It should be in one of the first two dlls
This, under 'Constraints & Limitations', makes me think it may not actually be possible from powershell:
http://www.cloudidentity.com/blog/2014/07/08/using-adal-net-to-authenticate-users-via-usernamepassword/
Looking at the code below, the first acquire token succeeds, the second fails - possibly/probably because $cred is a UserCredential not a UserPasswordCredential.
Is is possible to do this with powershell?
Finally, on a totally different track, how do I find the values for redirectUri and resourceAppIdURI that my application needs? When I look in the AAD console, and browser to my Enterprise Application, I can find the AppId (which I can use as $clientId).
I'm not sure the redirectUri is strictly necessary for me as all I really want is the token, but I can have a good guess at what it should be.
When I try to call the first AquireToken method (without $cred) using my app details, it fails with this message:
Exception calling "AcquireToken" with "4" argument(s): "AADSTS50001: The application named https://myappwithapi/Login was not found in the tenant named me.onmicrosoft.com.
Is it possible for me to find the require value for resourceAppIdURI by looking in my azure portal?
'https://myappwithapi/Login' is from my azure portal > enterprise apps > [app' > properties > HomepageUrl
code:
#setup
$TenantName = "mme.onmicrosoft.com"
$clientId = "1950a258-227b-4e31-a9cf-717495945fc2" # Microsoft
$clientId = "03faf8db-..........................." #
$username = "me#me.onmicrosoft.com"
$password = Read-Host -AsSecureString -Prompt "Enter Password"
# add dlls
$adal = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll"
$adalplatform = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.platform.dll"
[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null
[System.Reflection.Assembly]::LoadFrom($adalplatform) | Out-Null
#prep request
$redirectUri = "urn:ietf:wg:oauth:2.0:oob" # Microsoft
$resourceAppIdURI = "https://graph.windows.net"
$authority = "https://login.windows.net/$TenantName"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
# Get Token prompting for creds
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId, $redirectUri, "Always")
$authResult
# Get the cred
$cred = New-Object -TypeName 'Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential' -ArgumentList $username, $password
#$cred = New-Object -TypeName 'Microsoft.IdentityModel.Clients.ActiveDirectory.UserPassCredential' -ArgumentList $username, $password
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId, $cred)
$authResult
This post has more the one question in it.
Your base use case 'Using Powershell to get Azure AD Token (jwt)' is a common one and there are several samples and pre-built examples to leverage. For example:
https://github.com/pcgeek86/AzureADToken
A PowerShell module that allows you to get a JSON Web Token (JWT) from Azure Active Directory (AAD).
https://gallery.technet.microsoft.com/Get-Azure-AD-Bearer-Token-37f3be03
This script acquires a bearer token that can be used to authenticate to the Azure Resource Manager API with tools such as Postman. It uses the Active Directory Authentication Library that is installed with the Azure SDK.
See if those two resources resolves your use base line use case.
As for this...
"Is it possible for me to find the require value for resourceAppIdURI by looking in my azure portal?"
You can do this via a remote PowerShell logon to AzureAD. Install the AAD PowerShell module.
https://learn.microsoft.com/en-us/powershell/azure/overview?view=azurermps-5.1.1
https://msdn.microsoft.com/en-us/library/dn135248(v=nav.70).aspx
Download and install MSOL. Sign in with the MSOL
https://www.microsoft.com/en-US/download/details.aspx?id=39267
The Microsoft Online Services Sign-In Assistant provides end user sign-in capabilities
and use the built-in cmdlets to pull your information from your organization settings, and or hit the MSGraph API and query.
https://learn.microsoft.com/en-us/powershell/azure/active-directory/install-adv2?view=azureadps-2.0
You can use the Azure Active Directory PowerShell Module Version for Graph for Azure AD administrative tasks
As for this one:
"how do I find the values for redirectUri and resourceAppIdURI that my application needs?"
This is in your app registration section of your portal. The developer team provide the redir uri not Azure. It's part of the registration process all else is generated by Azure App Reg process.
The app registration process is here and of course you are someone else had to register this app in AzureAD, and thus can retrieve it at any time.:
https://blogs.msdn.microsoft.com/onenotedev/2015/04/30/register-your-application-in-azure-ad
Any registered apps and their details can be retrieved using...
Get-AzureADApplication
Get-AzureADApplication | Select -Property *
(Get-AzureADApplication).ReplyUrls
Get-AzureADApplication | Select -Property AppID, DisplayName,ReplyUrls
https://learn.microsoft.com/en-us/powershell/module/azuread/get-azureadapplication?view=azureadps-2.0

How to run powershell script using default credential from sql job agent

I am downloading a file from sharepoint.
I have already scheduled the job in SQL job agent
Its working fine when i use the following code
$UserName = "xxxx"
$PswdPath = "D:\securestring.txt"
$SecurePassword = cat $PswdPath| convertto-securestring
$fileName = [System.IO.Path]::GetFileName($FileUrl)
$DownloadPath = "D:\Excel\"
$downloadFilePath = [System.IO.Path]::Combine($DownloadPath,$fileName)
$client = New-Object System.Net.WebClient
$client.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
$client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
$client.DownloadFile($FileUrl, $downloadFilePath)
$client.Dispose()
But the problem here i face is whenever i update my password i need to update the secure string as well
So i wanted to use the default credentials
so i used the following script
$webclient = New-Object System.Net.WebClient
$webclient.UseDefaultCredentials = $true
$webclient.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
$webclient.DownloadFile($FileUrl, $DownloadPath)
but its getting failed with the following error
Exception calling "DownloadFile" with "2" argument(s): "The remote server returned an error: (401) Unauthorized."
went through different blogs all were suggesting the same approach which i have followed
Any help in this regard?
As far as I understand default credentials users the account and password the sql agent process is started and since it will not match the SharePoint online account it will fail. It would be easier if you create a powershell that updates all secure strings once password is changed.

Powershell Sharepoint snapin when not on the sharepoint server

I am new to both powershell and sharepoint, and I need to make script to automate the removal and uploading of attachments from outlook to sharepoint. I have easily completed the first part of extracting the attachment, however the uploading to sharepoint has become difficult do to my company's rules. As I understand to use sharepoint cmdlets you need to add the sharepoint snap-in but I am unable to do so because I dont have access to the sharepoint server. Is there anyway to the snapin without being on the server and if not can I upload it another way?
You can't add the SP snap in unless the server is a SP server. Instead, use a webservice/webclient approach to upload the file. Something like this should work depending on your SP version:
http://blog.sharepoint-voodoo.net/?p=205
Accepted answer link is broken.
This script uses PowerShell to upload a file to a document library in SharePoint using purely web service calls so it could be done remotely, also meaning it should work with O365 though I have not tried.
These variables are used throughout the script for source file, destination file and authentication. If your workstation is on the same domain as SharePoint, and your logged on user has permissions to the SharePoint site, you can omit $username, $password, and $domain
$LocalPath = "C:\filename.docx"
$spDocLibPath = "http://site.contoso.com/sites/spteam/Shared Documents/"
$username = "someone"
$password = "somepassword"
$domain = "contoso"
$UploadFullPath = $spDocLibPath + $(split-path -leaf $LocalPath)
$WebClient = new-object System.Net.WebClient
if($username -eq "" -or $password -eq "" -or $password -eq "")
{
# Use Local Logged on User Credentials
$WebClient.Credentials = [System.Net.CredentialCache]::DefaultCredentials
}
else
{
# Alternate Login for specifying credentials
$WebClient.Credentials = new-object System.Net.NetworkCredential($username, $password, $domain)
}
$WebClient.UploadFile($UploadFullPath, "PUT", $LocalPath)
https://web.archive.org/web/20160404174527/http://blog.sharepoint-voodoo.net/?p=205