iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🍙

Authentication and Authorization for Calling Azure Web Apps APIs from Azure Functions (Python)

に公開
2022/01/17

When people use web apps, they usually enter an ID and password for authentication.
(There are also one-time passwords and biometric authentication, but let's set those aside for now.)

Then, how should authentication be handled when Azure Functions, which is event-driven and functions without human intervention, uses an app?
One method is to have it enter an ID and password like a human, but that would require storing the password in Azure Functions, which is not ideal for security.
Furthermore, Azure AD has a frustrating specification that forces passwords to be changed periodically.
Under this approach, you would need to update the password settings regularly, which is very tedious.

So, let's consider a better way.

What I want to do

  • Call an API built on Azure Web Apps from Azure Functions (Python)
    • Assume Azure Web Apps has already been configured with Easy Auth for authentication and authorization.
  • Instead of entering an Azure AD user ID or password within Azure Functions, I want to grant execution permission to the Function itself based on roles.

Reference Documents

https://docs.microsoft.com/en-us/azure/developer/python/azure-sdk-authenticate

Code to obtain credentials and call the API in Azure Functions

The processing required in Azure Functions is as follows:

  • Authenticate using DefaultAzureCredential()
  • Obtain an AccessToken
  • Call the API with the AccessToken in the Authorization header
import requests
from azure.core.credentials import AccessToken
from azure.identity import DefaultAzureCredential

# Obtain the token
credential = DefaultAzureCredential()
scope = "https://(web-apps-name).azurewebsites.net/.default"
token: AccessToken = credential.get_token(scope)

# API call (Update parameters other than Authorization as needed)
headers["Authorization"] = "Bearer " + token.token
requests.get("https://(web-apps-name).azurewebsites.net/api/hello_world", headers=headers)

Note: About the convenient class DefaultAzureCredential

In the source code above, I used DefaultAzureCredential.
Since our goal is to authenticate with a managed identity, it might seem appropriate to use ManagedIdentityCredential, and it does indeed work fine on Azure. However, ManagedIdentityCredential does not work in a local environment, so you would need to deploy to Azure every time you want to verify the operation.
On the other hand, if you use DefaultAzureCredential, it will authenticate using a managed identity when running on Azure, and it will authenticate using local credentials (the information from az login) when running in a local environment.
In other words, by writing your authentication using this class, you can easily achieve this during testing in a local environment.
I will not cover how to set up the local environment in this article, so please refer to the following document:
https://docs.microsoft.com/en-us/azure/developer/python/configure-local-development-environment?tabs=cmd

Discussion