DuendeSoftware / Support

Support for Duende Software products
20 stars 0 forks source link

Issue with YARP and Kubernetes Deployment: BFF Application unable to redirect to Identity Server login page via Reverse Proxy #820

Closed abdullah-itblue closed 1 year ago

abdullah-itblue commented 1 year ago

I have set up an Identity Server and BFF (Backend for Frontend) application within the same Kubernetes pod, utilizing multiple containers.

The problem I am facing is that when I access the "bff/login" endpoint, the BFF application should redirect me to the Identity Server login page via the YARP reverse proxy. This redirection works perfectly on my local development environment, but after deploying the application to Kubernetes, it no longer functions as expected. The BFF application does not navigate to the Identity Server, nor does it redirect to the specified URL provided in the authority.

In Kubernetes there is a reverse proxy called trefik as in kubernetes you need a reverse proxy to work.

Could anyone help me troubleshoot this issue so BFF application can successfully redirect to the Identity Server login page?

josephdecock commented 1 year ago

It sounds like you need to add the forwarded headers middleware to your IdentityServer and BFF. See here for more details: https://docs.duendesoftware.com/identityserver/v6/deployment/proxies/.

abdullah-itblue commented 1 year ago

I have added forward headers , the problem is when I am navigation from bff to idc its looses https this is my code

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders =
        ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;
});

var bffOptions = new BffOptions();
builder.Configuration.GetSection("Bff").Bind(bffOptions);

builder.Services.AddAuthorization();

builder.Services
    .AddBff
    (
        options => options.ManagementBasePath = "/bff"

    )
    .AddRemoteApis();

JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

builder.Services
    .AddAuthentication
    (
        options =>
        {
            options.DefaultScheme = "cookie";
            options.DefaultChallengeScheme = "oidc";
            options.DefaultSignOutScheme = "oidc";
        }
    )
    .AddCookie
    (
        "cookie",
        options =>
        {
            options.Cookie.Name = "__Host-bff";
            options.Cookie.SameSite = SameSiteMode.Strict;
        }
    )
    .AddOpenIdConnect("oidc", options =>
    {
        options.Authority = bffOptions.Authority;
        options.RequireHttpsMetadata = false;

        options.ClientId = bffOptions.ClientId;
        options.ClientSecret = bffOptions.ClientSecret;

        options.ResponseType = "code";

        options.UsePkce = true;

        options.Scope.Clear();
        foreach (var scope in bffOptions.Scopes)
            options.Scope.Add(scope);

        options.GetClaimsFromUserInfoEndpoint = true;
        options.SaveTokens = true;
        options.MapInboundClaims = false;     

    });

var app = builder.Build();

app.Use((context, next) =>
{
    context.Request.Scheme = "https";
    return next(context);
});

var fordwardedHeaderOptions = new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
};
fordwardedHeaderOptions.KnownNetworks.Clear();
fordwardedHeaderOptions.KnownProxies.Clear();

app.UseForwardedHeaders(fordwardedHeaderOptions);

app.UseHttpsRedirection();

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();

app.UseBff();
app.UseAuthorization();
app.MapBffManagementEndpoints();
josephdecock commented 1 year ago

Do you have the forwarded headers middleware in IdentityServer too?

abdullah-itblue commented 1 year ago

yes I have

josephdecock commented 1 year ago

I suspect that your reverse proxy might not be setting the forwarded headers correctly. Debugging that might be a bit tricky, but you could log the incoming http request's headers in a piece of middleware to check that.

dclayton77 commented 1 year ago

I have a very similar issue which can be found here.

In terms of K8S, here are the steps that I took. My environment is slightly different but it is worth checking your environment with similar steps. I am using a Hetzner Load Balancer, Kong Gateway for the Ingress Controllers, the ingresses point to standard services which in turn point to standard pods. The ingress terminates the HTTPS traffic and sends it via port 80 from that point down. I also have a LinkerD service mesh installed in the cluster.

Upon navigating to the login page, I can see in the BFF logs that the required headers are present so I believe I have eliminated the K8S environment messing with the headers. However, the redirect URI is still missing https so my latest assumption is it is something not configured correctly in the BFF service.

Hopefully that helps you eliminate the K8S environment. I'm watching this thread with interest in the hope that one of us manages to isolate the problem.

dclayton77 commented 1 year ago

@abdullah-itblue I managed to finally resolve my issue. I ended up reworking my proxy so that the client ip address was preserved as I thought that might be a factor. That still didn't solve it, however, after applying the following, everything is now working great.

They key is to combine the forwarded headers configuration so that it is set as follows:

var forwardedHeadersOptions = new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.All,
    ForwardLimit = 1
};
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardedHeadersOptions);
josephdecock commented 1 year ago

Thanks so much for following up here! @abdullah-itblue, when you get a chance, please let us know if this works for you too.

josephdecock commented 1 year ago

Closing, but feel free to reopen if necessary.