Giter Club home page Giter Club logo

Comments (24)

grahamr975 avatar grahamr975 commented on May 29, 2024 1

This issue is from the ExchangeOnline Powershell Module and occurs for one of the following reasons:

  • You enter an incorrect user name or password.
  • You try to sign in to the service by using an account that doesn't have access to Exchange Online.
  • You have security defaults enabled in your tenant.
    Source

Note that the ExchangeOnline Powershell Module in this script still uses basic authentication. It's on my to-do list to migrate this over to OAuth just as I have done for the EWS portions.

We only use ExchangeOnline to retrieve the contacts, so if you're up to the challenge you could follow a guide like the one here to set up an AzureAD App. After that, you'd need to modify the function here: https://github.com/grahamr975/EWS-Office365-Contact-Sync/blob/master/EWSContacts/Module/functions/contacts/Get-GALContacts.ps1

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ConnectionUri -Credential $Credentials -Authentication Basic -AllowRedirection

from ews-office365-contact-sync.

grahamr975 avatar grahamr975 commented on May 29, 2024

Hello @BastiGit,

Have you tried using the -ModernAuth parameter? For a list of all parameters, see https://github.com/grahamr975/EWS-Office365-Contact-Sync/blob/master/EWSContactSync.ps1

Follow the Get Started guide in the README file. This shows how to set up the script with modern authentication.

I'd recommend you test this on an account with basic authentication disabled to verify the script will function properly in your environment using only modern authentication. The guide below shows you how to set up a security group with no basic authentication using PowerShell. It's working well in mine.

https://docs.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/disable-basic-authentication-in-exchange-online

from ews-office365-contact-sync.

BastiGit avatar BastiGit commented on May 29, 2024

Hello @grahamr975,

thanks for your quick reply.

Yes, I have used the -ModernAuth parameter as described in the README.
However, then the following error appears:

[outlook.office365.com] Connecting to remote server outlook.office365.com failed with the following error message : Access is denied.

Is there anything else to do for modern authentication?

I have saved the credentials by Export-Clixml, but they are only relevant for BasicAuth, right?

from ews-office365-contact-sync.

grahamr975 avatar grahamr975 commented on May 29, 2024

Did you unblock all of the DLL files referenced in step 4 of the README?

You do still need credentials for Modern Auth since we use those to generate the OAuth access token. This account should have permissions as specified in the README.

from ews-office365-contact-sync.

BastiGit avatar BastiGit commented on May 29, 2024

Yes, I have unblocked all DLL files from step 4.

At Export-Clixml I enter my Office 365 account data.
This account is an administrator and also has the Application Impersonation permissions.

Unfortunately, the access denied error message comes up again.

from ews-office365-contact-sync.

BastiGit avatar BastiGit commented on May 29, 2024

Thank you very much for your tips and time.

I have created an Azure-AD app using the tutorial and have customized the function in the Get-GALContacts.ps1 script. Now everything works perfectly and the contacts are being synced.

The script now uses the following function:
Connect-ExchangeOnline -CertificateThumbPrint “<CertThumbprint>” -AppID “<MyAppId>” -Organization “<MyTenant.OnMicrosoft.com>”

and instead of Remove-PSSession $Session there is now Disconnect-ExchangeOnline -Confirm:$false at the end of the GALContact script.

We disabled BasicAuth on our tenant for all services, so I'm glad we don't have to enable it again.

Thanks @grahamr975!

from ews-office365-contact-sync.

grahamr975 avatar grahamr975 commented on May 29, 2024

@BastiGit Thanks for this information. I'll work on incorporating this piece into the script as time allows since basic authentication will be fully depreciated next year, as you point out.

from ews-office365-contact-sync.

nldenic avatar nldenic commented on May 29, 2024

Thank you very much for your tips and time.

I have created an Azure-AD app using the tutorial and have customized the function in the Get-GALContacts.ps1 script. Now everything works perfectly and the contacts are being synced.

The script now uses the following function: Connect-ExchangeOnline -CertificateThumbPrint “<CertThumbprint>” -AppID “<MyAppId>” -Organization “<MyTenant.OnMicrosoft.com>”

and instead of Remove-PSSession $Session there is now Disconnect-ExchangeOnline -Confirm:$false at the end of the GALContact script.

We disabled BasicAuth on our tenant for all services, so I'm glad we don't have to enable it again.

Thanks @grahamr975!
Can you send me the PS1 you have use or using ?

We have activate mfa for admin accounts. My exchange admin account have already all permistions but getting error ::
ERROR Failed to Sync-ContactList for [email protected] A constructor was not found. Cannot find an appropriate constructor for type Microsoft.Exchange.WebServices.Data.OAuthCredentials.

from ews-office365-contact-sync.

BastiGit avatar BastiGit commented on May 29, 2024

Hello @nldenic,

I'm sorry, but I can't send you the original .ps1 file, because it contains confidential data.

I have replaced the "PSSession" sections with "ExchangeOnline" in both the Get-Mailboxes.ps1 and Get-GALContacts.ps1 files, as described above.

Have you created an Azure AD app for the script (as described here)?

from ews-office365-contact-sync.

nldenic avatar nldenic commented on May 29, 2024

Thank you for your reply. Than i will create first the Application in azure and follow this steps.
Than will change the ps1 files and see if that works.

The commands to will not change still same am i right so :

cd "%~dp0EWS-Office365-Contact-Sync"

PowerShell.exe -ExecutionPolicy Bypass ^
-File "%CD%\EWSContactSync.ps1" ^
-CredentialPath "C:\Encrypted Credentials\SecureCredential.cred" ^
-FolderName "Directory Contacts" ^
-LogPath "%~dp0Logs" ^
-MailboxList [email protected] ^
-ModernAuth
pause

I have write this in an bat file. This is no issue am i right?

from ews-office365-contact-sync.

nldenic avatar nldenic commented on May 29, 2024

@BastiGit @grahamr975

Can you maybe just send the ps1 without your credentials and appid.

i have follow every step but still getting an error. in this case its now :
New-PSSession : A parameter cannot be found that matches parameter name 'AppID'

My Galcontacts.ps1 is now like :

process {
	try {
		# Connect to Office 365 Exchange Server using a Remote Session
	$Session = New-PSSession Connect-ExchangeOnline -CertificateThumbPrint “Thumbprint" -AppID "appid" -Organization “organisation.onmicrosoft.com”
	Import-PSSession $Session -DisableNameChecking -AllowClobber
	
		# Import Global Address List into Powershell from Office 365 Exchange as an array
		$ContactList = Get-User -ResultSize unlimited 

		# If the ExcludeSharedMailboxContacts switch is enabled, exclude contacts that are a shared mailbox or mailbox with no liscense
		if ($ExcludeSharedMailboxContacts) {
			$DirectoryList = $(Get-Mailbox -ResultSize unlimited | Where-Object {$_.HiddenFromAddressListsEnabled -Match "False"})
			$EmailAddressList = $DirectoryList.PrimarySMTPAddress
			$ContactList = $ContactList | Select-Object DisplayName,FirstName,LastName,Title,Company,Department,WindowsEmailAddress,Phone,MobilePhone | Where-Object {$EmailAddressList.Contains($_.WindowsEmailAddress)}
		} else {
			$ContactList = $ContactList | Select-Object DisplayName,FirstName,LastName,Title,Company,Department,WindowsEmailAddress,Phone,MobilePhone
		}
		
		# If the IncludeNonUserContacts switch is enabled, also include contacts that aren't actual users in the directory
		if ($IncludeNonUserContacts) {
			$ContactList += Get-Contact -ResultSize unlimited | Select-Object DisplayName,FirstName,LastName,Title,Company,Department,WindowsEmailAddress,Phone,MobilePhone
		}

		# If the ExcludeContactsWithoutPhoneNumber switch is enabled, exclude contacts that don't have a phone or mobile number
		if ($ExcludeContactsWithoutPhoneNumber) {
			$ContactList = $ContactList | Where-Object {$_.Phone -or $_.MobilePhone}
		}
	
	# Only return contacts with email addresses
	return $ContactList | Where-Object {$null -ne $_.WindowsEmailAddress -and "" -ne $_.WindowsEmailAddress}
	} catch {
		Write-Log -Level "FATAL" -Message "Failed to fetch Global Address List Contacts from Office 365 Directory" -exception $_.Exception.Message
	}
}
}Disconnect-ExchangeOnline -Confirm:$false

Can you please check this and confirm its set good ?

Its in this case changed for both Get-Mailboxes.ps1 and Get-GALContacts.ps1 but still same error message.

When i run empty powershell with.
$Session = New-PSSession Connect-ExchangeOnline -CertificateThumbPrint “Thumbprint" -AppID "appid" -Organization “organisation.onmicrosoft.com”

Its working and exchange shell starts. So I don't get it how to write this correct in the ps1 files.

from ews-office365-contact-sync.

Csarly avatar Csarly commented on May 29, 2024

dear all,
I've changed Get-GALContacts.ps1's lines starting here:

...

process {
	try {
		# Connect to Office 365 Exchange Server using a Remote Session
#	$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ConnectionUri -Credential $Credentials -Authentication Basic -AllowRedirection
#	Import-PSSession $Session -DisableNameChecking -AllowClobber
$cert = Get-ChildItem Cert:\CurrentUser\My\<self-signed-cert-thumbprint>
$appId = 'my-azure-app-id'
$exchangeOrgId = 'myOrgID.onmicrosoft.com'
$paramConnectExchangeOnline = @{
    CertificateThumbprint = $cert.ThumbPrint
    AppId                 = $appId
    Organization          = $exchangeOrgId
}
Connect-ExchangeOnline @paramConnectExchangeOnline


		# Import Global Address List into Powershell from Office 365 Exchange as an array
		$ContactList = Get-User -ResultSize unlimited -RecipientTypeDetails 'Usermailbox'

...
end of change

... and it works like a charm.

I hope you find it useful!

Cheers, Csarly

from ews-office365-contact-sync.

nldenic avatar nldenic commented on May 29, 2024

@Csarly

I have try you Galsync changes. But still same error message :(
Which file do you select here : $cert = Get-ChildItem Cert:\CurrentUser\My<self-signed-cert-thumbprint>

is it the Cer or pfx file ?

i have also already click allow public client flows in the application settings in azure :
image

Are you able to share me your ps1 ? Is there Basicauth active for your account which you use ?

from ews-office365-contact-sync.

Csarly avatar Csarly commented on May 29, 2024

@nldenic ,
what is the error message the script throws?
Sorry, there's a missing back-slash, this line is correct:
$cert = Get-ChildItem Cert:\CurrentUser\My<self-signed-cert-thumbprint>

Have you created a self-signed certificate?
Take it's thumbprint and replace "" with it.
Connect-ExchangeOnline uses modern authentication in combination with the certificate for automation capabilities.

I'm new to GitHub, so please forgive me, I just don't find the button to add a file... :(

from ews-office365-contact-sync.

nldenic avatar nldenic commented on May 29, 2024

@Csarly
No problem we can share here the script together.

Please see my error message :
image

My script is now as following:

image

Is this correct or do i need to fill this different ?

from ews-office365-contact-sync.

Csarly avatar Csarly commented on May 29, 2024

Get-GALContacts.txt
Hi,
I'm sorry, I was trying to create a branch, but it doesn't finish uploading...
I finaly found the obvious thing: drag&drop the script here... facepalm
You need to modify the parameters commented in capital letters!
That should do it..
You have to provide your cert thumbprint, otherwise it won't work. Your version is a mixture of certificate store and desktop. That will probably cause the error...

I hope it helps!
KR, Csarly

from ews-office365-contact-sync.

benj288 avatar benj288 commented on May 29, 2024

Hello Csarly,

have you updated the Sync-ContactList or the Connect-EXCExchange Modules in your environment?

from ews-office365-contact-sync.

Csarly avatar Csarly commented on May 29, 2024

Hi benj288,
no, sadly I was pulled away from this and had no time to invest further. :(
best, Csarly

from ews-office365-contact-sync.

benj288 avatar benj288 commented on May 29, 2024

Hi Csarly, thank you for your reply!
You don't use it anymore or has the problem resolved itself?
Kind regards

from ews-office365-contact-sync.

Csarly avatar Csarly commented on May 29, 2024

Hi ben,
both, due to other topics and lacking time, I could not finish the adjustments.
If the need arises again, and the 3rd party forces me again, I will post my version here.
Sorry for not being that helpful at the moment...
Cheers, Csarly

from ews-office365-contact-sync.

JBW-Imthorn avatar JBW-Imthorn commented on May 29, 2024

Hello,

Does anyone have this script working without ANY basic authentication? So without the $creds based on a (Global Admin) useraccount?

In several functions we see that the $creds variable is used. When leaving the $creds empty the script does not work, also not with the -ModernAuth parameter.

On this moment we have the script working with the -Modernauth parameter, but the script still requires credentials as described above. As we use Azure Privileged Identity Management, we cannot automate the script on this moment.

Does anyone else had this problem and managed to solve it?

Kind regards,
Sebastiaan

from ews-office365-contact-sync.

Csarly avatar Csarly commented on May 29, 2024

@JBW-Imthorn , hi Sebastiaan,
nope, EWS doesn't provide cert based auth, e.g., but I managed to run the script - kind of automated - with user & pw stored in an encrypted xml in my tests a few months ago.
I think there is a Azure Key Vault you maybe can leverage for storing your credentials. (I'm not familiar with it)

In my case OAuth2 was successfully commited after I changed line 99 in Connect-EXCExchange.ps1
from:
$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($token.AccessToken)
to:
$service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$token.AccessToken

I actually don't know why exactly... might be because I have installed the EWS Package ( -Name 'Exchange.WebServices.Managed.Api')....
I replaced line 55 against:
$EWSDLL = (Get-ChildItem -Path "$(split-path $((Get-Package -Name 'Exchange.WebServices.Managed.Api').Source) -Parent)\Microsoft.Exchange.WebServices.dll" -Recurse).FullName

I hope this helps a little bit though..
kr, Csarly

from ews-office365-contact-sync.

JBW-Imthorn avatar JBW-Imthorn commented on May 29, 2024

Hi @Csarly,

Thank you for your reply, I came across this item in the Microsoft docs. So that was triggering me with the question if anyone already tried.

Yes the encrypted XML is what we use too to run the script, and as you described we also changed the content of Connect-EXCExchange.ps1 and this is fully working.

The problem is more that we use Azure Privileged Identity Management. This means we need to activate a role in the Azure environment to gain access rights on the useraccount, it's more secure but also preventing us to automate the contactsync script as a privileged user account is needed.

We will lookin further for what the possibilities are, when we found a solution I will definitely post it here so others can use it also.

Kind regards,
Sebastiaan

from ews-office365-contact-sync.

grahamr975 avatar grahamr975 commented on May 29, 2024

All,

The latest version of the app moves to Azure-app-based certificate authentication which removes the need for basic auth & fixes MFA issues. See commit 9fcfe1f.

from ews-office365-contact-sync.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.