Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Starting with BFF 2.0.1 WithAccessToken leads to error 401 #179

Closed
boekhoffj2801 opened this issue Jun 29, 2023 · 9 comments · Fixed by #180
Closed

Starting with BFF 2.0.1 WithAccessToken leads to error 401 #179

boekhoffj2801 opened this issue Jun 29, 2023 · 9 comments · Fixed by #180
Assignees

Comments

@boekhoffj2801
Copy link

Which version of Duende BFF are you using?
Duende.BFF 2.0.0
Duende.BFF.YARP 2.0.0

Which version of .NET are you using?
.net 7
Describe the bug
We are using a YARP configuration which adds an user access token on redirection. This is working fine up to version 2.0.0 even, if no user has logged in.

"ReverseProxy": { "Routes": { "gProductConfiguratorRoute": { "ClusterId": "gProductConfiguratorCluster", "Match": { "Path": "/gProductConfigExtern.ProductConfigurator/{**remainder}" }, "Metadata": { "Duende.Bff.Yarp.TokenType": "User" } } }, "Clusters": { "gProductConfiguratorCluster": { "Destinations": { "gProductConfigurator/destination1": { "Address": "https://localhost:7105/" } } } } }

After update to BFF 2.0.1 the redirection fails with error 401:

`[06:22:12 Debug] Duende.AccessTokenManagement.OpenIdConnect.UserAccessAccessTokenManagementService
No active user. Cannot retrieve token

[06:22:12 Warning] Duende.Bff.Yarp.AccessTokenRequestTransform
Access token is missing. token type: 'User', local path: 'gProductConfiguratorRoute', detail: 'Missing access token'

[06:22:12 Information] Yarp.ReverseProxy.Forwarder.HttpForwarder
Not Proxying, a 401 response was set by the transforms.`

Our code to configure YARP looks like

        var reverseProxyConfig = builder.Configuration.GetSection("ReverseProxy");
        builder.Services.AddReverseProxy()
            .AddBffExtensions()
            .LoadFromConfig(reverseProxyConfig);

and for the pipeline

        app.UseAuthentication();
        app.UseBff();
        app.UseAuthorization();
        app.MapBffManagementEndpoints();
        app.MapBffReverseProxy(app => app.UseAntiforgeryCheck());

I found an extension method "WithOptionalUserAccessToken()", but if I add this after the last line, I get an error 500:

[06:31:28 Error] Serilog.AspNetCore.RequestLoggingMiddleware
HTTP POST /gProductConfigExtern.ProductConfigurator/GetGroups responded 500 in 40.2883 ms
System.InvalidOperationException: Sequence contains no matching element
at System.Linq.ThrowHelper.ThrowNoMatchException()
at System.Linq.Enumerable.First[TSource](IEnumerable1 source, Func2 predicate)
at Microsoft.AspNetCore.Builder.BffRemoteApiEndpointExtensions.GetBffRemoteApiEndpointMetadata(EndpointBuilder builder) in /_/src/Duende.Bff/Configuration/BffRemoteApiEndpointExtensions.cs:line 17
at Microsoft.AspNetCore.Builder.BffRemoteApiEndpointExtensions.<>c__31.<WithOptionalUserAccessToken>b__3_0(EndpointBuilder endpointBuilder) in /_/src/Duende.Bff/Configuration/BffRemoteApiEndpointExtensions.cs:line 70 at Yarp.ReverseProxy.Routing.ProxyEndpointFactory.CreateEndpoint(RouteModel route, IReadOnlyList1 conventions)
at Yarp.ReverseProxy.Management.ProxyConfigManager.CreateEndpoints()
at Yarp.ReverseProxy.Management.ProxyConfigManager.get_Endpoints()
at Microsoft.AspNetCore.Routing.CompositeEndpointDataSource.CreateEndpointsUnsynchronized()
at Microsoft.AspNetCore.Routing.CompositeEndpointDataSource.EnsureEndpointsInitialized()
at Microsoft.AspNetCore.Routing.DataSourceDependentCache1.Initialize() at System.Threading.LazyInitializer.EnsureInitializedCore[T](T& target, Boolean& initialized, Object& syncLock, Func1 valueFactory)
at Microsoft.AspNetCore.Routing.Matching.DataSourceDependentMatcher..ctor(EndpointDataSource dataSource, Lifetime lifetime, Func1 matcherBuilderFactory) at Microsoft.AspNetCore.Routing.Matching.DfaMatcherFactory.CreateMatcher(EndpointDataSource dataSource) at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.InitializeCoreAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.<Invoke>g__AwaitMatcher|8_0(EndpointRoutingMiddleware middleware, HttpContext httpContext, Task1 matcherTask)
at Serilog.AspNetCore.RequestLoggingMiddleware.Invoke(HttpContext httpContext)

From our point of view there is a breaking change between version 2.0.0 and 2.0.1. Is there a way of configuration to get back the old behavior? We need an optional user access token to answer generally every request but give detailed information if a user has logged in.
I found no examples to get "WithOptionalUserAccessToken" working. Can you provide a sample for such scenario?

To Reproduce
Use version 2.0.0 with YARP config that adds user access token. Update to version 2.0.1. On same method call get error 401.

Expected behavior
Either "routeConfig.WithAccessToken(TokenType.User);" should add a token optionally like before or provide an example, how to add an optional user access token, please.

Log output/exception with stacktrace

(see above)

With kind regards,
J. Boekhoff

@brockallen
Copy link
Member

Starting with BFF 2.0.1

I suspect you mean upgrading to 2.1.0?

In your current use it sounds like you want API calls to be sent to the API even if there is no user token, so anonymously. Is this correct?

@krilek
Copy link

krilek commented Jul 3, 2023

Connecting to this issue as we struggle with the same problem.

In your current use it sounds like you want API calls to be sent to the API even if there is no user token, so anonymously. Is this correct?

Exactly, previously it was possible to use YARP JSON metadata options and access anonymous remote API endpoints. Right now it returns 401.

@brockallen
Copy link
Member

@josephdecock Please have a look into this.

@josephdecock
Copy link
Member

josephdecock commented Jul 3, 2023

@krilek can you double check your version number please? Are you on 2.1.0?

@boekhoffj2801
Copy link
Author

Sorry, I didn't got an notification for changes to this request.
Yes, you are right. If tried to update to 2.1.0. And then an anonymous request to an api call gives 401. If a user has logged in , everything works fine.

@josephdecock josephdecock transferred this issue from DuendeSoftware/Support Jul 5, 2023
@josephdecock
Copy link
Member

In earlier versions of the BFF, we used YARP v1.x, which doesn't have a mechanism to cancel proxy requests. That meant that if we didn't have an access token we had to fall back to anonymous access. But what we always would have preferred to do (as the default behavior) is what we do in the simple Http forwarder - return a 401 error.

Since we've upgraded our dependency on YARP to v2, we now take advantage of its new ability to cancel proxied http requests. This gives us consistency between the two styles of remote API definitions.

So when we made this change we were really fixing a long standing design bug. What was missing though, and what is added in the PR linked to this thread, is the ability to add metadata to YARP routes so that they require an optional user access token.

@boekhoffj2801
Copy link
Author

I'm glad to see, that the missing use case of optional user access token will be supported in the future. Could you provide an example or snippet how to get this working again and work arround the breaking change?

@brockallen
Copy link
Member

@josephdecock will be working on the new docs showing you how to use this. We have a patch 2.1.1 with the updated API.

@josephdecock
Copy link
Member

The PR for the new docs is here. The TL;DR is, in 2.1.1 you can call .WithOptionalUserToken on a yarp route configured with code, or more generally set Duende.Bff.Yarp.OptionalUserToken in the metadata of a yarp route to get optional user access tokens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants