Skip to content
Carmel Eve By Carmel Eve Software Engineer I
Secure Azure Function-to-Function authentication without the need for credentials

Here at endjin we spend a lot of time working with data, and securing that data is top on our list of priorities . Therefore, anything we can do to reduce the need for storing access keys is a huge win! (Here is a guest blog from Barry Smart at Hymans Robertson which details our Swiss Cheese Model around security and compliance.)

In Azure, many services now have the ability to authenticate via a Managed Identity. This is essentially a service principal specific to that service, which you can then give access to various other resources. The applications can attempt to access resources using their associated identity, without the need for any kind of password or key.

Azure Weekly is a summary of the week's top Microsoft Azure news from AI to Availability Zones. Keep on top of all the latest Azure developments!

These managed identities can then be given access to necessary resources. For example, they can be granted roles and added to access control lists in ADLS Gen2 accounts, or the ability to access keys in key vault. This means that data can be securely accessed without needing to store connection strings or app passwords.

Specifically though, in this post I'm going to outline how to give a function the ability to call into another function without needing to store the function keys.

The process

Say we have one function (lets call it the AutoTriggerFunction) which is on a timer trigger, and as part of the triggered process it needs to call out into another function to do part of the work.  However, we don't want just anyone to be able to call into this second function, only those who have been given access (lets call this second function the ExclusiveFunction). The ExclusiveFunction will be HTTP triggered, but we need to be able to prove that the incoming request came from the AutoTriggerFunction as expected.

We can do that in a few steps:

  1. Enable a system provided identity on the AutoTriggerFunction.

This sets up an identity for the AutoTriggerFunction, which means that it can authenticate as itself in order to make requests. Practically, this means that it will then have an AAD managed identity associated with it, which it can then use to access resources.

  1. Enable easy auth on the ExclusiveFunction

Enabling easy auth means that when requests come in to the ExclusiveFunction, they must carry an authorisation header which has been validated against the function's authorisation service in order to be let through to the actual HTTP endpoint. This way, requests from services which have not been registered with the application will not be allowed to trigger the ExclusiveFunction.

To set up easy auth you go into the authorization section of the platform features, and turn on authentication via AAD. You then either set up a new, or select an existing, AAD application which will be used to control the authentication. Users can then be registered with this AAD application, which will allow them to retrieve valid auth tokens.

  1. Adding the managed identity as a user of the AAD application

We then need to register the managed identity for the AutoTriggerFunction with the AAD application which is managing the authentication for the ExclusiveFunction. Once the managed identity has been registered, valid auth tokens can be retrieved by the AutoTriggerFunction's identity and used to make authenticated HTTP requests to the client.

  1. Retrieve an access token from AAD

The AutoTriggerFunction can then request an access token from AAD for the ExclusiveFunction's authentication AAD application. Inside the calling AutoTriggerFunction's code this can be done using:

Where AzureServiceTokenProvider is part of the Microsoft.Azure.Services.AppAuthentication NuGet package. Here I'm just retrieving a single access token, these will be valid for a certain amount of time (usually an hour), which means if you have long running operations the access token could expire before the work is complete. To deal with this it is better to use an ITokenProvider, but I won't get into that here.

If the function has identity enabled, when you set the AzureServicesAuthConnectionString app setting to an empty string, it will automatically authenticate using its own managed identity. (Alternatively, you can use this setting to connect via a service principal, but that's a topic for another post). The AAD client ID variable here will be the ID of the AAD application you have used to secure the ExclusiveFunction.

You then use the bearer token returned to hit the endpoint for the ExclusiveFunction.

  1. Make sure that the authorization level of the HTTP endpoint is set to anonymous.

When you set up an HTTP trigger, the Run method looks like this:

public static class ExclusiveFunction
{
    [FunctionName("Function1")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req, ILogger log)
    {
      ...
    }
}
The best hour you can spend to refine your own data strategy and leverage the latest capabilities on Azure to accelerate your road map.

Here the AuthorizationLevel can be set to Anonymous, Function, System, Admin or User. You might think (I know I did) that because the AutoTriggerFunction is authenticating via an identity, you would need an authorization level of user. However, this feature currently isn't fully implemented, it may work in future but for now we need to use Anonymous authorization level.

Luckily, when using easy auth, all authentication is done at the level of the functions application and the request will only be allowed to make it through to the trigger endpoint if it has come from a user which is registered with the AAD application used for authorization. Therefore, at the level of the function HTTP endpoint, the authorization can be set to anonymous as the security checks have already been carried out.

And with that the AutoTriggerFunction can now securely access the ExclusiveFunction, purely using its own managed identity, and without the need for it to store the ExclusiveFunction's keys!

Doodle of two functions shaking hands.

Carmel Eve

Software Engineer I

Carmel Eve

Carmel is a software engineer and LinkedIn Learning instructor. She worked at endjin from 2016 to 2021, focused on delivering cloud-first solutions to a variety of problems. These included highly performant serverless architectures, web applications, reporting and insight pipelines, and data analytics engines. After a three-year career break spent travelling around the world, she rejoined endjin in 2024.

Carmel has written many blog posts covering a huge range of topics, including deconstructing Rx operators, agile estimation and planning and mental well-being and managing remote working.

Carmel has released two courses on LinkedIn Learning - one on the Az-204 exam (developing solutions for Microsoft Azure) and one on Azure Data Lake. She has also spoken at NDC, APISpecs, and SQLBits, covering a range of topics from reactive big-data processing to secure Azure architectures.

She is passionate about diversity and inclusivity in tech. She spent two years as a STEM ambassador in her local community and taking part in a local mentorship scheme. Through this work she hopes to be a part of positive change in the industry.

Carmel won "Apprentice Engineer of the Year" at the Computing Rising Star Awards 2019.