AzureAD / MSAL.PS

MIT License
159 stars 29 forks source link

The property 'Authority' cannot be found on this object. #45

Closed HAL377 closed 2 years ago

HAL377 commented 2 years ago

Hi,

With version 4.21.0.1 I was able to run this without any issues

Get-MsalToken -TenantId $TenantId -ClientId $ClientId -Scopes "User.ReadWrite.All","Directory.ReadWrite.All" -UserCredential $Credentials

but with the release 4.37.0.0 I get suddenly this error:

**_The property 'Authority' cannot be found on this object. Verify that the property exists. At C:\Program Files\WindowsPowerShell\Modules\MSAL.PS\4.37.0.0\Get-MsalToken.ps1:338 char:38

The ClientID is that of Microsoft Graph PowerShell (14d82eec-204b-4c2f-b7e8-296a70dab67e), and credentials are captured with Get-Credential.

I did the test within the same PS Session, same variables, simply changing the modules with -RequiredVersion during the import and I get to the error.

My Credential is a federated user identity.

Thanks for your feedback

Sincerely, Tonino Bruno ENGIE SA

EMarcais commented 2 years ago

Hi Hal37,

Had the same issue using this line: $Token = (Get-MsalToken -ClientId ($Config.ScriptMainConfig.TenantConfig.clientId) -TenantId ($Config.ScriptMainConfig.TenantConfig.tenantId) -ClientCertificate $thumbPrint).AccessToken

To resolve this, while waiting for an answer from Repo's maintainer, I opened the file Get-MsalToken.ps1 in the module folder and just commented the elseif line:

"*" {
                if ($AzureCloudInstance -and $TenantId) { [void] $AquireTokenParameters.WithAuthority($AzureCloudInstance, $TenantId) }
                elseif ($AzureCloudInstance) { [void] $AquireTokenParameters.WithAuthority($AzureCloudInstance, 'common') }
                #elseif ($TenantId) { [void] $AquireTokenParameters.WithAuthority(('https://{0}' -f $ClientApplication.AppConfig.Authority.AuthorityInfo.Host), $TenantId) }
                if ($Authority) { [void] $AquireTokenParameters.WithAuthority($Authority.AbsoluteUri) }

Hope this will help you to run the script with the latest version

abgreg commented 2 years ago

+1 Same for me. (Context: Internal Microsoft / Office tooling) Goods news: I'm the only one on my team reproing this so far. Bad news: This is a pretty blocking issue for me - reproing across accounts, machines, and scenarios.

ioamnesia commented 2 years ago

Ok, digging further, it looks like there was a change to the Microsoft.Identity.Client package that modified the members of ClientApplicationBase to put an Authority member and nest the existing AuthorityInfo member under that. Check your installed version using Get-Package Microsoft.Identity.Client. I had 4.16.0 installed and encountered this same error.

ioamnesia commented 2 years ago

It looks like the module directory has compatible versions of the Microsoft.Identity.Client dlls in it. Is it possible that, if an older version was installed using Install-Package, that Powershell is loading the dlls from the older package instead of the module directory?

ioamnesia commented 2 years ago

@HAL377 @EMarcais @abgreg

I was able to fix this by uninstalling any older nuget packages for Microsoft.Identity.Client and then uninstalling and reinstalling the MSAL.PS module.

abgreg commented 2 years ago

Interesting... I don't think that I have such a package installed?

PS C:\WINDOWS\system32> Get-Package Microsoft.Identity.Client
Get-Package : No package found for 'Microsoft.Identity.Client'.
ioamnesia commented 2 years ago

Interesting... I don't think that I have such a package installed?

PS C:\WINDOWS\system32> Get-Package Microsoft.Identity.Client
Get-Package : No package found for 'Microsoft.Identity.Client'.

I'm not sure if PS will return different results depending on if it's running as admin or not like it does with modules, but that is a possibility. If you check both and don't see it I'm not sure where it would be loading from, but an older version has to be the cause. There was definitely a change to the ClientApplicationBase object that the ConfidentialClientApplication inherits from that added the Authority member and moved the AuthorityInfo under it. I'm not sure what version that was though. The New-MSALToken cmdlet changed that reference on line 338 in the latest update and that's definitely what we're seeing with this error.

As a test, you could try opening a new PS instance and use Add-Type to load the two dlls in the modules directory to load the proper version before importing the module and see if that somehow helps.

Hopefully a developer will be able to shed more light on this.

HAL377 commented 2 years ago

Hi,

I tried your suggestion to add those DLL's directly but it did not change on my end... But perhaps I did not load the correct ones?

MSAL.PS\4.37.0.0\Microsoft.Identity.Client.4.37.0\net45\Microsoft.Identity.Client.dll MSAL.PS\4.37.0.0\Microsoft.Identity.Client.Desktop.4.37.0\net461\Microsoft.Identity.Client.Desktop.dll

image

jazuntee commented 2 years ago

For those who are able to reproduce this, do you have any profile scripts that auto-run or other modules imported before importing MSAL.PS? MSAL.PS will allow you to use an old version of the dll libraries if they are already imported into the session. This is a common issue with the Az modules. MSAL.PS should prompt you though when this dll conflict occurs allowing you to proceed but warning you that some functionality might not work correctly.

JBines commented 2 years ago

I replaced line 338 in the module with below and it works for me

elseif ($TenantId) { [void] $AquireTokenParameters.WithAuthority(('https://{0}' -f $ClientApplication.AppConfig.AuthorityInfo.Host), $TenantId) }

image

https://github.com/ioamnesia/MSAL.PS/commit/abdea2b61f147273466ed3015dcded893ee7acdc

jakubmank commented 2 years ago

Got the same problem in my script. The reason was ExchangeOnlineManagement module. One of its cmdlet was called before Get-MsalToken therefore the MSAL.PS module was not imported as first. I had to explictly put Import-Module MSAL.PS at the top of file (or just before using any other cmdlet which could load different module).

mmascolino commented 2 years ago

I too ran into the issue with the collision of ExchangeOnlineManagement and Get-MSALToken. The simple solution was to use Get-MSALToken in a fresh PowerShell session.

mortenlerudjordet commented 2 years ago

The same issue also exist using MSAL.PS with the MicrosoftTeams module. At the moment I'm using version 4.36.1.2 of MSAL.PS without issue, but new version does not work.

I'm using MSAL with SP and a AAD user for delegated permissions.

In a fresh powershell (5.1) session i need to run:

Import-Module MSAL.PS -MaximumVersion 4.36.1.2 -ErrorAction Continue -ErrorVariable oErr -Verbose:$false
if($oErr)
{
    Write-Error -Message "Failed to import supporten module version of: MSAL.PS" -ErrorAction Stop
}

Import-Module MicrosoftTeams -MaximumVersion 3.0.0 -ErrorAction Continue -ErrorVariable oErr -Verbose:$false
if($oErr)
{
    Write-Error -Message "Failed to import supporten module version of: MicrosoftTeams" -ErrorAction Stop
}

Commenting out line 338 worked and I get a token, replacing the code with what @JBines suggested does not work for my scenario.

Also commenting out the code on line 338 I can run with the latest version of both MSAL.PS and MicrosoftTeams for combined SP and delegated AAD user.

    $GraphConnectionDetails = @{
        'TenantId'       = $AzureConnection.TenantId
        'ClientId'       = $AzureConnection.ApplicationId
        'UserCredential' = $TeamsServiceAccount
        'Scope'          = $GraphScope
        'RedirectURI'    = $RedirectURI
    }
mortenlerudjordet commented 2 years ago

I added the following code instead on line 338, and this seems to do the trick with object structure conflicts.

elseif ($TenantId) {
    if( Get-Member -InputObject $ClientApplication.AppConfig -Name "AuthorityInfo" -MemberType Properties )
    {
        [void] $AquireTokenParameters.WithAuthority(('https://{0}' -f $ClientApplication.AppConfig.AuthorityInfo.Host), $TenantId)
    }
    else
    {
        [void] $AquireTokenParameters.WithAuthority(('https://{0}' -f $ClientApplication.AppConfig.Authority.AuthorityInfo.Host), $TenantId)
    }
}
o-l-a-v commented 2 years ago

Could it be related to assembly dependency conflicts?


I was checking out MSAL.PS today for replacing following code for generating access token with app id and secret only:

# Settings
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12

# Assets
$AppRegistration = [pscredential](Get-Credential -Message 'App Id and secret')
$TenantInitialDomain = [string] '<your_initial_domain>.onmicrosoft.com'
$TenantId = [string](
    (Invoke-RestMethod -Uri ('https://login.microsoftonline.com/{0}/.well-known/openid-configuration'-f$TenantInitialDomain) -Method 'Get').'userinfo_endpoint'.Split('/')[3]
)
$Body = [hashtable]@{
    'client_id'     = $AppRegistration.'Username'
    'client_secret' = $AppRegistration.GetNetworkCredential().'Password'
    'scope'         = 'https://graph.microsoft.com/.default'
    'grant_type'    = 'client_credentials'
}

# Get access token
$AccessToken = Invoke-RestMethod -Method 'Post' ('https://login.microsoftonline.com/{0}/oauth2/v2.0/token' -f $TenantId) -Body $Body

# Example use - Connect with Microsoft.Graph.Authentication
$null = Connect-MgGraph -AccessToken $AccessToken.'access_token'

But got the "The property 'Authority' cannot be found on this object" error. I added the code here as it might be helpful for others in same situation. Until MSAL.PS get's up and running again.

mortenlerudjordet commented 2 years ago

I'm running MSAL.PS in one location for both 5.1 and 7.2. Usually when the error crops up is when I switch between the runtimes, though have not spent to much time understanding where the problem comes from.

I did a debug through VSCode and saw that the $ClientApplication substructure was a bit different when it errors out. Guess that might be because different Microsoft.Identity.Client.dll are loaded into 5.1 and 7.2.

Compensating for the object structure difference, I did not get any other errors and the token was received as expected.

err-unknown-username commented 2 years ago

@mortenlerudjordet your post as of 9 days ago (Mar-12?) looks like a good work around.

@jasoth / @apurvghai : do you know what the release process for this project is?

agrecaBAS commented 2 years ago

On the off chance is anyone having this issue after importing Graph modules? I just discovered that I get this error if I run any of the following commands before running Get-MSALToken. I'm assuming it's going to be any Graph modules though.

Select-MgProfile -Name "beta"

Import-Module Microsoft.Graph.Users Import-Module Microsoft.Graph.Identity.Signins Import-Module Microsoft.Graph.Authentication

It appears this also happens when using the Connect-PnPOnline module.

I need to run the Get-MSALToken command before anything else in order to avoid this error. This is a better workaround for those who don't want to modify the module file.

mortenlerudjordet commented 2 years ago

@agrecaBAS, I import MSAL before graph and that seems to not give me the error

jazuntee commented 2 years ago

This error and numerous others can happen when the DLLs included with MSAL.PS cannot be loaded due to a conflict with another DLL loaded in the current PowerShell session, often from another module like Azure or Exchange Online Admin Shell.

You should see the following prompt during import when this occurs and as the message indicates, "Some module functionality will not work."

Ignore assembly conflict and continue importing module?
Some module functionality will not work.
[Y] Yes  [N] No  [?] Help (default is "N"):

As a workaround, I would suggest ensuring that the MSAL.PS module is loaded into the PowerShell session first before any other modules. There is a fix to this but it would require significant rework of the MSAL.PS module in C# so no guarantee this will be addressed anytime soon, if ever.

DMahalko commented 1 year ago

(This didn't thread correctly? Not sure how to comment on a closed issue..) Source: https://github.com/AzureAD/MSAL.PS/issues/45#issuecomment-1073692573

I was checking out MSAL.PS today for replacing following code for generating access token with app id and secret only: [....] But got the "The property 'Authority' cannot be found on this object" error. I added the code here as it might be helpful for others in same situation. Until MSAL.PS get's up and running again.

Can you explain why you care about MSAL.PS if the workaround code in your comment does the job required?

$AppID = ...
$AppSecret = ...
$TenantID = ...
$Body = [hashtable]@{
    'client_id'     = $AppID
    'client_secret' = $AppSecret
    'scope'         = 'https://graph.microsoft.com/.default'
    'grant_type'    = 'client_credentials'
}
$AccessToken = Invoke-RestMethod -Method 'Post' `
  ('https://login.microsoftonline.com/{0}/oauth2/v2.0/token' `
  -f $TenantId) -Body $Body

# Connect with Microsoft.Graph.Authentication
Connect-MgGraph -AccessToken $AccessToken.'access_token'

This works, and I don't need to load any additional modules. I have no idea what is "wrong" with doing this vs using Get-MsalToken..

o-l-a-v commented 1 year ago

@DMahalko

Because 1) IMO this functionality should work in such a module, and 2) I'd rather update an module than code.

Zachbanderson commented 1 year ago

I know this thread has been closed for a while, but installing the module first thing was an unreliable fix due to my environment. Adding a "-AzureCloudInstance 1" to the function call fixed it.

So my code became: Get-MsalToken -ClientId $ClientId -TenantId $TenantId -ClientSecret $ClientSecret -AzureCloudInstance 1

Here is a link to how the AzureCloudInstance parameter works. It's in C# but it translates to PowerShell too.

clearchaos3 commented 1 year ago

I know this thread has been closed for a while, but installing the module first thing was an unreliable fix due to my environment. Adding a "-AzureCloudInstance 1" to the function call fixed it.

So my code became: Get-MsalToken -ClientId $ClientId -TenantId $TenantId -ClientSecret $ClientSecret -AzureCloudInstance 1

Here is a link to how the AzureCloudInstance parameter works. It's in C# but it translates to PowerShell too.

My man, you are a life saver! This worked for me as well. Thank you.