# How to authenticate to Microsoft Graph from Azure DevOps Pipeline using Workload identity federation

With the introduction of the **Workload Identity Federation** feature (currently in preview but functioning well), we can leverage the identity associated with our Pipeline for authentication with Microsoft Graph and other Azure services, eliminating the need for additional Service Principals.

This means we no longer have to deal with the inconvenience of renewing saved secrets 💗.

To get more details about the **Workload Identity Federation** check the official documentation.

---

# Create the Workload Identity Federation Service Connection

In your Azure DevOps project: `Project settings` &gt;&gt; `Service connections` &gt;&gt; `Create service connection` &gt;&gt; `Azure Resource Manager` &gt;&gt; `Workload Identity federation (automatic)`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1711537494345/2128ddc4-73f4-4942-8a07-2d7fcf102f42.png align="left")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1711537664167/b67b0200-6ade-49ff-88c1-c20bb3bb95e0.png align="left")

Now you need to specify to what resource you will grant this newly created identity permissions to.

For this particular use case, I tend to use `Subscription` (`Resource Group`), which means that identity will be granted a `Contributor` role over the selected `Resource Group`.

It is a good idea to have a separate subscription with some dummy `Resource Group` just for this!

<div data-node-type="callout">
<div data-node-type="callout-emoji">💥</div>
<div data-node-type="callout-text">The <code>Contributor</code> role can be substituted with a less privileged role, such as <code>Reader</code>. However, it’s important to remember that workload identity <strong>must be assigned some role</strong>, otherwise all authentication attempts will fail!</div>
</div>

`Service connection name` will be used in the pipeline as an identity identifier later.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1711539087225/514fbf4d-d78b-4920-9a61-83bb594296f6.png align="center")

---

# Grant required Graph permissions to our identity

Now when the identity is created

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1711539631658/003dc238-8490-4791-a32a-c26e7888de5c.png align="left")

We can assign it the required API permissions

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1711539720989/f4e80fd4-96d0-4a52-b3aa-e6c45f926071.png align="left")

As you can see, a new App registration was created in our Azure tenant named as `<DevOps Organization>-<DevOps Project>-<GUID>`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1711539974932/b93b02d9-d0e6-44f5-b0f8-a1387464e42f.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">To grant permissions programmatically, you can use <code>Grant-AzureServicePrincipalPermission</code> (part of the <a target="_blank" rel="noopener noreferrer nofollow" href="https://www.powershellgallery.com/packages/AzureApplicationStuff" style="pointer-events: none"><code>AzureApplicationStuff</code></a> module)</div>
</div>

---

# Authenticate to Microsoft Graph within the Pipeline using the created Workload Identity

Now the last part where we use created workload identity to authenticate against Graph API.

## Getting the access token

To get the access token, add following `AzurePowerShell@5` step to your pipeline.

```yaml
- task: AzurePowerShell@5
        displayName: "Get Graph Token for Workload Federated Credential"
        inputs:
          azureSubscription: "workload_identity_for_graph_api"
          azurePowerShellVersion: "LatestVersion"
          ScriptType: "inlineScript"
          Inline: |
            $accessToken = (Get-AzAccessToken -ResourceTypeName MSGraph -ErrorAction Stop).Token
            Write-Host "##vso[task.setvariable variable=accessToken;issecret=true]$accessToken"
```

Don't forget to change the value of `azureSubscription` to match your `Service connection name` created in the previous step!

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1711541157205/f95c66b1-cb66-4914-bae0-bb976f563e48.png align="center")

This task will get the Graph access token and save it to the pipeline variable `accessToken` for later use.

## Using the access token to authenticate

Now that we have the access token, add the following step to your Pipeline

```yaml
 - task: PowerShell@2
        displayName: "Authenticate"
        inputs:
          targetType: "inline"
          script: |
            Write-Host "Authenticating to Graph API"
            $secureToken = ConvertTo-SecureString -String $(accessToken) -AsPlainText -Force
            Connect-MgGraph -AccessToken $secureToken -NoWelcome
```

This step converts the string from the `accessToken` pipeline variable to the secure string required by the `Connect-MgGraph` command and use it to authenticate.

Happy scripting 😉
