This post will show you how to authenticate for the client credentials flow in PowerShell with MSAL.Net using the .pfx file for the certificate authentication instead of loading the certificate from the certificate store. This post is in part based on this: Using PowerShell to Configure a signing certificate for a SAML-based SSO enterprise application Also, special thanks to my team members Bac Hoang and Will Fiddes for assisting with this sample. I am assuming that you already know the proper steps to create a self signed certificate and also you’re familiar with the client credentials flow. Please note that the public key cer file of the same certificate (of which the private key is used in this post) should be configured on the same app registration. Please refer to this blog post for the requirements.


Methods in this powershell script

  • Load-MSAL – ensures that the proper version of MSAL is installed for the version of PowerShell you’re using.
  • GetX509Certificate_FromPfx – this will return the certificate from the .Pfx file. You will need the full path to the .pfx file and the password for the pfx.
  • Get-GraphAccessTokenFromMSAL – This will Authenticate and retrieve an access token for the graph endpoint.
$ClientID           = "{client_id}"
$loginURL           = ""
$tenantdomain       = "{tenant_id}" 
$CertPassWord       = "{password_for_cert}"
$certPath           = "C:\temp\Certs\testCert_01.pfx"

[string[]] $Scopes  = ""

Function Load-MSAL {
    if ($PSVersionTable.PSVersion.Major -gt 5)
        $core = $true
        $foldername =  "netcoreapp2.1"
        $core = $false
        $foldername = "net45"

    # Download MSAL.Net module to a local folder if it does not exist there
    if ( ! (Get-ChildItem $HOME/MSAL/lib/Microsoft.Identity.Client.* -erroraction ignore) ) {
        install-package -Source -ProviderName nuget -SkipDependencies Microsoft.Identity.Client -Destination $HOME/MSAL/lib -force -forcebootstrap | out-null
    # Load the MSAL assembly -- needed once per PowerShell session
    [System.Reflection.Assembly]::LoadFrom((Get-ChildItem $HOME/MSAL/lib/Microsoft.Identity.Client.*/lib/$foldername/Microsoft.Identity.Client.dll).fullname) | out-null
Function Get-GraphAccessTokenFromMSAL {


    $global:app = $null

    $x509cert = [System.Security.Cryptography.X509Certificates.X509Certificate2] (GetX509Certificate_FromPfx -CertificatePath $certPath -CertificatePassword $CertPassWord)
    write-host "Cert = {$x509cert}"

    $ClientApplicationBuilder = [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder]::Create($ClientID)
    $global:app = $ClientApplicationBuilder.Build()

    [Microsoft.Identity.Client.AuthenticationResult] $authResult  = $null
    $AquireTokenParameters = $global:app.AcquireTokenForClient($Scopes)
    try {
        $authResult = $AquireTokenParameters.ExecuteAsync().GetAwaiter().GetResult()
    catch {
        $ErrorMessage = $_.Exception.Message
        Write-Host $ErrorMessage
    return $authResult

function GetX509Certificate_FromPfx($CertificatePath, $CertificatePassword){
    #write-host "Path: '$CertificatePath'"
        $LocalPath = Get-Location
        $CertificatePath = "$LocalPath\$CertificatePath"

    #Write-Host "Looking for '$CertificatePath'"

    $certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($CertificatePath, $CertificatePassword)
    Return $certificate

$myvar = Get-GraphAccessTokenFromMSAL
Write-Host "Access Token: " $myvar.AccessToken


Loading the certificate from a .pfx file in PowerShell can make it easier for an admin to manage certificates without having to install the certificate in the certificate store. However, this should not be done on a client machine as the user could potentially discover the file and also the password for it, as well as the method to authenticate. The client credentials flow is only intended to be ran in a back-end service to service type of scenario where only admins have access to the machine.

4 1 vote
Article Rating
Notify of

Newest Most Voted
Inline Feedbacks
View all comments
andrew stevens
andrew stevens
November 19, 2020 8:42 pm

Thanks for this, really helpful, keep up the good work!

Bac Hoang [MSFT]
November 24, 2020 11:22 pm
Reply to  andrew stevens

Glad to hear it’s helpful.

July 8, 2021 10:03 pm

Quick question tough, would that work on a Linux devops agent ?
I have an error with the Install-Package

vivek mishra
vivek mishra
November 30, 2021 9:02 pm

Thanks for the post. Quick question, my PFX file doesn’t have password. I downloaded it from keyvault (both cer and pfx) which doesn’t gives the password for PFX.
Can I use this solution without a password for PFX file.