Dec 8, 2020 2 min read

Simplified app-only authentication with CLI for Microsoft 365, in Azure DevOps

The new (upcoming) release of CLI for Microsoft 365 makes it easier to work with certificates, making the steps in Azure DevOps for secure unattended authentication much simpler.

Simplified app-only authentication with CLI for Microsoft 365, in Azure DevOps

In my previous post I attempted app-only authentication in an Azure DevOps pipeline, by means of PnP.PowerShell and CLI for Microsoft 365. As it turned out, this was easier with PnP.PowerShell. I ended the post with some suggestions for CLI and posted them as suggestions on their GitHub issues list too. The CLI core team and I worked over the past 1.5 week to get them implemented, and today they got merged into the master branch for what will be the next version (3.4.0).
This means that your Azure DevOps actions that use CLI for Microsoft 365 in an unauthenticated manner, can be simplified by a lot!

In the original post I provided this snippet:

- task: NodeTool@0
  inputs:
    versionSpec: '12.x'
- task: PowerShell@2
  inputs:
    targetType: 'inline'
    script: |
      $location = Get-Location
      $certStringBase64 = "$(YannicksDevOpsPipeline)"
      $certByteArray = [System.Convert]::FromBase64String($certStringBase64)

      [System.IO.File]::WriteAllBytes("$location/certificate.pfx", $certByteArray)
      $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]($certByteArray)
      $certThumbprint = $cert.Thumbprint
      $cert.Dispose()
      $cert = $null
      
      openssl pkcs12 -in "$location/certificate.pfx" -out "$location/certificate.pem" -nodes -passin pass:

      npm i -g @pnp/cli-microsoft365
      $env:CLIMICROSOFT365_AADAPPID = "e5c08ad8-xxxx-xxxx-b429-a266c94bc638"
      $env:CLIMICROSOFT365_TENANT = "b868e8f4-xxxx-xxxx-8c95-7f432eba848b"
      m365 login --authType certificate --certificateFile "$location/certificate.pem" --thumbprint $certThumbprint
      m365 spo web get --webUrl https://contoso.sharepoint.com/sites/crisismanagement
      m365 logout

      Remove-Item "$location/certificate.pfx"
      Remove-Item "$location/certificate.pem"
    pwsh: true

With the release of version 3.4.0 of CLI for Microsoft 365, the resulting task can be as simple as the following:

- task: NodeTool@0
  inputs:
    versionSpec: '12.x'
- task: PowerShell@2
  displayName: "Run M365 CLI with improvements"
  inputs:
    targetType: 'inline'
    script: |
      npm i -g @pnp/cli-microsoft365@next
      m365 login --authType certificate --certificateBase64Encoded "$(YannicksDevOpsPipeline)" --appId e5c08ad8-xxxx-xxxx-b429-a266c94bc638 --tenant b868e8f4-xxxx-xxxx-8c95-7f432eba848b
      m365 spo web get --webUrl https://contoso.sharepoint.com/sites/crisismanagement
      m365 logout
    pwsh: true
Version 3.4.0 is in beta at the time of writing, this is the reason why I use the @next tag to install this through npm. As soon as 3.4.0 has it's official release, you better use the GA version.

CLI for Microsoft 365 now supports:

  • passing in appId and tenant as options to the login command, so no more awkward environment variables
  • calculating the certificate thumbprint, so no need anymore to pass in the thumbprint yourself
  • taking the base64 encoded version of your certificate, so no more converting the Azure Key Vault value to a file on disk
  • working with certificates that have empty or undefined passwords (like those that get loaded from an Azure Key Vault)

This also means you don't necessarily need to use PowerShell Core task, but you can also the bash task (or any other command prompt task) in Azure DevOps.

Happy releasing!

Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Yannick Reekmans.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.