ResolveEntraID.psm1
function ConvertTo-REntraGUID { <# .SYNOPSIS Convert a string to a GUID .DESCRIPTION Convert a string to a GUID. If the string is already a GUID, it will be returned as is. .PARAMETER Identity The string to convert to a GUID. .PARAMETER Provider The provider to use for the conversion. .PARAMETER NoCache Option that no Cache will be created. ID(s) with the mapping property will not be cached. .PARAMETER IdOnly Option that only show the resolved ID. .EXAMPLE PS C:\> ConvertTo-REntraGUID -Identity "<userPrincipalName>" -Provider UserUPN Will convert the string "<userPrincipalName>" to a GUID using the provider "UserUPN". .EXAMPLE PS C:\> ConvertTo-REntraGUID -Identity "<userPrincipalName>" -Provider UserUPN -NoCache Will convert the string "<userPrincipalName>" to a GUID using the provider "UserUPN" and not cache the result. .EXAMPLE PS C:\> ConvertTo-REntraGUID -Identity "<userPrincipalName>" -Provider UserUPN -IdOnly Will convert the string "<userPrincipalName>" to a GUID using the provider "UserUPN" and only return the GUID. .EXAMPLE PS C:\> "<userPrincipalName>" | ConvertTo-REntraGUID -Provider UserUPN Will convert the string "<userPrincipalName>" to a GUID using the provider "UserUPN". #> [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [AllowEmptyCollection()] [AllowNull()] [string[]] $Identity, [Parameter(Mandatory)] [PSFArgumentCompleter("ResolveEntraID.Provider")] [PSFValidateSet(TabCompletion = "ResolveEntraID.Provider")] [string[]] $Provider, [switch] $NoCache, [switch] $IdOnly ) begin { function Write-Result { <# .SYNOPSIS Write the result .DESCRIPTION Write the result in several variants: ID, Name (resolved Property), Provider or with IdOnly Name The function will also write the result in the cache (NameIDMappingTable), if NoCache isn't set. #> [OutputType([string])] [CmdletBinding()] param ( [string] $Id, [string] $Provider, [string] $Name, [switch] $IdOnly, [switch] $NoCache ) $result = [PSCustomObject]@{ ID = $Id Name = $Name Provider = $Provider } if ($IdOnly) { $Id } else { $result } if ($NoCache) { return } if (-not $script:NameIdMappingTable[$Provider]) { $script:NameIdMappingTable[$Provider] = @{} } $script:NameIdMappingTable[$Provider][$Name] = $result } } process { :main foreach ($entry in $Identity) { if ($entry -match '^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$') { $entry continue } # Cache check for entry foreach ($providerName in $Provider) { if ($NoCache) { break } if ($script:NameIdMappingTable[$providerName].$entry) { Write-Result -Id $script:NameIdMappingTable[$providerName].$entry.ID -Name $entry -NoCache -Provider $providerName continue main } } # Resolve against Entra :providers foreach ($providerName in $Provider) { # Resolve provider to use $providerObject = $script:IdentityProvider[$providerName] if (-not $providerObject) { Write-PSFMessage -Level Error -Message "Could not find identity provider {0}. Please register or check the spelling of the provider. Known providers: {1}" -StringValues $providerObject.Name, ((Get-MeidIdentityProvider).Name -join ", ") -Target $providerObject.Name continue } # Resolve identities foreach ($queryPath in $providerObject.QueryByName) { try { $graphResponse = Invoke-EntraRequest -Path ($queryPath -f $entry) -ErrorAction Stop } catch { if ($_.ErrorDetails.Message -match '"code":\s*"Request_ResourceNotFound"') { Write-PSFMessage -Level InternalComment -Message "ID {0} could not found as {1}." -StringValues $entry, $providerObject.Name -Target $entry -Tag $providerObject.Name -ErrorRecord $_ -OverrideExceptionMessage continue } Write-PSFMessage -Level Error -Message "Error resolving {0}." -StringValues $entry -ErrorRecord $_ -Target $entry -Tag $providerObject.Name, "fail" -EnableException $true -PSCmdlet $PSCmdlet continue } if ($graphResponse) { break } } if (-not $graphResponse ) { continue providers } # Multi value handling of identities foreach ($propertyName in $providerObject.NameProperty) { $resolvedPrincipal = $graphResponse | Where-Object $propertyName -EQ $entry if ($resolvedPrincipal) { break } } if ($resolvedPrincipal.Count -gt 1) { Write-PSFMessage -Level Error -Message "Unable to uniquely identify {0} as {1}. Found {2} matches for property {3}." -StringValues $entry, $providerObject.Name, $resolvedPrincipal.Count, $propertyName continue providers } # Resolve identity to ID foreach ($propertyID in $providerObject.IDProperty) { $resolvedID = $resolvedPrincipal.$propertyID if (-not $resolvedID) { continue } break } if (-not $resolvedID) { $resolvedID = $entry Write-PSFMessage -Level SomewhatVerbose -Message "{0} of type {1} could be found but failed to resolve the {2}." -StringValues $entry, $providerObject.Name, ($providerObject.IdProperty -join ", ") -Target $entry -Tag $providerObject.Name } Write-Result -Id $resolvedID -Name $entry -Provider $providerObject.Name -IdOnly:$IdOnly -NoCache:$NoCache continue main } Write-Result -Id $entry -Name $entry -Provider "Unknown" -IdOnly:$IdOnly -NoCache } } end { } } function ConvertTo-REntraName { <# .SYNOPSIS Convert a GUID to a user defined property. .DESCRIPTION Convert a GUID to a user defined property. If the GUID is already a user defined property, it will be returned as is. .PARAMETER Identity The GUID to convert to a user defined property. .PARAMETER Provider The provider to use for the conversion. .PARAMETER NoCache Option that no Cache will be created. ID(s) with the mapping property will not be cached. .PARAMETER NameOnly Option that only show the resolved Name. .EXAMPLE PS C:\> ConvertTo-REntraName -Identity "<GUID>" -Provider UserUPN Will convert the GUID "<GUID>" to a user defined property using the provider "UserUPN". .EXAMPLE PS C:\> ConvertTo-REntraName -Identity "<GUID>" -Provider UserUPN -NoCache Will convert the GUID "<GUID>" to a user defined property using the provider "UserUPN" and not cache the result. .EXAMPLE PS C:\> "<GUID>" | ConvertTo-REntraName -Provider UserUPN Will convert the GUID "<GUID>" to a user defined property using the provider "UserUPN". .EXAMPLE PS C:\> ConvertTo-REntraName -Identity "<GUID>" -Provider UserUPN -NameOnly Will convert the GUID "<GUID>" to a user defined property using the provider "UserUPN" and only return the user defined property. #> [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [AllowEmptyCollection()] [AllowNull()] [string[]] $Identity, [Parameter(Mandatory)] [PSFArgumentCompleter("ResolveEntraID.Provider")] [PSFValidateSet(TabCompletion = "ResolveEntraID.Provider")] [string[]] $Provider, [switch] $NoCache, [switch] $NameOnly ) begin { function Write-Result { <# .SYNOPSIS Write the result .DESCRIPTION Write the result in several variants: ID, Name (resolved Property), Provider or with NameOnly Name The function will also write the result in the cache (IdNameMappingTable), if NoCache isn't set. #> [OutputType([string])] [CmdletBinding()] param ( [string] $Id, [string] $Provider, [string] $Name, [switch] $NameOnly, [switch] $NoCache ) $result = [PSCustomObject]@{ ID = $Id Name = $Name Provider = $Provider } if ($NameOnly) { $Name } else { $result } if ($NoCache) { return } if (-not $script:IdNameMappingTable[$Provider]) { $script:IdNameMappingTable[$Provider] = @{} } $script:IdNameMappingTable[$Provider][$Id] = $result } } process { :main foreach ($entry in $Identity) { if ($entry -notmatch '^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$') { $entry continue } foreach ($providerName in $Provider) { if ($NoCache) { break } if ($script:IdNameMappingTable[$providerName].$entry) { Write-Result -Id $entry -Name $script:IdNameMappingTable[$providerName].$entry.Name -NoCache -Provider $providerName -NameOnly:$NameOnly continue main } } #region iterate over providers :providers foreach ($providerName in $Provider) { $providerObject = $script:IdentityProvider[$providerName] if (-not $providerObject) { Write-PSFMessage -Level Error -Message "Could not find identity provider {0}. Please register or check the spelling of the provider. Known providers: {1}" -StringValues $providerName, ((Get-REntraIdentityProvider).Name -join ", ") -Target $providerName continue } foreach ($queryPath in $providerObject.QueryByGuid) { try { $graphResponse = Invoke-EntraRequest -Path ($queryPath -f $entry) -ErrorAction Stop } catch { if ($_.ErrorDetails.Message -match '"code":\s*"Request_ResourceNotFound"') { Write-PSFMessage -Level InternalComment -Message "ID {0} could not found as {1}." -StringValues $entry, $providerName -Target $entry -Tag $providerName -ErrorRecord $_ -OverrideExceptionMessage continue } Write-PSFMessage -Level Error -Message "Error resolving {0}." -StringValues $entry -ErrorRecord $_ -Target $entry -Tag $providerName, "fail" -EnableException $true -PSCmdlet $PSCmdlet continue } if ($graphResponse) { break } } if (-not $graphResponse ) { continue providers } foreach ($propertyName in $providerObject.NameProperty) { $resolvedName = $graphResponse.$propertyName if ($resolvedName) { break } } if (-not $resolvedName) { $resolvedName = $entry Write-PSFMessage -Level SomewhatVerbose -Message "{0} of type {1} could be found but failed to resolve the {2}." -StringValues $entry, $providerName, ($providerObject.NameProperty -join ", ") -Target $entry -Tag $providerName } Write-Result -Id $entry -Name $resolvedName -Provider $providerName -NameOnly:$NameOnly -NoCache:$NoCache continue main } #endregion iterate over providers Write-Result -Id $entry -Name $entry -Provider "Unknown" -NameOnly:$NameOnly -NoCache } } end { } } function Clear-REntraIdentityCache { <# .SYNOPSIS Clear Entra ID identiy cache. .DESCRIPTION Clear Microsoft Entra ID identiy cache. This function will clear the cache of the identity. .PARAMETER Provider Provider(s) that should be used to clear the cache. .EXAMPLE PS C:\> Clear-REntraIdentityCache Will clear all cached identities. .EXAMPLE PS C:\> Clear-REntraIdentityCache -Provider "User" Will clear the cached identities for the provider "User". .EXAMPLE PS C:\> Clear-REntraIdentityCache -Provider "User","Group" Will clear the cached identities for the providers "User" and "Group". #> [CmdletBinding()] param ( [string[]] $Provider ) if (-not $Provider) { $script:IdNameMappingTable = @{} $script:NameIdMappingTable = @{} } else { foreach ($providerName in $Provider) { $script:IdNameMappingTable.Remove($providerName) $script:NameIdMappingTable.Remove($providerName) } } } function Get-REntraIdentityCache { <# .SYNOPSIS Get Entra ID identiy cache. .DESCRIPTION Get Microsoft Entra ID identiy cache. This function will get all cached identities. .PARAMETER Provider Provider(s) that should be used to get the cache. .EXAMPLE PS C:\> Get-REntraIdentityCache Will get all cached identities. .EXAMPLE PS C:\> Get-REntraIdentityCache -Provider "User" Will get the cached identities for the provider "User". .EXAMPLE PS C:\> Get-REntraIdentityCache -Provider "User","Group" Will get the cached identities for the providers "User" and "Group". #> [OutputType([hashtable])] [CmdletBinding()] param ( [string[]] $Provider ) if (-not $Provider) { $script:IdNameMappingTable $script:NameIdMappingTable } else { foreach ($providerName in $Provider) { $script:IdNameMappingTable[$providerName] $script:NameIdMappingTable[$providerName] } } } function Get-REntraIdentityProvider { <# .SYNOPSIS Get Entra ID identity provider. .DESCRIPTION Get Microsoft Entra ID identity provider. This function will get all registered providers. .PARAMETER ProviderName Name(s) of the Entra ID identity provider. .EXAMPLE PS C:\> Get-REntraIdentityProvider Will get all providers. .EXAMPLE PS C:\> Get-REntraIdentityProvider -ProviderName "*" Will get all providers. .EXAMPLE PS C:\> Get-REntraIdentityProvider -ProviderName "User" Will get the provider with name "User". .EXAMPLE PS C:\> Get-REntraIdentityProvider -ProviderName "User*" Will get all providers with name starting with "User". .EXAMPLE PS C:\> Get-REntraIdentityProvider -ProviderName "*User" Will get all providers with name ending with "User". .EXAMPLE PS C:\> Get-REntraIdentityProvider -ProviderName "*User*" Will get all providers with name containing "User". #> [CmdletBinding()] param ( [PSFArgumentCompleter("ResolveEntraID.Provider")] [string] $ProviderName = '*' ) process { $script:IdentityProvider.Values | Where-Object Name -Like $ProviderName } } function Register-REntraIdentityProvider { <# .SYNOPSIS Register Entra ID identity provider. .DESCRIPTION Register Microsoft Entra ID identity provider. This function will register a provider with the defined properties. Per default the provider are "User", "Group" and "Application" for more information, check the examples of this function. .PARAMETER ProviderName Name(s) of the Entra ID identity provider. .PARAMETER NameProperty Property(s) to search for. E.g.: userPrincipalName .PARAMETER IDProperty Property(s) to return. E.g.: id .PARAMETER QueryByName Query(s) to search for the property. E.g.: users?`$filter=userPrincipalName eq '{0}' .PARAMETER QueryByGUID Query(s) to search for the GUID. E.g.: users/{0} .EXAMPLE PS C:\> Register-REntraIdentityProvider -ProviderName "User" -NameProperty "userPrincipalName", "mail" -IDProperty "id" -QueryByName "users?`$filter=userPrincipalName eq '{0}' or mail eq '{0}'", "users?`$filter=Name eq '{0}'" -QueryByGUID "users/{0}" Will register a provider with name "User", the property to search for "userPrincipalName" and "mail" with the query to get the GUID "users?`$filter=userPrincipalName eq '{0}' or mail eq '{0}'" or "users?`$filter=Name eq '{0}'" or to get the userPrincipalName "users/{0}". .EXAMPLE PS C:\> Register-REntraIdentityProvider -ProviderName "Group" -NameProperty "displayName" -IDProperty "id" -QueryByName "groups?`$filter=displayName eq '{0}'" -QueryByGUID "groups/{0}" Will register a provider with name "Group", the property to search for "displayName" with the query to get the GUID "groups?`$filter=displayName eq '{0}'" or to get the displayName "groups/{0}". .EXAMPLE PS C:\> Register-REntraIdentityProvider -ProviderName "Application" -NameProperty "displayName" -IDProperty "appId", "id" -QueryByName "applications?`$filter=displayName eq '{0}'", "servicePrincipals?`$filter=displayName eq '{0}'" -QueryByGUID "applications/{0}", "servicePrincipals(appId='{0}')", "servicePrincipals/{0}" Will register a provider with name "Application", the property to search for "displayName" with the query to get the GUID "applications?`$filter=displayName eq '{0}'" or to get the displayName "applications/{0}". Will register a provider with name "Application", the property to search for "displayName" with the query to get the GUID "servicePrincipals?`$filter=displayName eq '{0}'" or to get the displayName "servicePrincipals(appId='{0}')". Will register a provider with name "Application", the property to search for "displayName" with the query to get the GUID "servicePrincipals?`$filter=displayName eq '{0}'" or to get the displayName "servicePrincipals/{0}". #> [CmdletBinding()] param ( [Parameter(Mandatory)] [string[]] $ProviderName, [Parameter(Mandatory)] [string[]] $NameProperty, [Parameter(Mandatory)] [string[]] $IDProperty, [Parameter(Mandatory)] [string[]] $QueryByName, [Parameter(Mandatory)] [string[]] $QueryByGUID ) process { $queriesName = foreach ($item in $QueryByName) { if ($item -match "\{0\}") { $item; continue } $item.TrimEnd("/").Replace("{", "{{").Replace("}", "}}"), "{0}" -join "/" } $queriesGUID = foreach ($item in $QueryByGUID) { if ($item -match "\{0\}") { $item; continue } $item.TrimEnd("/").Replace("{", "{{").Replace("}", "}}"), "{0}" -join "/" } foreach ($entry in $ProviderName) { $script:IdentityProvider[$entry] = [PSCustomObject]@{ Name = $entry NameProperty = $NameProperty IDProperty = $IDProperty QueryByName = $queriesName QueryByGUID = $queriesGUID PSTypeName = "ResolveEntraID.Provider" } } } } function Resolve-REntraIdentity { <# .SYNOPSIS Resolve Entra ID identity. .DESCRIPTION Resolve Microsoft Entra ID identity. This function will resolve an ID to a property or resolve a property to a ID. Requires an active connection to Azure with EntraAuth. Default service for EntraAuth is "ResolveEntraGraph". .PARAMETER Identity ID(s) that should be resolved by the function. .PARAMETER Provider Provider(s) that should be used to resolve the ID(s). .PARAMETER ResultType Option to define the result type. Default is "Name". .PARAMETER NoCache Option that no Cache will be created. ID(s) with the mapping property will not be cached. .PARAMETER NameOnly Option that only show the resolved name. .EXAMPLE PS C:\> Resolve-REntraIdentity -Identity "<ID>" -Provider UserUPN -ResultType Name Will resolve the ID "<ID>" with defined property in the provider "UserUPN". The written output is ID, Name (Property), Provider and the result will be written in the cache. .EXAMPLE PS C:\> Resolve-REntraIdentity -Identity "<Property>" -Provider UserUPN -ResultType ID Will resolve the Name (Property) "<Property>" with defined property in the provider "UserUPN". The written output is ID, Name (Property), Provider and the result will be written in the cache. .EXAMPLE PS C:\> Resolve-REntraIdentity -Identity "<ID>","<ID2>" -Provider UserUPN,Group Will resolve the IDs "<ID>" and "<ID2>" with defined property in the providers "UserUPN" and "Group". The written output is ID, Name (Property), Provider and the result will be written in the cache. .EXAMPLE PS C:\> Resolve-REntraIdentity -Identity "<ID>","<ID2>" -Provider UserUPN,Group -NoCache Will resolve the IDs "<ID>" and "<ID2>" with defined property in the providers "UserUPN" and "Group". The written output is ID, Name (Property), Provider and the result will NOT be written in the cache. .EXAMPLE PS C:\> Resolve-REntraIdentity -Identity "<ID>","<ID2>" -Provider UserUPN,Group -NoCache -NameOnly Will resolve the IDs "<ID>" and "<ID2>" with defined property in the providers "UserUPN" and "Group". The written output is only Name (Property) and the result will NOT be written in the cache. .EXAMPLE PS C:\> Resolve-REntraIdentity -Identity "<Property>","<Property2>" -Provider UserUPN,Group -NoCache -ResultType ID -IdOnly Will resolve the Name (Property) "<Property>" and "<Property2>" with defined property in the providers "UserUPN" and "Group". The written output is only the ID and the result will NOT be written in the cache. .EXAMPLE PS C:\> "<ID>" | Resolve-REntraIdentity -Provider UserUPN Will resolve the ID "<ID>" with defined property in the provider "UserUPN". The written output is ID, Name (Property), Provider and the result will be written in the cache. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', ('Provider','NoCache', 'NameOnly') , Justification = 'Provider, NoCache and NameOnly are used in the function, in a steppable pipeline and should not be suppressed.')] [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [AllowEmptyCollection()] [AllowNull()] [string[]] $Identity, [Parameter(Mandatory)] [PSFArgumentCompleter("ResolveEntraID.Provider")] [PSFValidateSet(TabCompletion = "ResolveEntraID.Provider")] [string[]] $Provider, [ValidateSet("Name", "ID")] [string] $ResultType = "Name", [switch] $NoCache, [Alias("IdOnly")] [switch] $NameOnly ) begin { Assert-EntraConnection -Cmdlet $PSCmdLet -Service $Script:PSDefaultParameterValues["Invoke-EntraRequest:Service"] # GetSteppablePipeline is used to create a portable pipeline, that allows pausing and resuming the enclosed command as needed. # Effectively this means, the wrapped command will only be run once, no matter the numbers of input ids. # This significantly improves performance. $command = switch ($ResultType) { "Name" { { ConvertTo-REntraName -Provider $Provider -NoCache:$NoCache -NameOnly:$NameOnly }.GetSteppablePipeline() } "ID" { { ConvertTo-REntraGUID -Provider $Provider -NoCache:$NoCache -IdOnly:$NameOnly }.GetSteppablePipeline() } } $command.begin($true) } process { foreach ($entry in $Identity) { $command.Process($entry) } } end { $command.End() } } function Set-REntraConnection { <# .SYNOPSIS Set the default service for ResolveEntraID. .DESCRIPTION Set the default service for for ResolveEntraID. .PARAMETER Name The name of the service. Default is "ResolveEntraGraph". .EXAMPLE PS C:\> Set-REntraConnection -Name "ResolveEntraGraph" Will set the default service for Invoke-EntraRequest to "ResolveEntraGraph" #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param ( [Parameter(Mandatory)] [PSFValidateSet(TabCompletion = "ResolveEntraID.EntraService")] [PsfArgumentCompleter("ResolveEntraID.EntraService")] [string] $Name ) process { $Script:PSDefaultParameterValues["Invoke-EntraRequest:Service"] = $Name } } function Unregister-REntraIdentityProvider { <# .SYNOPSIS Unregister Entra ID identity provider. .DESCRIPTION Unregister Microsoft Entra ID identity provider. This function will unregister a provider. .PARAMETER ProviderName Name(s) of the Entra ID identity provider. .EXAMPLE PS C:\> Get-REntraIdentityProvider -ProviderName "*" Will unregister all providers. .EXAMPLE PS C:\> Unregister-REntraIdentityProvider -ProviderName "User" Will unregister the provider with name "User". .EXAMPLE PS C:\> Unregister-REntraIdentityProvider -ProviderName "User","Group" Will unregister the providers with name "User" and "Group". .EXAMPLE PS C:\> Get-REntraIdentityProvider -ProviderName "User*" Will unregister all providers with name starting with "User". .EXAMPLE PS C:\> "User" | Unregister-REntraIdentityProvider Will unregister the provider with name "User". #> [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [PSFArgumentCompleter("ResolveEntraID.Provider")] [PSFValidateSet(TabCompletion = "ResolveEntraID.Provider")] [string[]] $ProviderName ) process { foreach ($entry in $ProviderName ) { Clear-REntraIdentityCache -Provider $entry $script:IdentityProvider.Remove($entry) } } } # ID for Name mapping $script:IdNameMappingTable = @{} # Name for ID mapping $script:NameIdMappingTable = @{} # Identity Provider $script:IdentityProvider = @{} Register-PSFTeppScriptblock -Name ResolveEntraID.Provider -ScriptBlock { foreach ($provider in Get-MeidIdentityProvider){ @{ Text = $provider.Name ToolTip = "{0} --> Property: {1}" -f $provider.Name, ($provider.NameProperty -join ", ") } } } Register-PSFTeppScriptblock -Name ResolveEntraID.EntraService -ScriptBlock { foreach ($service in Get-EntraService){ @{ Text = $service.Name ToolTip = "{0} --> ServiceUrl: {1}" -f $service.Name, $service.ServiceUrl } } } $param = @{ ProviderName = "Application" NameProperty = "displayName" IdProperty = "appId", "id" QueryByName = "applications?`$filter=displayName eq '{0}'", "servicePrincipals?`$filter=displayName eq '{0}'" QueryByGUID = "applications/{0}", "servicePrincipals(appId='{0}')", "servicePrincipals/{0}" } Register-REntraIdentityProvider @param $param = @{ Name = 'ResolveEntraGraph' ServiceUrl = 'https://graph.microsoft.com/beta' Resource = 'https://graph.microsoft.com' DefaultScopes = @() HelpUrl = 'https://developer.microsoft.com/en-us/graph/quick-start' } Register-EntraService @param $Script:PSDefaultParameterValues["Invoke-EntraRequest:Service"] = "ResolveEntraGraph" $param = @{ ProviderName = "Group" NameProperty = "displayName" IdProperty = "id" QueryByName = "groups?`$filter=displayName eq '{0}'" QueryByGUID = "groups/{0}" } Register-REntraIdentityProvider @param $param = @{ ProviderName = "User" NameProperty = "userPrincipalName", "mail" IdProperty = "id" QueryByName = "users?`$filter=userPrincipalName eq '{0}' or mail eq '{0}'", "users?`$filter=Name eq '{0}'" QueryByGUID = "users/{0}" } Register-REntraIdentityProvider @param |