[英]Duende BFF Yarn does not pass tokens when using gRpc Web Client from Blazor WebAssembly app
I am building a web application with ASP.NET Core 6.我正在使用 ASP.NET 核心 6 构建 web 应用程序。
I have:我有:
My Frontend.Client is configured to call its own BFF (the Frontend.Server), while the server forwards the calls to the REST and gRpc services using Duende.Bff.YARP .我的 Frontend.Client 配置为调用自己的 BFF(Frontend.Server),而服务器使用Duende.Bff.YARP将调用转发到 REST 和 gRpc 服务。
The calls to the REST service work as expected: the client passes the token automatically as by documentation.对 REST 服务的调用按预期工作:客户端按照文档自动传递令牌。
My problem is with the calls to gRpc, which don't seem to use the correct HttpClient with the AntiForgeryToken and the Access Token as it should.我的问题是对 gRpc 的调用,它似乎没有使用正确的 HttpClient 和 AntiForgeryToken 和访问令牌。
I know I'm missing some setting somewhere but I can't find any example on how to use Duende with a gRpcWebClient.我知道我在某处遗漏了一些设置,但我找不到任何关于如何将 Duende 与 gRpcWebClient 一起使用的示例。
My Frontend.Client configuration contains:我的Frontend.Client配置包含:
builder.Services.AddScoped<AuthenticationStateProvider, BffAuthenticationStateProvider>();
builder.Services.AddTransient<AntiforgeryHandler>();
builder.Services.AddHttpClient("backend", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<AntiforgeryHandler>();
builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("backend"));
builder.Services.AddSingleton(services => {
var backendUrl = new Uri(builder.HostEnvironment.BaseAddress);
var channel = GrpcChannel.ForAddress(backendUrl, new GrpcChannelOptions {
HttpHandler = new GrpcWebHandler(new HttpClientHandler()),
});
return new Commenter.CommenterClient(channel);
});
My Frontend.Server configuration contains:我的Frontend.Server配置包含:
builder.Services.AddBff();
var proxyBuilder = builder.Services.AddReverseProxy().AddTransforms<AccessTokenTransformProvider>();
// Initialize the reverse proxy from the "ReverseProxy" section of configuration
proxyBuilder.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
builder.Services.AddAuthentication(options => {
options.DefaultScheme = "cookie";
options.DefaultChallengeScheme = "oidc";
options.DefaultSignOutScheme = "oidc";
})
.AddCookie("cookie", options => {
options.Cookie.Name = "__Host-blazor";
options.Cookie.SameSite = SameSiteMode.Strict;
})
.AddOpenIdConnect("oidc", options => {
options.Authority = "https://localhost:5007";
options.ClientId = "photosharing.bff";
options.ClientSecret = "A9B27D26-E71C-4C53-89A8-3DAB53CE1854";
options.ResponseType = "code";
options.ResponseMode = "query";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("photosrest");
options.Scope.Add("commentsgrpc");
options.Scope.Add("offline_access");
options.MapInboundClaims = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
});
//code omitted for brevity
app.UseAuthentication();
app.UseBff();
app.UseAuthorization();
app.MapBffManagementEndpoints();
app.MapReverseProxy().AsBffApiEndpoint();
The appsettings.json file used to read the configuration contains:用于读取配置的 appsettings.json 文件包含:
"ReverseProxy": {
"Routes": {
"photosrestroute": {
"ClusterId": "photosrestcluster",
"Match": {
"Path": "/photos/{*any}"
},
"Metadata": {
"Duende.Bff.Yarp.TokenType": "User"
}
},
"commentsgrpcroute": {
"ClusterId": "commentsgrpccluster",
"Match": {
"Path": "/comments.Commenter/{*any}"
},
"Metadata": {
"Duende.Bff.Yarp.TokenType": "User"
}
}
},
"Clusters": {
"photosrestcluster": {
"Destinations": {
"photosrestdestination": {
"Address": "https://localhost:5003/"
}
}
},
"commentsgrpccluster": {
"Destinations": {
"commentsgrpdestination": {
"Address": "https://localhost:5005/"
}
}
}
}
}
When my client calls the gRpc, I get a 401 Unauthorized response and Duende.Bff logs that the AntiForgery check did not pass, in fact the request does not have the header with the X-CSRF 1 (while the calls to the REST Api do). When my client calls the gRpc, I get a 401 Unauthorized response and Duende.Bff logs that the AntiForgery check did not pass, in fact the request does not have the header with the X-CSRF 1 (while the calls to the REST Api do )。 This would suggest that the gRpc client is not using the HTTP client that Duende uses.
这表明 gRpc 客户端没有使用 Duende 使用的 HTTP 客户端。
How do I connect my gRpc client to Duende?如何将我的 gRpc 客户端连接到 Duende?
NOTE: before introducing the Authentication / Authorization bit, I was using YARP directly and the calls to gRpc were working just fine.注意:在引入身份验证/授权位之前,我直接使用 YARP 并且对 gRpc 的调用工作正常。 It's when I added Duende that it broke.
当我添加 Duende 时,它就坏了。
The problem was the AntiforgeryHandler, since I had not added it to the chain of the HttpHandlers of my gRpcChannel.问题是 AntiforgeryHandler,因为我没有将它添加到我的 gRpcChannel 的 HttpHandler 链中。 What I did to solve it was
我为解决它所做的是
The AntiforgeryHandler becomes: AntiforgeryHandler 变为:
namespace PhotoSharingApplication.Frontend.Client.DuendeAuth;
public class AntiforgeryHandler : DelegatingHandler {
public AntiforgeryHandler() { }
public AntiforgeryHandler(HttpClientHandler innerHandler) : base(innerHandler) { }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
request.Headers.Add("X-CSRF", "1");
return base.SendAsync(request, cancellationToken);
}
}
The construction of the grpc client in my Frontend.Client project becomes:我的 Frontend.Client 项目中 grpc 客户端的构建变成:
builder.Services.AddSingleton(services => {
var backendUrl = new Uri(builder.HostEnvironment.BaseAddress);
var channel = GrpcChannel.ForAddress(backendUrl, new GrpcChannelOptions {
HttpHandler = new GrpcWebHandler(new AntiforgeryHandler(new HttpClientHandler())),
});
return new Commenter.CommenterClient(channel);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.