Sep 01 2023 09:43 AM - edited Sep 01 2023 09:44 AM
When running the script below, I get the following error:
Import-Module Microsoft.Graph.Authentication
Import-Module Az.Accounts
function Connect-MgGraphViaCred {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[System.Management.Automation.PSCredential] $credential,
[string] $tenant = "customersbank.com"
)
# connect to Azure using credentials
$param = @{
Credential = $credential
Force = $true
}
if ($tenant) { $param.tenant = $tenant }
Connect-AzAccount
# retrieve token for MSGraph
$token = (Get-AzAccessToken -ResourceTypeName MSGraph -ErrorAction Stop).token
# convert token string to securestring if new version of Connect-MgGraph is used
if ((Get-Help Connect-MgGraph -Parameter accesstoken).type.name -eq "securestring") {
$token = ConvertTo-SecureString $token -AsPlainText -Force
}
# use token for connecting to Microsoft Graph
$null = Connect-MgGraph -AccessToken $token -ErrorAction Stop
}
$User = "##username##"
$PWord = ConvertTo-SecureString -String "##password##" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
Connect-MgGraphViaCred -credential $Credential
I am running the script inside a Power Automate Desktop flow. When I run it on my Win10 machine, it runs fine, but it needs to run on a Windows Server 2019 OS, which is where it fails. I am assuming that it has something to do with the version of the Connect-AZAccount or Get-AZAccessToken commands.
P.A.D. only supports PowerShell 5, so I am forced to use that version. The server's version of PowerShell is slightly older but, from what I understand, the only way to update it is via Windows Update and that says there are no new updates. Is it possible that this just won't run on Windows Server?
Module Name | Win10 Version | Server 2019 Version |
Az | 9.7.1 | 10.2.0 |
Az.Accounts | 2.12.2 | 2.12.5 |
Sep 02 2023 01:27 AM
Solution
Hi, Steve.
I can't offer any advice on what's causing that issue as I've not seen it before, but I can offer some commentary around the environment and your questions towards the end.
Firstly, on the environment, I only use Windows PowerShell (aka 5.1) as it's the only option out-of-the-box, and is therefore the only option available in practically every customer engagement I've been in. And in most cases, this is on Windows Server 2019, too.
This dovetails into your question of "is it possible that this just won't run on Windows Server?", for which the answer is it most certainly does run on Windows Server under Windows PowerShell.
That said, while I have a few solutions doing as you're doing - which is using Az.Accounts to procure a token for including in subsequent Microsoft.Graph calls (amongst others), there is a point of difference in that I'm using certificate-based authentication rather than old-school username-and-password credentials. Still, that one point aside, the approach you're taking definitely works.
With respect to the error, "method not found" is typically thrown for one of "two" reasons (technically, it's one reason but it's useful to split it):
One possibility is that different versions of a library are required by different PowerShell modules. And it's noteworthy that the class (contained in Azure.Identity.BrokeredAuthentication.dll) from your error message is used by both the Az.Accounts and Microsoft.Graph.Authentication modules. So, there's a possibility that they are in conflict.
There's a lot of different troubleshooting steps you can pursue here, but in the interest of keeping things simple, I'd wipe out all module versions (using Uninstall-Module) matching the following specifications and re-install those that you need:
There's a reasonable chance that ensuring that both the Az modules and Microsoft.Graph modules are current that the underpinning SharedTokenCacheCredentialBrokerOptions class issue will also be resolved.
As a side note, you might also want to ensure you're running .NET 4.7.2 or above, as both Az and Graph modules are tagged to this as the minimum version:
Cheers,
Lain
Sep 05 2023 12:14 PM - edited Sep 05 2023 12:14 PM
@LainRobertson Thank you, Lain, for a detailed and thoughtful response!
I did not understand that both the Az.Accounts and Microsoft.Graph.Authentication modules utilized the same DLL that was mentioned in the error. Once I understood that, I realized that the largest gap in versions was for Graph.Authentication:
Name | Win10 Laptop Version | RPA Server 2019 Version |
Az.Accounts | 2.12.2 | 2.12.5 |
Microsoft.Graph.Authentication | 1.27.0 | 2.3.0 |
I then uninstalled all the Graph modules and reinstalled using the "-requiredversion 1.27" switch. My script now executes successfully on the 2019 server!
Oh, and after checking the registry, both machines running .NET 4.8.
Some follow-up questions:
Thanks again for your assistance! I opened a Microsoft ticket for this issue but it's still being routed to the correct support group.
Sep 05 2023 02:04 PM - edited Sep 05 2023 02:07 PM
@LainRobertson It doesn't appear that the DLL mentioned in the error, Azure.Identity.BrokeredAuthentication.dll, is used by both Az.Accounts and Microsoft.Graph.Authentication. I used Process Explorer to do a little testing and the DLL is only loaded with Az.Accounts:
Though dropping the version of Microsoft.Graph.Authentication back from v2 to v1 is what fixed the error.
The really strange thing is a colleague reminded me that they were unable to get the script to run on their laptop with PowerShell 5.1 and they have almost the same versions of those modules as the server. The only difference is Microsoft.Graph.Authentication is at 1.28 instead of 1.27. This is so confusing.
Sep 05 2023 05:21 PM
Hey, Steve.
Speaking to your two earlier questions (which covers your last post):
First, you need to know which DLL you're looking for, as DLLs themselves have dependencies, and there's more than one way to load a DLL which can obscure locating them in memory.
Let's use your error message as the example to consider, where looking at it gives us two important clues:
So, while there's no mention of a DLL, we do have a class name to work with.
Next, we check the class to see from which module it was loaded. In my example below, I'm killing two birds with one stone as this is actually taken from having loaded Microsoft.Graph.Authentication (second screenshot, showing the progression of events leading to the class being loaded) where you can see it does indeed use Azure.Identity.BrokeredAuthentication.dll:
Now that we know the actual DLL name the class is defined in (as distinct from the process owner that imported it), it's a basic case of looking for the file - which in my example I've scoped to the x64 Windows PowerShell directory, but you could just as easily scan the whole drive for:
And presto! We now know which modules (and which versions of those modules) contain the potentially-conflicting DLL. Conveniently, this also confirms both Az.Accounts and Microsoft.Graph.Authentication leverage Azure.Identity.BrokeredAuthentication.dll (unsurprising given they're both aimed at authentication).
No, they're not preview.
Sometimes things disappear from current module when compared to old ones because they forgot to include them (which even happens at the Graph API level, too), or because of a regression (aka bug), or just because they're not doing something the same way anymore - which is the most common reason.
In this brave, new "agile" world, you can't count on backwards compatibility the way you could in the past, so constant script fiddling is something we all just have to live with.
Because the ".ctor" reference tells us we're dealing with the constructor, we can see what constructor definitions exist by simply including "::new" (without the parentheses at the end):
Constructor definitions taken from the Microsoft.Graph.Authentication 2.3.0 module.
I don't have an older version of Az.Accounts to compare, but I'd wager a comparison between ne Graph and old Az would result in different overloaded definitions being seen.
Your error message is a clear one to understand (the "what") - in the context of what it's telling you, but do find out the "why", you have to dig deeper as we've done above.
Depending on how a DLL is being loaded, you can find conflicts between older and newer versions of the same DLL, which in turn impacts the downstream DLLs/applications that have been coded to expect an overload that no longer exists in the explicit form it is aligned to, resulting in the error message you're seeing.
I would also quickly add (perhaps all too obviously) that while we're talking about Az.Accounts and Microsoft.Graph.Authentication in this specific case, given the nature of PowerShell modules, a given DLL could be spread out across many more, which is why it pays to keep them all on the current branch (or near to it) when possible to do so.
This isn't solving your problem, of course, but hopefully it helps you better understand it.
Cheers,
Lain
Sep 11 2023 07:57 AM - edited Sep 11 2023 07:58 AM
@LainRobertson Thank you again for your insightful and detailed response! I am not completely sure I would be able to duplicate your detective work if this type of an issue comes up again, but at least I understand the reasons for an error like this and what direction to proceed when troubleshooting.
A few follow-up questions regarding DLLs:
One question not related to DLLs:
I am using the workaround of logging into Azure first, then getting a token to use in MgGraph commands because I'm unable to assign the needed permissions to an app registration and connect that way. That, or the command I need to execute does not support running as an app. This unfortunately necessitates logging in with a name and password, which I have to try to obfuscate the best that I can. You had mentioned that you sometimes need to do the same workaround, but you use a certificate, which is preferable. Is there a way to do this yet still use administrator roles instead of app permissions? (I apologize for not using all of the correct terms - hopefully you know what I'm getting at.)
Thanks again.
BTW, Microsoft still has not been able to respond to my ticket.
Sep 11 2023 04:15 PM
Here's some matching answers in short-form:
On the final question, I haven't come across the need to use a normal user account as everything I've done works just fine with a servicePrincipal (aka app registration), and I've only seen certificate-based authentication for the latter - though I've also had no reason to look into if it's possible for a regular user (of type "member" as distinct from "guest") account.
If I can muster up some time, I'll have a look and let you know - or maybe someone else already knows. But for now, from me, the answer for CBA on user accounts is "I don't know" (or in Australian, we simply say "dunno"!).
Cheers,
Lain