Extend example of "JS With Backend" to include Swagger/Swashbuckle support? #123
-
BFF version3 .NET version8 DescriptionI have a new BFF project where the structure is very close to the sample located at https://github.com/DuendeSoftware/Samples/tree/main/BFF/v3/JsBffSample, where a SPA client is using a "local API", hosted in the BFF app. In my development environment, I'd like to be able to use SwaggerUI for some local testing of the BFF's API. However, I'm having trouble getting anything to work in Swagger or using another REST client, even though the SPA front-end is working exactly as expected. Is there a sample out there somewhere that would demonstrate the steps necessary to interact with the BFF local API using a REST client or Swagger/Swashbuckle? Thank you! Reproduction stepsNo response Expected behaviorNo response LogsNo response Additional contextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Interesting question! And a great opportunity to dig into some internals :-) I take it you are seeing an inexplicable I'll assume we're using the JsBffSample/FrontendHost/Program.cs as-is, and then explain some of the required additions. Also, you will need the With that, let's start! You will want to add the required services for Swashbuckle and the Swagger UI first: var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
+ builder.Services.AddEndpointsApiExplorer();
+ builder.Services.AddSwaggerGen(); Next, you'll want to configure the request pipeline. This is where we'll wire up Swagger UI, and make sure the var app = builder.Build();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
+
+ if (app.Environment.IsDevelopment())
+ {
+ app.UseSwagger();
+ app.UseSwaggerUI();
+
+ app.Use(async (context, next) =>
+ {
+ // CRITICAL: DO NOT DEPLOY THIS CHECK TO PRODUCTION OR A PUBLCI URL - IT IS ALL TO EASY TO BYPASS!
+ var swaggerUIOptions = context.RequestServices.GetRequiredService<IOptions<SwaggerUIOptions>>().Value;
+ if (context.Request.Headers.Referer.Any(it => it.EndsWith($"/{swaggerUIOptions.RoutePrefix}/index.html")))
+ {
+ var bffOptions = context.RequestServices.GetRequiredService<IOptions<BffOptions>>().Value;
+ context.Request.Headers[bffOptions.AntiForgeryHeaderName]= bffOptions.AntiForgeryHeaderValue;
+ }
+ await next();
+ });
+ }
+
app.UseBff();
app.UseAuthorization();
app.MapBffManagementEndpoints();
// if you want the TODOs API local
app.MapControllers()
.RequireAuthorization()
.AsBffApiEndpoint();
// if you want the TODOs API remote
// app.MapRemoteBffApiEndpoint("/todos", "https://localhost:5020/todos")
// .RequireAccessToken(Duende.Bff.TokenType.User);
app.Run(); What this code does is when in a development environment, add Swagger and Swagger UI to the request pipeline. It also adds a middleware delegate that checks the HTTP Referer header - if the request is coming from Swagger UI's When not adding this middleware delegate, the BFF middleware will typically block the request as it does not contain the required header, resulting in the 401 you are seeing. Caution An alternative could be to disable BFF's anti-forgery check, but I would advise against this as you may miss required checks coming from non-Swagger UI endpoints in here. For completeness, here's how you could do that: - app.MapControllers()
+ var localApis = app.MapControllers()
.RequireAuthorization()
.AsBffApiEndpoint();
+ if (app.Environment.IsDevelopment())
+ {
+ localApis.SkipAntiforgery();
+ } |
Beta Was this translation helpful? Give feedback.
Interesting question! And a great opportunity to dig into some internals :-) I take it you are seeing an inexplicable
401 Unauthorized
when invoking the API using Swagger UI?I'll assume we're using the JsBffSample/FrontendHost/Program.cs as-is, and then explain some of the required additions. Also, you will need the
Swashbuckle.AspNetCore
NuGet package installed.With that, let's start! You will want to add the required services for Swashbuckle and the Swagger UI first:
Next, you'll want to configure the request pipeline. …