Jwt Bearer Authentication in a function app
Hi,
Is there an example available of implementing jwt bearer authentication in a function app ?
I am using the durable function monitor tool https://github.com/microsoft/DurableFunctionsMonitor in injected mode in isolated worker model.
I want to authenticate calls to /api/durable-functions-monitor end point , because my other functions in the function app use authorization level as Function and we don't want to establish a separate dedicated function app just for durable function monitor
Hence what we are trying to accomplish is use jwt bearer authentication just to secure the endpoint /api/durable-functions-monitor
Azure Functions
-
Praveen Kumar Gudipudi • 275 Reputation points • Microsoft External Staff • Moderator
2025-04-30T00:36:05.0733333+00:00 Hello @Parag Kale,
Please find the Azure Functions with JWT Authentication steps below,
Issuing the JWT
JSON Web Tokens are simply a mechanism for securely transferring JSON strings. Rather than having the user pass credentials back and forth on each call and then checking the user’s credentials over and over, we can simply retrieve the relevant information about the user and encrypt it into a token which we return to the client as a cookie. When the client makes subsequent calls, the client passes the JWT back which the application will decrypt and verify that the contents are valid.
Note that because the token is passed with each request, you’ll want to be cautious not to go overboard and only add key data like the username, user ID, user email, role(s) and so on.
We’re going to use the JWT package to generate and parse our tokens:
Please follow below documents to configure JWT token in your function app: https://charliedigital.com/2020/05/24/azure-functions-with-jwt-authentication/
If you have any further queries, please feel free to reach out us.
-
Praveen Kumar Gudipudi • 275 Reputation points • Microsoft External Staff • Moderator
2025-05-01T10:58:33.93+00:00 Hello @Parag Kale,
Following up to see if you have chance to check my previous response if that helps you to resolve your issue, please let us know.
-
Praveen Kumar Gudipudi • 275 Reputation points • Microsoft External Staff • Moderator
2025-05-02T19:34:15.6633333+00:00 Hello @Parag Kale,
We haven't heard back from you yet, and I wanted to ensure everything is on track and see if there's anything more, we can assist you with.
-
Dasari Kamali • 335 Reputation points • Microsoft External Staff • Moderator
2025-05-06T04:36:32.4033333+00:00 Hi @Parag Kale,
You can secure just the/api/durable-functions-monitor
endpoint by adding custom middleware in the isolated worker model. Configure JWT Bearer auth in theProgram.cs
and validate tokens only when the request path matches that endpoint. -
Parag Kale • 20 Reputation points
2025-05-06T09:00:32.28+00:00 Any code example you could share for a function app?
I know this works for mvc applications. I couldn’t find a working code for a function app
-
Dasari Kamali • 335 Reputation points • Microsoft External Staff • Moderator
2025-05-07T06:07:07.5666667+00:00 Hi @Parag Kale,
Create an Azure AD app and add the Microsoft Azure PowerShell (1950a258-227b-4e31-a9cf-717495945fc2) in
Authorized client applications
as shown below.Run the below commands in Powershell to retrieve the Access Token.
$tenantId = 'tenantId' Connect-AzAccount -Tenant $tenantId -UseDeviceAuthentication (Get-AzAccessToken -ResourceUrl "api://<60efd83bxxx>").Token
Below is the sample Durable function code to authenticate using the Jwt Bearer token.
using System.IdentityModel.Tokens.Jwt; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.DurableTask; using Microsoft.DurableTask.Client; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; namespace FunctionApp62 { public static class Function1 { private const string Issuer = "https://login.microsoftonline.com/<tenantID>/v2.0"; private const string Audience = "<ClientID>"; private static readonly string MetadataAddress = $"{Issuer}/.well-known/openid-configuration"; private static readonly ConfigurationManager<OpenIdConnectConfiguration> ConfigManager = new ConfigurationManager<OpenIdConnectConfiguration>( MetadataAddress, new OpenIdConnectConfigurationRetriever()); [Function(nameof(Function1))] public static async Task<List<string>> RunOrchestrator( [OrchestrationTrigger] TaskOrchestrationContext context) { var logger = context.CreateReplaySafeLogger(nameof(Function1)); logger.LogInformation("Running orchestrator..."); var outputs = new List<string> { await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo"), await context.CallActivityAsync<string>(nameof(SayHello), "Seattle"), await context.CallActivityAsync<string>(nameof(SayHello), "London") }; return outputs; } [Function(nameof(SayHello))] public static string SayHello([ActivityTrigger] string name, FunctionContext executionContext) { var logger = executionContext.GetLogger("SayHello"); logger.LogInformation("Saying hello to {name}.", name); return $"Hello {name}!"; } [Function("DurableFunctionsMonitor")] public static async Task<HttpResponseData> HttpStart( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] Microsoft.Azure.Functions.Worker.Http.HttpRequestData req, [DurableClient] DurableTaskClient client, FunctionContext executionContext) { var logger = executionContext.GetLogger("DurableFunctionsMonitor"); if (!req.Headers.TryGetValues("Authorization", out var authHeaders)) { var unauthorizedResponse = req.CreateResponse(System.Net.HttpStatusCode.Unauthorized); await unauthorizedResponse.WriteStringAsync("Missing Authorization header."); return unauthorizedResponse; } var authHeader = authHeaders.FirstOrDefault(); if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ")) { var unauthorizedResponse = req.CreateResponse(System.Net.HttpStatusCode.Unauthorized); await unauthorizedResponse.WriteStringAsync("Missing or invalid Authorization header."); return unauthorizedResponse; } var token = authHeader.Substring("Bearer ".Length).Trim(); if (!await ValidateJwtTokenAsync(token, logger)) { var unauthorizedResponse = req.CreateResponse(System.Net.HttpStatusCode.Unauthorized); await unauthorizedResponse.WriteStringAsync("Invalid token."); return unauthorizedResponse; } string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(nameof(Function1)); logger.LogInformation("Started orchestration with ID = '{instanceId}'.", instanceId); return await client.CreateCheckStatusResponseAsync(req, instanceId); } private static async Task<bool> ValidateJwtTokenAsync(string token, ILogger logger) { var tokenHandler = new JwtSecurityTokenHandler(); try { var config = await ConfigManager.GetConfigurationAsync(CancellationToken.None); var validationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = Issuer, ValidateAudience = true, ValidAudience = Audience, ValidateLifetime = true, RequireExpirationTime = true, ValidateIssuerSigningKey = true, IssuerSigningKeys = config.SigningKeys }; tokenHandler.ValidateToken(token, validationParameters, out _); logger.LogInformation("Token validated successfully."); return true; } catch (Exception ex) { logger.LogError($"Token validation failed: {ex.Message}"); return false; } } } }
Test the below curl command to get the output,
curl http://localhost:7220/api/DurableFunctionsMonitor -H "Authorization: Bearer <AccessToken>"
Local Output :
Azure Function App Output :
-
Dasari Kamali • 335 Reputation points • Microsoft External Staff • Moderator
2025-05-08T04:32:26.9566667+00:00 Hi @Parag Kale,
Just following up to see if you had a chance to review my previous message.
-
Parag Kale • 20 Reputation points
2025-05-08T22:12:38.53+00:00 Don't think this will open http://localhost:7220/api/DurableFunctionsMonitor in the browser
-
Dasari Kamali • 335 Reputation points • Microsoft External Staff • Moderator
2025-05-09T05:20:44.15+00:00 Hi @Parag Kale,
Yes, we can't open
http://localhost:7220/api/DurableFunctionsMonitor
directly in the browser because it requires anAccess Token
. So, I first tested it using thecurl
command in the command prompt.Then, I accessed [http://localhost:7220/runtime/webhooks/durabletask/instances/f4b174d2xxxx?code=0CAtdJuMyk8zxxxxx] in the browser.
Terminal Output :
-
Parag Kale • 20 Reputation points
2025-05-09T11:30:48.95+00:00 Thanks for the script.
I want to know where is the token being generated? When we use the durable function monitor in injected mode, we don’t have access to its front end react module.
so precisely my requirement is when the durable functions mnitor endpoint is visited in browser, it should have access token either generated with in the function or in some other http function and redirected to this function with token passed in header.
-
Dasari Kamali • 335 Reputation points • Microsoft External Staff • Moderator
2025-05-09T12:19:34.2566667+00:00 Hi @Parag Kale,
I shared you the Powershell commands in my previous comment, run them in Powershell to get the Access Token.
-
Parag Kale • 20 Reputation points
2025-05-09T13:21:37.65+00:00 Okay, got it.
so if I directly open the endpoint of durable function monitor in browser, how can I pass the token generated by powershell in first step
-
Dasari Kamali • 335 Reputation points • Microsoft External Staff • Moderator
2025-05-12T03:33:14.85+00:00 Hi @Parag Kale,
Pass your Access Token in the below command at
<AccessToken>
and test it in the command prompt.curl http://localhost:7220/api/DurableFunctionsMonitor -H "Authorization: Bearer <AccessToken>"
-
Dasari Kamali • 335 Reputation points • Microsoft External Staff • Moderator
2025-05-13T04:57:03.2766667+00:00 Hi @Parag Kale,
Just checking in to see if above information was helpful. If you have any further updates on this issue, please feel free to post back.
Sign in to comment