Functions/Get-AGGraphAccessTokenFromAz.ps1
|
Function Get-AGGraphAccessTokenFromAz { <# .SYNOPSIS Gets the bearer token needed for Graph REST API calls using Az module authentication. .DESCRIPTION Gets the bearer token needed for Graph REST API calls using the currently logged in Azure context from the Az module. This eliminates the need for TenantID, ClientID, and ClientSecret. .EXAMPLE $Token = Get-AGGraphAccessTokenFromAz This example gets a token using the current Az context and stores it in a variable. .EXAMPLE $Token = Get-AGGraphAccessTokenFromAz Get-AGGroups -AccessToken $Token -DisplayNameStartsWith Az-Cont This example gets a token and then uses it to retrieve groups. .PARAMETER ResourceUrl The resource URL for which to get an access token. Defaults to "https://graph.microsoft.com". .INPUTS None. You cannot pipe input to this function. .OUTPUTS A token response object compatible with the other AG* functions in this module. .NOTES Author: Lars Panzerbjørn Creation Date: 2026.08.27 Requires the Az.Accounts module to be installed and an active Az login context. The returned token is also stored in module scope for use by other functions in this module. #> [CmdletBinding(PositionalBinding=$False)] param( [Parameter()][string]$ResourceUrl = "https://graph.microsoft.com" ) BEGIN{ # Check if Az module is available if (-not (Get-Module -ListAvailable -Name Az.Accounts)) { throw "Az.Accounts module is not installed. Please install it using: Install-Module -Name Az.Accounts" } # Check if we're logged in try { $null = Get-AzContext -ErrorAction Stop } catch { throw "Not logged into Azure. Please run Connect-AzAccount first." } } PROCESS{ try { # Get the token from Az module $AzToken = Get-AzAccessToken -ResourceUrl $ResourceUrl -ErrorAction Stop # The token might be in different formats depending on Az module version # Extract the actual token string if ($AzToken.Token -is [SecureString]) { # Convert SecureString to plain text $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($AzToken.Token) $TokenString = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR) } else { # It's already a string $TokenString = $AzToken.Token.ToString() } # Calculate expiration time if ($AzToken.ExpiresOn) { $ExpiresOn = $AzToken.ExpiresOn if ($ExpiresOn -is [DateTime]) { $ExpiresOnDateTime = $ExpiresOn } else { # Try to parse it $ExpiresOnDateTime = [DateTime]::Parse($ExpiresOn.ToString()) } } else { # Default to 1 hour if we can't determine $ExpiresOnDateTime = (Get-Date).AddHours(1) } # Create a token object compatible with existing AG* functions $TokenResponse = [PSCustomObject]@{ access_token = $TokenString token_type = "Bearer" expires_in = ($ExpiresOnDateTime.ToUniversalTime() - (Get-Date).ToUniversalTime()).TotalSeconds expires_on = [DateTimeOffset]::Parse($ExpiresOnDateTime.ToString()).ToUnixTimeSeconds() not_before = [DateTimeOffset]::Now.ToUnixTimeSeconds() resource = $ResourceUrl } # Add the ExpiresOn property with the correct date format (matching your original function) $TokenResponse | Add-Member -MemberType NoteProperty -Name "ExpiresOn" -Value $ExpiresOnDateTime # Store in script scope for other functions to use $Script:TenantID = (Get-AzContext).Tenant.Id $Script:BaseUri = $ResourceUrl $Script:TokenResponse = $TokenResponse $Script:Headers = @{Authorization = "Bearer $TokenString"} Write-Verbose "Successfully acquired Graph access token. Expires at: $($ExpiresOnDateTime.ToString('yyyy-MM-dd HH:mm:ss'))" Write-Verbose "Token starts with: $($TokenString.Substring(0, [Math]::Min(20, $TokenString.Length)))..." } catch { throw "Failed to acquire access token: $_" } } END{ Return $TokenResponse } } |