microsoft / DurableFunctionsMonitor

A monitoring/debugging UI tool for Azure Durable Functions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Authentication issues in injected mode

yoozek opened this issue · comments

On wiki here, there is an instruction to set app setting WEBSITE_AUTH_OPENID_ISSUER
However when I'm trying to do this on my Function App it throws the following error:
AppSetting with name 'WEBSITE_AUTH_OPENID_ISSUER' is not allowed.

The same goes for the 'WEBSITE_AUTH_CLIENT_ID' app setting.

What should I do to configure it now?
I'm using WebAppAuthSettingsV2 for EasyAuth

Now I can see in Kudu console that these variables are already set. However I get 401
image

Hello @yoozek ,

You are only supposed to set WEBSITE_AUTH_CLIENT_ID and WEBSITE_AUTH_OPENID_ISSUER settings when deploying DfMon outside Azure (e.g. into a K8s cluster).
If you deploy DfMon as an Azure Functions instance, you should not set those settings exactly because they're already set by the platform.

The easiest way to deploy DfMon in standalone mode as a dedicated Azure Functions instance is to use this button:

Deploy to Azure

And the recommended authentication mode in that case is server-directed login flow. Instructions on how to configure your AAD application for that flow are here.

I can see from your error message that you're trying to use client-directed login flow instead. This can work, but there should be strong reasons for doing so. Can you provide more details on your current setup and rationale for going in that direction, so I can advise you further?

Hello @scale-tone
Thanks for quick reply. Ok, I found out that as you wrote there is no need to set these appsettings because they are already in place.

I'm running Azure Function App with enabled Authentication (V2) and I would like to add monitor in injected mode.
Now I have issue with "Login Failed" described on screen above.

Is this trying to authenticate to storage account with task hub using my principal (logged in user) or as application (the one configured in Authentication tab in azure portal)?

I would like to add monitor in injected mode.

@yoozek , can you show a screenshot of this tab:

image

of your Function App instance in Azure Portal (with whatever sensitive info redacted)?

@scale-tone
image

auth works fine by the way

I don't know what I changed but it works now. Hovewer it still says anonymous in right top, is this correct?

it still says anonymous in right top, is this correct?

No, it is not correct, it means that your DfMon endpoint now has its authentication disabled (which, of course, is a bad idea for a publicly available endpoint).

This can only happen either when DfmSettings.DisableAuthentication property is set to true in your code or when DFM_NONCE config setting is set to i_sure_know_what_i_am_doing.

Please, provide the following things (with all sensitive info redacted):

  • Your CSPROJ-file.
  • Your host.json file.
  • How your call to DfmEndpoint.Setup() looks like right now (this call must be in your code, if you're using DfMon in injected mode).
  • A screenshot of your Function App instance's Configuration tab in Azure Portal. Only config setting names are needed.
  • Open Dev Tools in your browser (by pressing F12), go to Network tab there, then navigate to your DfMon endpoint and make a screenshot of all network calls that are failing (if any), with details like status code and/or error message.

Do you still need help on this, @yoozek ?

@scale-tone yes, sorry this week I had a lot of different topics and couldn't find time to get into this again. I'll try it again and describe next week

@scale-tone sorry for the delay, here are the details

Csproj

<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<TargetFramework>net6.0</TargetFramework>
		<Nullable>enable</Nullable>
		<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
		<AzureFunctionsVersion>v4</AzureFunctionsVersion>
		<DurableFunctionsMonitorRoutePrefix>monitor</DurableFunctionsMonitorRoutePrefix>
  </PropertyGroup>
	<ItemGroup>
		<PackageReference Include="DurableFunctionsMonitor.DotNetBackend" Version="6.2.1" />
//...

host.json

{
  "version": "2.0",
  "functionTimeout": "00:10:00",
  "logging": {
    "logLevel": {
      "default": "Warning",
      "Host.Results": "Information",
      "Host.Triggers.DurableTask": "Information",
      "System.Net.Http.HttpClient": "Information",
      "Microsoft.EntityFrameworkCore.Database.Command": "Warning",
      "Function": "Information"
    },
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  }
}

In startup.cs

       DfmEndpoint.Setup(new DfmSettings
        {
            DisableAuthentication = appEnvironment is { IsDev: true, IsAzureDev: false }
        });

Function App config names
image

From Network traffic in browser I see:
/api/monitor/a/p/i/easyauth-config - it returns 200 but userName is null
/api/monitor/a/p/i/task-hub-names - returns 401 Unauthorized

Error window shows following:
image

Thanks for that info, @yoozek .
Sorry, but so far I am unable to reproduce that behavior.

Can you try to open some task hub directly (by navigating to a URL like https://my-func-instance/api/monitor/MyTaskHub )? Does it produce the same error message or something different?
Can you show a screenshot of a failing request in browser's dev tools (with all sensitive info hidden, but preferably with response headers shown)?

Also can you please confirm that your authentication settings are still the same as what's shown on your initial screenshot?

Also can you show all the dependencies in your CSPROJ-file?

Hi @scale-tone

When accessing it directly I have this error:
image

/api/monitor/a/p/i/easyauth-config returns 200 and userName = null

In browser's network tab I can see this
image

Yes, I can confirm that my authentication settings on Function App are the same

here is the CSPROJ file

<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<TargetFramework>net6.0</TargetFramework>
		<Nullable>enable</Nullable>
		<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
		<AzureFunctionsVersion>v4</AzureFunctionsVersion>
		<DurableFunctionsMonitorRoutePrefix>monitor</DurableFunctionsMonitorRoutePrefix>
  </PropertyGroup>
	<ItemGroup>
		<PackageReference Include="Azure.Security.KeyVault.Certificates" Version="4.4.0" />
		<PackageReference Include="DurableFunctionsMonitor.DotNetBackend" Version="6.2.1" />
		<PackageReference Include="EFCore.BulkExtensions" Version="6.6.2" />
		<PackageReference Include="FluentEmail.Liquid" Version="3.0.2" />
		<PackageReference Include="FluentEmail.Smtp" Version="3.0.2" />
		<PackageReference Include="ISO.4217.CurrencyCodes" Version="1.0.10" />
	    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
		<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.9.4" />
		<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="1.5.0" />
		<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.1.1" />
		<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
		<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="6.0.8" />
		<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.3" />
		<PackageReference Include="Microsoft.SharePointOnline.CSOM" Version="16.1.23311.12000" />
		<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
		<PackageReference Include="NSwag.ApiDescription.Client" Version="13.18.2">
			<PrivateAssets>all</PrivateAssets>
			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
		<PackageReference Include="SharpZipLib" Version="1.4.1" />
		<PackageReference Include="sib_api_v3_sdk" Version="3.3.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="local.settings.json">
		  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
		</None>
		<None Update="host.json">
			<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
		</None>
	</ItemGroup>
</Project>

@yoozek , I can see from your CSPROJ-file that your local.settings.json file gets deployed to your Function App instance.
This should not be the case (as it might contain settings that are not intended for cloud env).
I suggest you add <CopyToPublishDirectory>Never</CopyToPublishDirectory> flag to its node to prevent that from happening. And re-deploy the app, of course.
This might not resolve the actual issue, but it is a good idea to do so anyway.

If after that the issue is still present, can you please try to navigate and login to your DfMon instance in browser's incognito mode and see if results are the same?

Still the same, is service principal requiring any special permissions?

service principal requiring any special permissions?

Which service principal are you referring to?

Anyway, to explain the situation better.

The 401 Unauthorized response that you're observing is not produced by DfMon's code. Whenever DfMon returns 401, it always gives an empty body along with it and never produces any HTML.

The only thing that could possibly return such a response is EasyAuth module. But so far I am unable to identify the combination of settings that could result in such strange behavior of it. With the settings you've shown on your screenshot it should return 302 Found for any requests not containing a valid auth cookie and allow all other requests to proceed.

In your case, for some yet unknown reason, EasyAuth allows requests to DfMon's HTML statics and even allows requests to /a/p/i/easyauth-config, but rejects all other API calls. So surely there must be something missing in the picture.

Do you have any other HTTP-triggered functions or proxies in your project? If yes, which authentication do they use?

Do you have any reverse proxy (like App Gateway, or FrontDoor, or API Management) in front of your Function App instance?

Can I ask you to stream logs from your Function App instance and check if any errors appear there when you navigate to DfMon?

Also can you please confirm that those failing requests contain 'Cookie' header in them?

Do you still need help on this, @yoozek ?

We decided to not invest more time in that. If this works for you and it's not reproducable let's give up.

Anyway much thanks for your time and tips to investigate it