1

I've got two functions (let's call them A and B) in an Azure function app (environment: Python); both are HTTP triggered function. Function A calls function B to receive a token from an external 3rd party API endpoint. Microsoft authentication is turned on for the function app. So, function A calls B with Microsoft client credentials. The function app is developed in VScode and deployed through the Azure plugin in the cloud. This is where function A gets stuck, waiting for a response from B. But B never executes. I've tried the following:

  • Call B from a local notebook with the same client credentials while B is deployed. Works as intended; B sends out token from the cloud.
  • Execute function A locally, calling B from cloud. Works as intended; B sends out token from the cloud.
  • Trigger function B from browser. works as intended; B sends out a token that I can see from the browser.

Its only when A executes in cloud when it can't get a response from B and times out.

The client credential script I'm using:

# Dedicated Graph Access App
client_secret = 'secret'
client_id = 'client_id'

token_url = 'https://login.microsoftonline.com/<tenant_id>/v2.0/token?'
token_data = {"client_id":client_id,
            "client_secret":client_secret,
            "scope":"<client_id>/.default",
            "grant_type":"client_credentials"
            }
token_r = requests.post(token_url, data=token_data)
token = token_r.json().get('access_token')

headers = {
    'Authorization':"Bearer "+token,
    'ConsistencyLevel':'eventual'
}

Function B is called via:

accessTokenUrl = "https://appname.azurewebsites.net/api/functionName?code=<function_code>"
access_token = requests.get(accessTokenUrl, headers = headers).content.decode()

Which works when I call function B from local notebook. I know function A gets stuck waiting for B to respond because I've checked logs for B, it never executes as if never got triggered by A. And I've put some debugging messages in A which lets me know that A got up to B execution and then it timed out.

I'm at a complete loss of why this happens. Is there a specific way to call one function from another function in Azure apps? Why can't A get response from B when B executes fine by itself?

I've tried the following:

  • Call B from a local notebook with the same client credentials while B is deployed. Works as intended; B sends out token from the cloud.
  • Execute function A locally, calling B from cloud. Works as intended; B sends out token from the cloud.
  • Trigger function B from browser. works as intended; B sends out a token that I can see from the browser.
5
  • Can you please share codes for both function A and function B? You want to call function B from function A in cloud? Commented Feb 16, 2024 at 5:26
  • Yes, both functions are part of an Azure function app. I've shared the relevant part of function A. Function B is literally just sending a token back and is not the issue, because it executes fine by itself. Commented Feb 16, 2024 at 5:31
  • Can you share the codes separately for function A and function B, so that it will be easy to help you better Commented Feb 16, 2024 at 5:37
  • Its a V1 or V2 model? Commented Feb 16, 2024 at 5:47
  • its a serverless function app. the relevant codes are in the post. Commented Feb 16, 2024 at 6:01

1 Answer 1

0

I have created two Http triggered python V2 model functions (function_A and function_B). I am using the below code to get the token in function_A by calling function_B.

My folder structure looks like below-

enter image description here

I have the following codes in the below mentioned files.

function_app.py-

import azure.functions as func
import logging
import requests

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="function_A")
def function_A(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    function_b_response = requests.get("https://{functionApp_Name}.azurewebsites.net/api/function_b")
    token = function_b_response.text.strip()
    
    return func.HttpResponse(
        f"Bearer token from function B: {token}",
        status_code=200
    )

@app.route(route="function_B", auth_level=func.AuthLevel.ANONYMOUS)
def function_B(req: func.HttpRequest) -> func.HttpResponse:
    tenant_id = '{tenant_id}'
    client_id = '{client_id}'
    client_secret = '{client_secret}'

    token_url = f'https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token'
    token_data = {
            "client_id":client_id,
            "client_secret":client_secret,
            "scope":"{client_id}/.default",
            "grant_type":"client_credentials"
            }
    token_r = requests.post(token_url, data=token_data)
    token = token_r.json().get('access_token') 

    return func.HttpResponse(
        f"{token}",
        status_code=200
    )

requirements.txt-

azure-functions
requests

When I execute the code locally, I am able to get the token as shown below-

enter image description here

enter image description here

I deployed the functions to function app using vs code and got successfully deployed response.

enter image description here

I can see the functions in portal.

enter image description here

I can get the token upon invoking function_A in portal.

enter image description here

enter image description here

Use my code, you will get the output too.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the effort, however this is not what I was looking for (your example does not have the authentication, functions are anonymous access). Azure's function app with authentication seems to have some issues communicating between functions. I ended up splitting the two functions in two different function apps and it worked then.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.