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)
Related
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
I have been trying to read outlook messages in a inbox with a specific subject and download the attachments associated with that particular subject.
This is the powershell script which i have used
$filepath = “C:\folder”
$filter="[Subject]=Test Powershell"
Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
$namespace.Logon("profilename","mypassword",$false,$false)
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
#$folder.items|select *
$folder.items.Restrict($filter)|
select -Expand Attachments | % {
for ($i = $_.Count; $i; $i--) {
$_.Item($i).SaveAsFile("$filepath\$($_.Item($i).FileName)")
}
}
However after the outlook MAPI object was created, I was prompted with the profile password to be provided manually even though I have added $namespace.Logon with profile password as a paramater. I want the password of the profile to be sent through the script without password prompt.
Please point out the change that has to be made to do so.
Namespace.Logon does not take the password for your Exchange mailbox. It might work for a password protected PST file, but not for an Exchange mailbox. Login in at least once and make sure "remember password" checkbox is checked to make sure you are no longer prompted.
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
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
Trying is use cmdkey in a PowerShell logon script to store credentials in the credential manager. When the script is run from PowerShell ISE everything works, but when it's run as a logon script via Group Policy everything but cmdkey works. Cannot for the life of me figure out why cmdkey will work everywhere except when the script run on logon.
# Checks if CRM for Outlook is isntalled by checking the folder path
$installed = Test-Path "C:\Program Files (x86)\Microsoft Dynamics CRM"
# Checks if the CRM has already been configured using the CoreConfigured registry entry
$configured = Get-ItemProperty -Path HKCU:\software\Microsoft\MSCRMClient -Name "CoreConfigured"
# If CRM is installed and not configured, configure it, if CRM is not installed or installed and configured, exit
If ($installed -eq "True" -and $configured.CoreConfigured -ne 1) {
$message1 = New-object -ComObject Wscript.Shell
$message1.Popup("Preparing to configure Microsoft CRM for Outlook, please make sure Outlook is closed.",10,"Systems")
# Prompts user for email address and Password to configure CRM for Outlook
$c = Get-Credential -Message "To confgiure CRM, please enter your email address and password:"
# puts user credentials into Windows Credential Manager using required CRM URLs
cmdkey /generic:Microsoft_CRM_https://disco.crm.dynamics.com/ /user: $c.Username /pass: $c.Password | Out-Null
cmdkey /generic:Microsoft_CRM_https://disco.crm4.dynamics.com/ /user: $c.Username /pass: $c.Password | Out-Null
$message2 = New-Object -ComObject Wscript.Shell
$message2.Popup("Please wait, a notification will appear when the configuration is complete.",10,"Systems")
# Silenty runs the CRM configuration Wizard with custom XML file
$exe = "C:\Program Files (x86)\Microsoft Dynamics CRM\Client\ConfigWizard\Microsoft.Crm.Application.Outlook.ConfigWizard.exe"
&$exe -p /Q /i 'C:\Program Files (x86)\Microsoft Dynamics CRM\Default_Client_Config.xml' /xa /l 'c:\temp\crminstall.txt' | Out-Null
$message3 = New-Object -ComObject Wscript.Shell
$message3.Popup("Configuration complete! You may now open Outlook!",10,"Systems")
}
else {
exit
}
I imagine cmdkey is using Microsoft's Data Protection API (DPAPI) to encrypt credentials so only the current user can retrieve them. You can't use this API unless the user's session is loaded. When your script runs, it may be too early in the logon process for the security information the DPAPI needs is loaded. I'm not sure how logon scripts work, but try putting a delay in your logon script until you get a value back.
Here's the PowerShell code that encrypts with the DPAPI:
$scope = [Security.Cryptography.DataProtectionScope]::CurrentUser
$encryptedBytes = [Security.Cryptography.ProtectedData]::Protect( $plainBytes, $null, $scope )
$decryptedBytes = [Security.Cryptography.ProtectedData]::Unprotect( $encryptedBytes, $null, 0 )
Add a loop in your logn script that tries to encrypt/decrypt some random array of bytes until it succeeds.
I had the same issue: cmdkey was not working in Powershell when run as a User Logon Script.
In my case the issue was related to the user's group membership. The user was a member of the group "Power Users", but not a member of the group "Users" (or any other group).
According to this article from Microsoft, the group "Power Users" has "no default user rights", while the group "Users" has rights to "perform common tasks, such as running applications, using local and network printers".
The solution was to add my user(s) to the group "Users". This immediately solved the issue and allowed cmdkey to work in Powershell Logon Scripts.
I had this same problem with a PowerShell GPO logon script calling cmdkey.exe. The credentials populated into Credential Manager for Users, but Administrators the credentials did not show up. I found out that the credentials are saving in Credential Manager, but for the elevated user. If you run cmdkey /list in an elevated command prompt you will see the credentials there.