PSIntuneAuth.psm1
function Get-MSIntuneAuthToken { <# .SYNOPSIS Get an authentication token required for interacting with Microsoft Intune using Microsoft Graph API NOTE: This function requires that AzureAD module is installed. Use 'Install-Module -Name AzureAD' to install it. .PARAMETER TenantName A tenant name should be provided in the following format: tenantname.onmicrosoft.com. .PARAMETER ClientID Application ID for an Azure AD application. Uses by default the Microsoft Intune PowerShell application ID. .PARAMETER ClientSecret Web application client secret. .PARAMETER Credential Specify a PSCredential object containing username and password. .PARAMETER Resource Resource recipient (app, e.g. Graph API). Leave empty to use https://graph.microsoft.com as default. .PARAMETER RedirectUri Redirect URI for Azure AD application. Leave empty to leverage Azure PowerShell well known redirect URI. .PARAMETER PromptBehavior Set the prompt behavior when acquiring a token. .EXAMPLE # Manually specify username and password to acquire an authentication token: Get-MSIntuneAuthToken -TenantName domain.onmicrsoft.com # Manually specify username and password to acquire an authentication token using a specific client ID: Get-MSIntuneAuthToken -TenantName domain.onmicrsoft.com -ClientID "<GUID>" # Retrieve a PSCredential object with username and password to acquire an authentication token: $Credential = Get-Credential Get-MSIntuneAuthToken -TenantName domain.onmicrsoft.com -Credential $Credential # Retrieve a PSCredential object for usage with Azure Automation containing the username and password to acquire an authentication token: $Credential = Get-AutomationPSCredential -Name "<CredentialName>" Get-MSIntuneAuthToken -TenantName domain.onmicrsoft.com -ClientID "<GUID>" -Credential $Credential .NOTES Author: Nickolaj Andersen Contact: @NickolajA Created: 2017-09-27 Updated: 2020-01-28 Version history: 1.0.0 - (2017-09-27) Function created 1.0.1 - (2017-10-08) Added ExpiresOn property 1.0.2 - (2018-01-22) Added support for specifying PSCredential object for silently retrieving an authentication token without being prompted 1.0.3 - (2018-01-22) Fixed an issue with prompt behavior parameter not being used 1.0.4 - (2018-01-22) Fixed an issue when detecting the AzureAD module presence 1.0.5 - (2018-01-22) Enhanced the AzureAD module detection logic 1.0.6 - (2018-01-28) Changed so that the Microsoft Intune PowerShell application ID is set as default for ClientID parameter 1.2.0 - (2019-10-27) Added support for using app-only authentication using a client ID and client secret for a web app. Resource recipient is now also possible to specify directly on the command line instead of being hard-coded. Now using the latest authority URI and installs the AzureAD module automatically. 1.2.1 - (2020-01-15) Fixed an issue where when multiple versions of the AzureAD module installed would cause an error attempting in re-installing the Azure AD module 1.2.2 - (2020-01-28) Added more verbose logging output for further troubleshooting in case an auth token is not aquired #> [CmdletBinding()] param( [parameter(Mandatory=$true, ParameterSetName="AuthPrompt", HelpMessage="A tenant name should be provided in the following format: tenantname.onmicrosoft.com.")] [parameter(Mandatory=$true, ParameterSetName="AuthCredential")] [parameter(Mandatory=$false, ParameterSetName="AuthAppOnly")] [ValidateNotNullOrEmpty()] [string]$TenantName, [parameter(Mandatory=$false, ParameterSetName="AuthPrompt", HelpMessage="Application ID for an Azure AD application. Uses by default the Microsoft Intune PowerShell application ID.")] [parameter(Mandatory=$false, ParameterSetName="AuthCredential")] [parameter(Mandatory=$false, ParameterSetName="AuthAppOnly")] [ValidateNotNullOrEmpty()] [string]$ClientID = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547", [parameter(Mandatory=$true, ParameterSetName="AuthAppOnly", HelpMessage="Web application client secret.")] [ValidateNotNullOrEmpty()] [string]$ClientSecret, [parameter(Mandatory=$true, ParameterSetName="AuthCredential", HelpMessage="Specify a PSCredential object containing username and password.")] [ValidateNotNullOrEmpty()] [PSCredential]$Credential, [parameter(Mandatory=$false, ParameterSetName="AuthPrompt", HelpMessage="Resource recipient (app, e.g. Graph API). Leave empty to use https://graph.microsoft.com as default.")] [parameter(Mandatory=$false, ParameterSetName="AuthCredential")] [parameter(Mandatory=$false, ParameterSetName="AuthAppOnly")] [ValidateNotNullOrEmpty()] [string]$Resource = "https://graph.microsoft.com", [parameter(Mandatory=$false, ParameterSetName="AuthPrompt", HelpMessage="Redirect URI for Azure AD application. Leave empty to leverage Azure PowerShell well known redirect URI.")] [parameter(Mandatory=$false, ParameterSetName="AuthCredential")] [ValidateNotNullOrEmpty()] [string]$RedirectUri = "urn:ietf:wg:oauth:2.0:oob", [parameter(Mandatory=$false, ParameterSetName="AuthPrompt", HelpMessage="Set the prompt behavior when acquiring a token.")] [parameter(Mandatory=$false, ParameterSetName="AuthCredential")] [ValidateNotNullOrEmpty()] [ValidateSet("Auto", "Always", "Never", "RefreshSession")] [string]$PromptBehavior = "Auto" ) Process { $ErrorActionPreference = "Stop" # Determine if the AzureAD module needs to be installed or updated to latest version try { Write-Verbose -Message "Attempting to locate AzureAD module on local system" $AzureADModule = Get-Module -Name "AzureAD" -ListAvailable -ErrorAction Stop -Verbose:$false if ($AzureADModule -ne $null) { if (($AzureADModule | Measure-Object).Count -eq 1) { $CurrentModuleVersion = Get-Module -Name "AzureAD" -ListAvailable -ErrorAction Stop -Verbose:$false | Select-Object -ExpandProperty Version } else { $CurrentModuleVersion = Get-Module -Name "AzureAD" -ListAvailable -ErrorAction Stop -Verbose:$false | Sort-Object -Property Version -Descending | Select-Object -First 1 -ExpandProperty Version } $LatestModuleVersion = (Find-Module -Name "AzureAD" -ErrorAction Stop -Verbose:$false).Version Write-Verbose -Message "AzureAD module detected, checking for latest version" if ($LatestModuleVersion -gt $CurrentModuleVersion) { Write-Verbose -Message "Latest version of AzureAD module is not installed, attempting to install: $($LatestModuleVersion.ToString())" $UpdateModuleInvocation = Update-Module -Name "AzureAD" -Scope "AllUsers" -Force -ErrorAction Stop -Confirm:$false -Verbose:$false } else { Write-Verbose -Message "Latest version for AzureAD module was detected, continue to aquire authentication token" } } else { throw "Unable to detect Azure AD module" } } catch [System.Exception] { Write-Warning -Message "Unable to detect AzureAD module, attempting to install from online repository" try { # Install NuGet package provider $PackageProvider = Install-PackageProvider -Name NuGet -Force -Verbose:$false # Install AzureAD module Install-Module -Name "AzureAD" -Scope AllUsers -Force -ErrorAction Stop -Confirm:$false -Verbose:$false Write-Verbose -Message "Successfully installed AzureAD" } catch [System.Exception] { Write-Warning -Message "An error occurred while attempting to install AzureAD module. Error message: $($_.Exception.Message)"; break } } try { # Get installed Azure AD module $AzureADModules = Get-Module -Name "AzureAD" -ListAvailable -ErrorAction Stop -Verbose:$false if ($AzureADModules -ne $null) { # Check if multiple modules exist and determine the module path for the most current version if (($AzureADModules | Measure-Object).Count -gt 1) { $LatestAzureADModule = ($AzureADModules | Select-Object -Property Version | Sort-Object)[-1] $AzureADModulePath = $AzureADModules | Where-Object { $_.Version -like $LatestAzureADModule.Version } | Select-Object -ExpandProperty ModuleBase } else { $AzureADModulePath = $AzureADModules | Select-Object -ExpandProperty ModuleBase } try { # Construct array for required assemblies from Azure AD module $Assemblies = @( (Join-Path -Path $AzureADModulePath -ChildPath "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"), (Join-Path -Path $AzureADModulePath -ChildPath "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll") ) # Load required assemblies Add-Type -Path $Assemblies -ErrorAction Stop -Verbose:$false try { # Construct variable for authority URI switch ($PSCmdlet.ParameterSetName) { "AuthAppOnly" { $Authority = "https://login.microsoftonline.com/$($TenantName)" } default { $Authority = "https://login.microsoftonline.com/$($TenantName)/oauth2/v2.0/token" } } # Construct new authentication context $AuthenticationContext = New-Object -TypeName "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $Authority -ErrorAction Stop # Construct platform parameters $PlatformParams = New-Object -TypeName "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList $PromptBehavior -ErrorAction Stop try { # Determine parameters when acquiring token Write-Verbose -Message "Currently running in parameter set context: $($PSCmdlet.ParameterSetName)" switch ($PSCmdlet.ParameterSetName) { "AuthPrompt" { # Acquire access token Write-Verbose -Message "Attempting to acquire access token using user delegation" $AuthenticationResult = ($AuthenticationContext.AcquireTokenAsync($Resource, $ClientID, $RedirectUri, $PlatformParams)).Result } "AuthCredential" { # Construct required identity model user password credential Write-Verbose -Message "Attempting to acquire access token using legacy user delegation with username and password" $UserPasswordCredential = New-Object -TypeName "Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential" -ArgumentList ($Credential.UserName, $Credential.Password) -ErrorAction Stop # Acquire access token $AuthenticationResult = ([Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($AuthenticationContext, $Resource, $ClientID, $UserPasswordCredential)).Result } "AuthAppOnly" { # Construct required identity model client credential Write-Verbose -Message "Attempting to acquire access token using app-based authentication" $ClientCredential = New-Object -TypeName "Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential" -ArgumentList ($ClientID, $ClientSecret) -ErrorAction Stop # Acquire access token $AuthenticationResult = ($AuthenticationContext.AcquireTokenAsync($Resource, $ClientCredential)).Result } } # Check if access token was acquired if ($AuthenticationResult.AccessToken -ne $null) { Write-Verbose -Message "Successfully acquired an access token for authentication" # Construct authentication hash table for holding access token and header information $Authentication = @{ "Content-Type" = "application/json" "Authorization" = -join("Bearer ", $AuthenticationResult.AccessToken) "ExpiresOn" = $AuthenticationResult.ExpiresOn } # Return the authentication token return $Authentication } else { Write-Warning -Message "Failure to acquire access token. Response with access token was null"; break } } catch [System.Exception] { Write-Warning -Message "An error occurred when attempting to call AcquireTokenAsync method. Error message: $($_.Exception.Message)"; break } } catch [System.Exception] { Write-Warning -Message "An error occurred when constructing an authentication token. Error message: $($_.Exception.Message)"; break } } catch [System.Exception] { Write-Warning -Message "Unable to load required assemblies from AzureAD module to construct an authentication token. Error message: $($_.Exception.Message)"; break } } else { Write-Warning -Message "Azure AD PowerShell module is not present on this system, please install before you continue"; break } } catch [System.Exception] { Write-Warning -Message "Unable to load required AzureAD module to for retrieving an authentication token. Error message: $($_.Exception.Message)"; break } } } function Set-MSIntuneAdminConsent { <# .SYNOPSIS Grant admin consent for delegated admin permissions. NOTE: This function requires that AzureAD module is installed. Use 'Install-Module -Name AzureAD' to install it. .PARAMETER TenantName A tenant name should be provided in the following format: tenantname.onmicrosoft.com. .PARAMETER ClientID Specify a Global Admin user principal name. .EXAMPLE # Grant admin consent for delegated admin permissions for an Intune tenant: Set-MSIntuneAdminConsent -TenantName domain.onmicrsoft.com -UserPrincipalName "globaladmin@domain.onmicrosoft.com" .NOTES Author: Nickolaj Andersen Contact: @NickolajA Created: 2018-01-28 Updated: 2018-01-28 Version history: 1.0.0 - (2018-01-28) Function created 1.0.1 - (2018-01-28) Added static prompt behavior parameter with value of Auto #> [CmdletBinding()] param( [parameter(Mandatory=$true, HelpMessage="A tenant name should be provided in the following format: tenantname.onmicrosoft.com.")] [ValidateNotNullOrEmpty()] [string]$TenantName, [parameter(Mandatory=$true, HelpMessage="Specify a Global Admin user principal name.")] [ValidateNotNullOrEmpty()] [string]$UserPrincipalName ) try { # Get installed Azure AD modules $AzureADModules = Get-Module -Name "AzureAD" -ListAvailable -ErrorAction Stop -Verbose:$false if ($AzureADModules -ne $null) { # Check if multiple modules exist and determine the module path for the most current version if (($AzureADModules | Measure-Object).Count -gt 1) { $LatestAzureADModule = ($AzureADModules | Select-Object -Property Version | Sort-Object)[-1] $AzureADModulePath = $AzureADModules | Where-Object { $_.Version -like $LatestAzureADModule.Version } | Select-Object -ExpandProperty ModuleBase } else { $AzureADModulePath = Get-Module -Name "AzureAD" -ListAvailable -ErrorAction Stop -Verbose:$false | Select-Object -ExpandProperty ModuleBase } # Construct array for required assemblies from Azure AD module $Assemblies = @( (Join-Path -Path $AzureADModulePath -ChildPath "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"), (Join-Path -Path $AzureADModulePath -ChildPath "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll") ) Add-Type -Path $Assemblies -ErrorAction Stop try { # Set static variables $Authority = "https://login.microsoftonline.com/$($TenantName)/oauth2/token" $ResourceRecipient = "https://graph.microsoft.com" $RedirectUri = "urn:ietf:wg:oauth:2.0:oob" $ClientID = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" # Default Microsoft Intune PowerShell enterprise application # Construct new authentication context $AuthenticationContext = New-Object -TypeName "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $Authority -ErrorAction Stop # Construct platform parameters $PlatformParams = New-Object -TypeName "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" -ErrorAction Stop # Construct user identifier $UserIdentifier = New-Object -TypeName "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($UserPrincipalName, "OptionalDisplayableId") # Acquire authentication token and invoke admin consent $AuthenticationResult = ($AuthenticationContext.AcquireTokenAsync($ResourceRecipient, $ClientID, $RedirectUri, $PlatformParams, $UserIdentifier, "prompt=admin_consent")).Result # Check if access token was acquired if ($AuthenticationResult.AccessToken -ne $null) { # Construct authentication hash table for holding access token and header information $Authentication = @{ "Content-Type" = "application/json" "Authorization" = -join("Bearer ", $AuthenticationResult.AccessToken) "ExpiresOn" = $AuthenticationResult.ExpiresOn } # Return the authentication token return $Authentication } else { Write-Warning -Message "Failure to acquire access token. Response with access token was null" ; break } } catch [System.Exception] { Write-Warning -Message "An error occurred when constructing an authentication token: $($_.Exception.Message)" ; break } } else { Write-Warning -Message "Azure AD PowerShell module is not present on this system, please install before you continue" ; break } } catch [System.Exception] { Write-Warning -Message "Unable to load required assemblies (Azure AD PowerShell module) to construct an authentication token. Error: $($_.Exception.Message)" ; break } } |