Edit

Share via


Authenticate C++ apps to Azure services during local development using developer accounts

During local development, applications need to authenticate to Azure to use different Azure services. Authenticate locally using one of these approaches:

This article explains how to authenticate using a developer account with tools supported by the Azure Identity library. In the sections ahead, you learn:

  • How to use Microsoft Entra groups to efficiently manage permissions for multiple developer accounts.
  • How to assign roles to developer accounts to scope permissions.
  • How to sign-in to supported local development tools.
  • How to authenticate using a developer account from your app code.

Supported developer tools for authentication

For an app to authenticate to Azure during local development using the developer's Azure credentials, the developer must be signed-in to Azure using Azure CLI.

The Azure Identity library can detect that the developer is signed-in from the tool. The library can then obtain the Microsoft Entra access token via the tool to authenticate the app to Azure as the signed-in user.

This approach takes advantage of the developer's existing Azure accounts to streamline the authentication process. However, a developer's account likely has more permissions than required by the app, therefore exceeding the permissions the app runs with in production. As an alternative, you can create application service principals to use during local development, which can be scoped to have only the access needed by the app.

Create a Microsoft Entra group for local development

Create a Microsoft Entra group to encapsulate the roles (permissions) the app needs in local development rather than assigning the roles to individual service principal objects. This approach offers the following advantages:

  • Every developer has the same roles assigned at the group level.
  • If a new role is needed for the app, it only needs to be added to the group for the app.
  • If a new developer joins the team, a new application service principal is created for the developer and added to the group, ensuring the developer has the right permissions to work on the app.
  1. Navigate to the Microsoft Entra ID overview page in the Azure portal.

  2. Select All groups from the left-hand menu.

  3. On the Groups page, select New group.

  4. On the New group page, fill out the following form fields:

    • Group type: Select Security.
    • Group name: Enter a name for the group that includes a reference to the app or environment name.
    • Group description: Enter a description that explains the purpose of the group.

    A screenshot showing how to create a group in the Azure portal.

  5. Select the No members selected link under Members to add members to the group.

  6. In the flyout panel that opens, search for the service principal you created earlier and select it from the filtered results. Choose the Select button at the bottom of the panel to confirm your selection.

  7. Select Create at the bottom of the New group page to create the group and return to the All groups page. If you don't see the new group listed, wait a moment and refresh the page.

Assign roles to the group

Next, determine what roles (permissions) your app needs on what resources and assign those roles to the Microsoft Entra group you created. Groups can be assigned a role at the resource, resource group, or subscription scope. This example shows how to assign roles at the resource group scope, since most apps group all their Azure resources into a single resource group.

  1. In the Azure portal, navigate to the Overview page of the resource group that contains your app.

  2. Select Access control (IAM) from the left navigation.

  3. On the Access control (IAM) page, select + Add and then choose Add role assignment from the drop-down menu. The Add role assignment page provides several tabs to configure and assign roles.

  4. On the Role tab, use the search box to locate the role you want to assign. Select the role, and then choose Next.

  5. On the Members tab:

    • For the Assign access to value, select User, group, or service principal .
    • For the Members value, choose + Select members to open the Select members flyout panel.
    • Search for the Microsoft Entra group you created earlier and select it from the filtered results. Choose Select to select the group and close the flyout panel.
    • Select Review + assign at the bottom of the Members tab.

    A screenshot showing how to assign a role to the Microsoft Entra group.

  6. On the Review + assign tab, select Review + assign at the bottom of the page.

Sign-in to Azure using developer tooling

Sign-in to Azure using one of several developer tools that can be used to perform authentication in your development environment. The account you authenticate should also exist in the Microsoft Entra group you created and configured earlier.

Azure CLI

Developers can use Azure CLI to authenticate. Apps using DefaultAzureCredential or AzureCliCredential can then use this account to authenticate app requests.

To authenticate with the Azure CLI, run the az login command. On a system with a default web browser, the Azure CLI launches the browser to authenticate the user.

az login

For systems without a default web browser, the az login command uses the device code authentication flow. The user can also force the Azure CLI to use the device code flow rather than launching a browser by specifying the --use-device-code argument.

az login --use-device-code

Authenticate to Azure services from your app

The Azure Identity library for C++ provides various credentials adapted to supporting different scenarios and Microsoft Entra authentication flows. The steps ahead demonstrate how to use DefaultAzureCredential when working with user accounts locally.

Implement the code

The DefaultAzureCredential class is an ordered sequence of mechanisms for authenticating to Microsoft Entra ID. Each authentication mechanism is a class derived from the TokenCredential class and is known as a credential. In this scenario, DefaultAzureCredential sequentially checks to see if the developer has signed-in to Azure using the Azure CLI. If the developer is signed-in to Azure CLI, then the credentials used to sign into the tool is used by the app to authenticate to Azure. For more information about customizing the credential chain, see How to customize DefaultAzureCredential.

  1. Add the azure-identity-cpp package to your application using vcpkg.

    vcpkg add port azure-identity-cpp
    
  2. Add the following lines in your CMake file:

    find_package(azure-identity-cpp CONFIG REQUIRED)
    target_link_libraries(<your project name> PRIVATE Azure::azure-identity)
    
  3. For any C++ code that creates an Azure SDK client object in your app, you want to:

    1. Include the azure/identity.hpp header.

    2. Use DefaultAzureCredential or AzureCliCredential to create an instance of a credential. For example:

      • To use DefaultAzureCredential, set the environment variable AZURE_TOKEN_CREDENTIALS to dev that indicates the app is running in a development environment. For more information, see How to customize DefaultAzureCredential.

        // Environment variable AZURE_TOKEN_CREDENTIALS=dev
        auto credential = std::make_shared<Azure::Identity::DefaultAzureCredential>(true);
        
      • Or use AzureCliCredential to always use the Azure CLI signed-in user to authenticate.

        auto credential = std::make_shared<Azure::Identity::AzureCliCredential>();
        
    3. Pass the instance of DefaultAzureCredential or AzureCliCredential to the Azure SDK client constructor.

    An example of these steps is shown in the following code segment. The example creates an Azure Storage Blob client using DefaultAzureCredential to authenticate to Azure.

    #include <azure/identity.hpp>
    #include <azure/storage/blobs.hpp>
    #include <iostream>
    #include <memory>
    
    int main() {
        try {
            // DefaultAzureCredential supports dev, test, and prod environments.
            // See documentation for details on customizing the credential chain:
            // https://learn.microsoft.com/azure/developer/cpp/sdk/authentication/credential-chains#defaultazurecredential-overview
            // In production, it's better to use a specific credential type so authentication is more predictable and easier to debug.
            // Here DefaultAzureCredential is used for local development and environment variable AZURE_TOKEN_CREDENTIALS=dev
    
            auto credential = std::make_shared<Azure::Identity::DefaultAzureCredential>(true);
    
            // Or use AzureCliCredential to always use the Azure CLI signed-in user to authenticate
            // auto credential = std::make_shared<Azure::Identity::AzureCliCredential>();
    
            // Create a client for the specified storage account
            std::string accountUrl = "https://<replace_with_your_storage_account_name>.blob.core.windows.net/";
            Azure::Storage::Blobs::BlobServiceClient blobServiceClient(accountUrl, credential);
    
            // Get a reference to a container
            std::string containerName = "sample-container";
            auto containerClient = blobServiceClient.GetBlobContainerClient(containerName);
    
            // TODO: perform some action with the blob client
            // auto blobClient = containerClient.GetBlobClient("sample-blob");
            // auto downloadResult = blobClient.DownloadTo("path/to/local/file");
    
        } catch (const std::exception& ex) {
            std::cout << "Exception: " << ex.what() << std::endl;
            return 1;
        }
    
        return 0;
    }