Search code examples
c#azuredocker.net-coreidentityserver4

Identity Server OpenID Config Http Redirect


I'm having an issue with an Identity Server hosted on an Azure Docker WebApp. The IS has multiple clients, one of them is an .NET Core Razor Page App, also hosted on Azure Docker WebApp.

My problem is that the MVC app tries to access the IS via http and not https, as configured, and I'm not sure why.

MVC Startup:

        services
            .AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie()
            .AddOpenIdConnect(options =>
            {
                options.Authority = Configuration["IdentityServer:Authority"];
                options.RequireHttpsMetadata = !Env.IsDevelopment();

                options.ClientId = Configuration["IdentityServer:ClientId"];
                options.ClientSecret = Configuration["IdentityServer:ClientSecret"];

                options.ResponseType = "code";

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

                options.ClaimActions.MapAllExcept("iss", "nbf", "exp", "aud", "nonce", "iat", "c_hash");

                options.UsePkce = true;
                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;
            });

MVC Config:

"IdentityServer": {
  "Authority": "https://****.azurewebsites.net",
  "ClientId": "****-admin",
  "ClientSecret": "****"
}

IS Client Config:

"IdentityServer": {
  "Clients": [
    {
      "ClientId": "****-admin",
      "ClientSecrets": [ { "Value": "*****************************" } ],
      "ClientName": "MVC Client",
      "AllowedGrantTypes": [ "authorization_code" ],
      "AllowedScopes": [ "openid", "profile", "email" ],
      "RedirectUris": [
        "https://****.azurewebsites.net//signin-oidc"
      ],
      "PostLogoutRedirectUris": [
        "https://****.azurewebsites.net/signout-callback-oidc"
      ],
      "RequireConsent": false,
      "AllowOfflineAccess": true,
      "AllowAccessTokensViaBrowser": false,
      "RequirePkce": true,
      "AlwaysSendClientClaims": true,
      "UpdateAccessTokenClaimsOnRefresh": true
    }
  ]
}

Docker File for both:

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY packages /root/.nuget/packages
COPY ["****.Domain/****.Domain.csproj", "****.Domain/"]
COPY ["****.Application/****.Application.csproj", "****.Application/"]
COPY ["****.Infrastructure/****.Infrastructure.csproj", "****.Infrastructure/"]
COPY ["****.Auth/****.Auth.csproj", "****.Auth/"]
RUN dotnet restore "****.Auth/****.Auth.csproj"
COPY . .
WORKDIR "/src/****.Auth"
RUN dotnet build "****.Auth.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "****.Auth.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "****.Auth.dll"]

The problem is now that the MVC Client tries to load OpenID endpoints via http, what fails because the RedirectUri does not match (http vs https), and I don't really understand why.

[2020-04-14 06:10:28 ERR] Invalid redirect_uri: http://****.azurewebsites.net/signin-oidc
{"ClientId":"****","ClientName":"Mvc Client","RedirectUri":null,"AllowedRedirectUris":["https://****.azurewebsites.net/signin-oidc"],"SubjectId":"anonymous","ResponseType":null,"ResponseMode":null,"GrantType":null,"RequestedScopes":"","State":null,"UiLocales":null,"Nonce":null,"AuthenticationContextReferenceClasses":null,"DisplayMode":null,"PromptMode":null,"MaxAge":null,"LoginHint":null,"SessionId":null,"Raw":{"client_id":"****-admin","redirect_uri":"http://****.azurewebsites.net/signin-oidc","response_type":"code","scope":"openid profile email offline_access","code_challenge":"tYfbgtCWvJawPddV3pHVcmEf41PfWE8v4d3js3WzV2Q","code_challenge_method":"S256","response_mode":"form_post","nonce":"637224414258581372.NDkwZmJkMTQtMDg0NS00ODMyLTgwMmYtYjIxYTA4YmYzYjY0MTc1YmY2ZGYtMzMyOC00YTBjLWI5ZDgtMjkzMWViMzk5YjUy","state":"CfDJ8Ox9u0p5MQ9MsZe5b-yGtbTFFUGO9B9TgRxvfcngit3msFwYDgHhej1KZa5t-5APppkSqDp0zj-0IHxZBDgfHr4m0MzsoWSs4M-uzUQ_gFWTtq5z2vH2s_7E5nv4jquHvprvkhYgXXACUolUW0rxUVYNIBf-CpwySLIL-9em4nZpsmQ2IYTTAofgd1xbbRX874H7L8Cs-6ULPdYMz9C8o1blQ5lYjS1IzgAsrTfbQBdxBhUQ53RLerQx5e-OoVWPWQ5Hp4nGCyR6z7ao6jkBPvtipV9D9tgzt8mFGnhqs3aBfcsztruAKOO_lU1Z8UW2NEPtAjMUVjyKpL-pMbpT5dbKH0g2TumWv1cod31oYTB1l42uyG8xwq0d6sJ8cUzDt-PgzkTEX8nnjQ--3301eBk","x-client-SKU":"ID_NETSTANDARD2_0","x-client-ver":"5.5.0.0"},"$type":"AuthorizeRequestValidationLog"}

I'm open for any help.


Solution

  • After some time of investigation and mackies hint, I checked the discovery endpoints and they pointed to http scheme. When running insiden a docker container and azure linux app service some forwarding headers need to be configured, better described here:

    https://learn.microsoft.com/en-US/azure/app-service/containers/configure-language-dotnetcore#detect-https-session

    For me it worked adding the following code lines to the Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
        ...
    
        services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                ForwardedHeaders.XForwardedProto;
            // Only loopback proxies are allowed by default.
            // Clear that restriction because forwarders are enabled by explicit 
            // configuration.
            options.KnownNetworks.Clear();
            options.KnownProxies.Clear();
        });
    }
    
    public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
    {
        app.UseForwardedHeaders();
    
        ...
    }