azureazure-functionshttp-status-code-403

Azure Functions - 403 Forbidden error while calling from inside Azure Portal


I am trying to execute a Timer triggered function via the Azure Portal but I get a 403 Forbidden error:

enter image description here

My networking settings on the Function App: enter image description here

So it should be available and the appservice itself is running. I have created a new Function App with the default settings on Azure but still get the 403 error. Is there any other setting in Azure that I should set manually to be able to execute the function?

Program.cs

var host = new HostBuilder()
 .ConfigureAppConfiguration((context, config) =>
 {
     var builtConfig = config.Build();

     if (context.HostingEnvironment.IsDevelopment())
     {
         config.AddUserSecrets<Program>();
     }
 })
.ConfigureFunctionsWebApplication()
.ConfigureServices((context, services) =>
{
    var configuration = context.Configuration;
    var connectionString = configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");


    services.AddApplicationInsightsTelemetryWorkerService();
    services.ConfigureFunctionsApplicationInsights();
    services.ConfigureFunctionServices();
    services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(connectionString));
    
    services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

    services.AddAutoMapper(typeof(Program));
    var mapperConfig = new MapperConfiguration(mc =>
    {
        mc.AddProfile(new ConfigureAutoMapper());
    });
})
.Build();
host.Run();

Function test:

public class FunctionTest
{
    private readonly ILogger _logger;

public FunctionTest(ILoggerFactory loggerFactory)
{
    _logger = loggerFactory.CreateLogger<FunctionTest>();
}

[Function("FunctionTest")]
public void Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer)
{
    _logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
    
    if (myTimer.ScheduleStatus is not null)
    {
        _logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
    }
}

}


Solution

  • I successfully executed the Timer trigger function after updating the below code to retrieve configuration details from local.settings.json, which allowed it to directly access the connection string.

    config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
          .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
          .AddEnvironmentVariables();
    var connectionString = configuration["DefaultConnection"];
    

    Program.cs :

    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using Microsoft.EntityFrameworkCore;
    using AutoMapper;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.Azure.Functions.Worker;
    
    namespace FunctionApp16
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var host = new HostBuilder()
                    .ConfigureAppConfiguration((context, config) =>
                    {
                        config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                              .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                              .AddEnvironmentVariables();
    
                        if (context.HostingEnvironment.IsDevelopment())
                        {
                            config.AddUserSecrets<Program>();
                        }
                    })
                    .ConfigureFunctionsWebApplication()
                    .ConfigureServices((context, services) =>
                    {
                        var configuration = context.Configuration;
                        var connectionString = configuration["DefaultConnection"];
                        if (string.IsNullOrEmpty(connectionString))
                        {
                            throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
                        }
                        services.AddApplicationInsightsTelemetryWorkerService();
                        services.AddDbContext<ApplicationDbContext>(options =>
                            options.UseSqlServer(connectionString));
                        services.AddIdentity<ApplicationUser, IdentityRole>()
                                .AddEntityFrameworkStores<ApplicationDbContext>()
                                .AddDefaultTokenProviders();
                        var mapperConfig = new MapperConfiguration(mc =>
                        {
                            mc.AddProfile(new ConfigureAutoMapper());
                        });
                        IMapper mapper = mapperConfig.CreateMapper();
                        services.AddSingleton(mapper);
                    })
                    .ConfigureLogging(logging =>
                    {
                        logging.AddConsole();
                    })
                    .Build();
                host.Run();
            }
        }
    }
    

    FunctionTest.cs :

    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Logging;
    
    namespace FunctionApp16
    {
    
        public class FunctionTest
        {
            private readonly ILogger<FunctionTest> _logger;
    
            public FunctionTest(ILoggerFactory loggerFactory)
            {
                _logger = loggerFactory.CreateLogger<FunctionTest>();
            }
    
            [Function("FunctionTest")]
            public void Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer)
            {
                _logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
    
                if (myTimer.ScheduleStatus is not null)
                {
                    _logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
                }
            }
        }
    }
    

    local.settings.json :

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "<StorageConneString>",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
        "DefaultConnection": "<sqlConneString>"
      }
    }
    

    I added the DefaultConnection in the Function app > Environment variables > App settings as shown below.

    enter image description here

    Azure Function app Output :

    The Timer trigger function ran successfully as shown below.

    enter image description here

    Invocations :

    enter image description here