passing authentication token from 1 HTTP triggered function to another

Parag Kale 20 Reputation points
2025-05-09T14:58:59.78+00:00

Hi

I am using durable functions monitor in injected mode and not using the inbuilt authentication provided in function app. Rather I am generating auth code and auth token using Microsoft identity platform auth code flow.

I have below function that when accessed presents the sign in screen

[Function("Function1")]

public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)

{

string tenant = "tenantId"; // or use your tenant ID

string clientId = "clientId";

// Ensure this redirect URI matches what is in your app registration

string redirectUri = "http://localhost:7267/api/Function2";

// Define the scopes you need (openid, profile, offline_access, etc.)

string scope = "openid profile email";

string authUrl = $"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize" +

$"?client_id={clientId}" +

$"&response_type=code" +

$"&redirect_uri={WebUtility.UrlEncode(redirectUri)}" +

$"&response_mode=query" +

$"&scope={WebUtility.UrlEncode(scope)}" +

$"&state=12345&prompt=login"; // ideally, generate a dynamic state value

var response = req.CreateResponse(HttpStatusCode.Redirect);

response.Headers.Add("Location", authUrl);

return response;

}

This redirects me to Function2 where I get the auth token as below

[Function("Function2")]

public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)

{

string code = req.Query["code"]!;

string tenant = "tenantId"; // or your tenant-specific ID

string clientId = "clientId";

string clientSecret = "secret";

string redirectUri = "http://localhost:7267/api/Function2";

// Build the MSAL confidential client application

IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(clientId)

.WithClientSecret(clientSecret)

.WithRedirectUri(redirectUri)

.WithAuthority($"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token")

.Build();

AuthenticationResult result = app.AcquireTokenByAuthorizationCode(

new string[] { "openid", "profile", "email" }, code)

.ExecuteAsync().Result;

if (result.AccessToken != null)

{

var response = req.CreateResponse(HttpStatusCode.Redirect);

response.Headers.Add("Location", "http://localhost:7267/api/DFM");

response.Headers.Add("Authorization", result.AccessToken);

return response;

}

else

{

return req.CreateResponse(HttpStatusCode.BadRequest);

}

}

The endpoint http://localhost:7267/api/DFM is my custom endpoint for the durable function monitor in injected mode

[Function(nameof(MyCustomDfMonEndpoint))]

public Task<HttpResponseData> ServeDfMonStatics(

[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = Globals.DfMonRoutePrefix + "/{p1?}/{p2?}/{p3?}")] HttpRequestData req,

string p1,

string p2,

string p3

)

{

if (!req.Headers.TryGetValues("Authorization", out var authHeaders))

{

var unauthorizedResponse = req.CreateResponse(HttpStatusCode.Unauthorized);

unauthorizedResponse.WriteStringAsync("Missing Authorization header.");

return Task.FromResult(unauthorizedResponse);

}

return this.DfmServeStaticsFunction(req, p1, p2, p3);

}

Currently what I am seeing is the endpoint for DFM doesn't get the token in headers passed from Function2 using response.Headers.Add("Authorization", result.AccessToken);

What I am looking for is getting the token in the headers when it is redirected from Function2 and maintaining that token when the links on the durable function monitor are hit. so that the below check always prevents unauthorized access

if (!req.Headers.TryGetValues("Authorization", out var authHeaders))

{

var unauthorizedResponse = req.CreateResponse(HttpStatusCode.Unauthorized);

unauthorizedResponse.WriteStringAsync("Missing Authorization header.");

return Task.FromResult(unauthorizedResponse);

}

Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
5,745 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.