Public/Add-EntraIDClientCertificateAccessTokenProfile.ps1
<# .SYNOPSIS Adds a new profile for getting Entra ID access tokens. .EXAMPLE Add-EntraIDAccessTokenProfile #> function Add-EntraIDClientCertificateAccessTokenProfile { [CmdletBinding(DefaultParameterSetName = "x509certificate2")] Param ( [Parameter(Mandatory = $false)] [String] $Name = "Default", [Parameter(Mandatory = $false)] [String] $Resource = "https://graph.microsoft.com", [Parameter(Mandatory = $false)] [String] $Scope, [Parameter(Mandatory = $true, ParameterSetName = "x509certificate2")] [System.Security.Cryptography.X509Certificates.X509Certificate2] $Certificate, [Parameter(Mandatory = $true, ParameterSetName = "thumbprint")] [String] $Thumbprint, [Parameter(Mandatory = $true, ParameterSetName = "pfx")] [String] $Path, [Parameter(Mandatory = $true, ParameterSetName = "pfx")] [SecureString] $Password, [Parameter(Mandatory = $true)] [ValidatePattern("^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$")] [String] $ClientId, [Parameter(Mandatory = $true)] [ValidatePattern("^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$")] [String] $TenantId, [Parameter(Mandatory = $false)] [ValidateSet("v1", "v2")] [String] $TokenVersion = "v1" ) Process { if ($Script:Profiles.ContainsKey($Name)) { Write-Warning "Profile $Name already exists, overwriting" } if($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('TokenVersion')) { Write-Warning "TokenVersion is not currently being used" } if($PSCmdlet.MyInvocation.BoundParameters['Resource'] -and $PSCmdlet.MyInvocation.BoundParameters['Scope']) { throw "Cannot specify both Resource and Scope" } $Certificate = $null; if ($PSCmdlet.ParameterSetName -eq "x509certificate2") { } elseif ($PSCmdlet.ParameterSetName -eq "thumbprint") { $localmachine = Get-ChildItem Cert:\LocalMachine\My | Where-Object ThumbPrint -eq $Thumbprint | Select-Object -First 1 $currentuser = Get-ChildItem Cert:\CurrentUser\My | Where-Object ThumbPrint -eq $Thumbprint | Select-Object -First 1 if ($localmachine) { $Certificate = $localmachine } elseif ($currentuser) { $Certificate = $currentuser } else { throw "Certificate with thumbprint $Thumbprint not found" } } elseif ($PSCmdlet.ParameterSetName -eq "pfx") { if (!(Test-Path $Path)) { throw "Path $Path does not exist" } $Certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($Path, $Password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::UserKeySet) } if (!$Certificate) { throw "Certificate not found" } if (!$Certificate.HasPrivateKey) { throw "Certificate $($Certificate.Thumbprint) does not have a private key" } Write-Verbose "Certificate thumbprint: $($Certificate.Thumbprint)" Write-Verbose "Certificate subject: $($Certificate.Subject)" Write-Verbose "Certificate not valid after: $($Certificate.NotAfter)" Write-Verbose "Certificate not valid before: $($Certificate.NotBefore)" $Script:Profiles[$Name] = @{ AuthenticationMethod = "clientcertificate" ClientId = $ClientId Resource = $Scope ? $null : $Resource Scope = $Scope TenantId = $TenantId Certificate = $Certificate ThumbPrint = $Certificate.Thumbprint # V2Token = $TokenVersion -eq "v2" } Get-EntraIDAccessToken -Profile $Name | Out-Null } } |