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,768 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Khadeer Ali 5,065 Reputation points Microsoft External Staff Moderator
    2025-05-12T12:31:34.6866667+00:00

    @Parag Kale

    Use an HTTP-only cookie to store the token after it is first received. This way, the token gets automatically sent with every request by the browser — including JS, CSS, and static resource fetches from DFM.


    Pseudo Code (Logical Flow)

    
    
    FUNCTION ServeDfMonStatics(request):
        IF access_token IS IN QUERY PARAMS:
            // first request after login, store token in cookie
            SET COOKIE "access_token" with value from query
            REDIRECT to same endpoint WITHOUT token in query (clean URL)
    
        ELSE IF access_token IS IN COOKIE:
            // All future requests will have token from cookie
            PROCEED to serve DFM static content
    
        ELSE:
            // First time, no token yet — redirect to login
            REDIRECT to Azure login page with proper redirect_uri
    

    Actual Code (C# Azure Function)

    
    
    [Function(nameof(MyCustomDfMonEndpoint))]
    public async Task<HttpResponseData> ServeDfMonStatics(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = Globals.DfMonRoutePrefix + "/{p1?}/{p2?}/{p3?}")] HttpRequestData req,
        string p1, string p2, string p3)
    {
        // Check for token in query parameter
        string tokenFromQuery = req.Query["access_token"];
    
        // Step 1: If token found in query, save it as cookie and redirect to clean URL
        if (!string.IsNullOrEmpty(tokenFromQuery))
        {
            var response = req.CreateResponse(HttpStatusCode.Redirect);
            response.Headers.Add("Set-Cookie", $"access_token={tokenFromQuery}; HttpOnly; Path=/; SameSite=Lax");
            response.Headers.Add("Location", req.Url.AbsolutePath); // remove query from URL
            return response;
        }
    
        // Step 2: Check if access token exists in cookies
        string tokenFromCookie = null;
        if (req.Headers.TryGetValues("Cookie", out var cookies))
        {
            var cookieStr = cookies.FirstOrDefault();
            tokenFromCookie = cookieStr?
                .Split(';')
                .Select(c => c.Trim())
                .FirstOrDefault(c => c.StartsWith("access_token="))?
                .Split('=')[1];
        }
    
        if (!string.IsNullOrEmpty(tokenFromCookie))
        {
            // Token exists, proceed to serve DFM static resources
            return await this.DfmServeStaticsFunction(req, p1, p2, p3);
        }
    
        // Step 3: If no token anywhere, redirect to login
        var tenant = "your-tenant-id";
        var clientId = "your-client-id";
        var redirectUri = "https://yourfunctionhost/api/DFM"; // must match Azure AD redirect URI
        var authUrl = $"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?" +
                      $"client_id={clientId}&response_type=code&redirect_uri={redirectUri}&response_mode=query&scope=openid%20profile%20email";
    
        var loginResponse = req.CreateResponse(HttpStatusCode.Redirect);
        loginResponse.Headers.Add("Location", authUrl);
        return loginResponse;
    }
    

    Summary of What This Code Does

    • First request with token (via ?access_token=xyz) → Stores token in cookie → Redirects to clean URL
    • All future requests → Token is read from cookie, allowing continued access to DFM content
    • If no token at all → Redirects user to Microsoft Login page
      Hope this helps. Do let us know if you have any further queries.

    If this answers your query, do click Accept Answer and Yes for "Was this answer helpful." And if you have any further questions, let us know.

    0 comments No comments

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.