0

We have an existing .NET 6 Web Application, protected with Duende Identity Server 6, running on Azure App Service. This works flawlessly.

We want to add Azure App Service Authentication in front of the this Azure App Service. That way we can enforce our company Active Directory (incl. MFA) to be used before even accessing the Web Application.

Our web-application is an OIDC client that calls an Duende OIDC Identity Server with it's own credential store.

Setting up App Service Authentication with our corporate AD works. We need to authenticate before we can access our Web Application.

After logging in on our OIDC Identity Server, a redirect takes place to https://webapp.com/signin-oidc. That responds with a 403-forbidden.

If I intercept the call to https://webapp.com/signin-oidc and remove the User-Agent header, it works! So I guess there is some CORS issue that I can't solve yet.

Things I tried:

  • Set Allowed Origins to "*" on webapp.com
  • Set Allowed Origins to "*" on our Identity Server web app
  • Added allowed Redirect url https://webapp.com/signin-oidc to the Azure App Service Authentication settings

Anything I forget or should think of?

Many thanks in advance!

Reproduced with this very basic ASP.NET 6 MVC application:

using System.IdentityModel.Tokens.Jwt;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
    .AddCookie("Cookies")
    .AddOpenIdConnect("oidc", options =>
    {
        options.Authority = "https://our-login-authority-url.com";

        options.ClientId = "com.company.app";
        options.ClientSecret = "<.. secret ..>";
        options.ResponseType = "code";
        options.UsePkce = true;

        options.Scope.Clear();
        options.Scope.Add("openid");
        options.Scope.Add("profile");
        options.Scope.Add("offline_access");

        // keeps id_token smaller
        options.GetClaimsFromUserInfoEndpoint = true;
        options.SaveTokens = true;
    });

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}")
    .RequireAuthorization();

app.Run();

Network-log. "Sensitive" data obscured. networkcalls

Header information from POST /signin-oidc request:

POST /signin-oidc HTTP/1.1
Host: mywebapp.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: nl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 699
Origin: null
DNT: 1
Connection: keep-alive
Cookie: .AspNetCore.OpenIdConnect.Nonce.CfDJ8K<...>NaM5Tw==
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-site
Pragma: no-cache
Cache-Control: no-cache

Update: Origin: null

If the Origin value is set to the OIDC authority url that is also an allowed return url in Azure App Service Authentication settings - it works.

Now I need to investigate why the POST from Identity Server does not contain a Origin value in the header.

JonHendrix
  • 933
  • 15
  • 28
  • The `User-Agent` header is not (normally) going to be the cause-of CORS errors, and CORS errors are typically HTTP 405, not 403 - so absent a screenshot of your browser console that explicitly says it's a CORS error I'm going to assume you're mistaken. Have you checked your ASP.NET Core request-pipeline configuration for any middleware that might be rejecting requests? Please share your `Configure`, `ConfigureServices`, (or .NET 6-style Startup/Main/`IHost` code). – Dai Jul 06 '23 at 08:10
  • Thanks for the swift feedback - I'm setting up the smallest web-app to repro this issue and get back to you – JonHendrix Jul 06 '23 at 08:24
  • Small repro-app setup is added to the original post – JonHendrix Jul 06 '23 at 08:49
  • Please share a screenshot of the errors you see in your browser's devtool's network tab - ensure "Preserve log" is checked so it shows all requests after redirections. – Dai Jul 06 '23 at 08:51
  • Screenshot added – JonHendrix Jul 06 '23 at 09:00
  • There are no CORS errors reported in that screenshot, so you should retitle your question - and remove the example code too: the problem is with the configuration of the IdentityServer, not the client application. – Dai Jul 06 '23 at 09:01
  • I don't grasp that idea just yet. The signin-oidc is middleware in my client application. If I intercept the POST and remove the User-Agent header, it works. How is that an Identity Server issue? I must be missing something fundamentally then... – JonHendrix Jul 06 '23 at 09:07
  • Just to confirm, which application/server is referred to be the `xxxx.eu` hostname in the `signin-oidc` error response row? And are you able to access your IdentityServer logs? You might need to set them to Verbose to make it log sufficient detail about its requests. – Dai Jul 06 '23 at 09:11
  • Our client application is called https://webapp.com/signin-oidc. Just checked the verbose IS6 logging - all success. Start authorize request - Authorize request protocol validation successful - AuthorizeResponseGenerator: Creating Authorization Code Flow response - Code issued for <..> - Authorize endpoint response <..json ..> - End authorize request - Invoking result: Duende.IdentityServer.Endpoints.Results.AuthorizeResult – JonHendrix Jul 06 '23 at 09:20
  • Authorize endpoint response also contains "webapp.com/signin-oidc" in the "RedirectUri"-property. But that's obvious, or else the authentication flow would have failed earlier with an invalid_request. – JonHendrix Jul 06 '23 at 09:21
  • Okay, that does help narrow it down. What do you see in the verbose-logs for your `webapp.com` site? Is there any response-body or interesting headers in the 403 response? I'm wondering if you need to configure `aud` validation too. – Dai Jul 06 '23 at 09:22
  • Verbose logging on this basic web-app just shows the generic 403 error. Eventlog.xml also empty. – JonHendrix Jul 06 '23 at 09:33
  • Added the Headers from the POST-request. Could it have something to do with same-site-cookie restrictions? Maybe the App Service Authentication misses some required auth-information when receiving this /signin-oidc call. Still keeping in mind that removing the User-agent-header makes this call work. – JonHendrix Jul 06 '23 at 09:34
  • The `Origin: null` line looks suspicious... – Dai Jul 06 '23 at 09:51
  • What's in the response-body of the 403 response? Have you configured the `webapp.com` website to log `Microsoft.Extensions.Logging` to disk? Can you set a breakpoint on methods added for [`OpenIdConnectOptions.Events`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.openidconnect.openidconnectoptions.events?view=aspnetcore-7.0#microsoft-aspnetcore-authentication-openidconnect-openidconnectoptions-events)? – Dai Jul 06 '23 at 09:53
  • Raw response: "You do not have permission to view this directory or page." – JonHendrix Jul 06 '23 at 09:55
  • `Origin: null` is the issue I guess! Using a browser extension to overwrite the `null` value to the value of the OIDC-authority url, makes it work. Question is, how/why does the .NET 6 Identity Server not supply the origin. Hacking it with web.config might be a workaround – JonHendrix Jul 06 '23 at 10:04

0 Answers0