see here for documentation.
duendesoftware / bff Goto Github PK
View Code? Open in Web Editor NEWFramework for ASP.NET Core to secure SPAs using the Backend-for-Frontend (BFF) pattern
License: Other
Framework for ASP.NET Core to secure SPAs using the Backend-for-Frontend (BFF) pattern
License: Other
see here for documentation.
For abandoned/expired tickets
Some starting code commented out in AuthenticationTicketExtensions.cs
For non-SPA clients?
Duende IdentityServer4
Donnet 6 Preview 4
Attribute [AllowAnonymous]
not works in the controller and 401 error is returned instead.
Result:
401 Unauthorized exception when calling the MVC controller
Observation:
When the below line is commented out from the Startup class the controller can be accessed anonymously.
app.UseBff();
The code in Util.IsLocalUrl
is clearly borrowed from MVC. The thing is that various parts of MVC recognize and resolve "~/" in url strings. But in BFF the values that pass this are used in AuthenticationProperties.RedirectUri
and the ultimate consumer of this is the OIDC authentication middleware which has no special processing for "~/".
I think the following fragment should be removed and return false.
BFF/src/Duende.Bff/Endpoints/Util.cs
Lines 28 to 44 in 17a3fc1
Which version of Duende IdentityServer are you using?
Duende.IdentityServer 6.0.0-preview.6
Duende.BFF 1.1.3
Which version of .NET are you using?
6.0.200
Describe the bug
Getting error when running Quick Start Sample "JavaScript applications with a backend". When clicking login I am getting the error.
I am running on Mac using Visual Studio Code
I first tried to create the apps per the docs. I got this error. Then I cloned the QuickStart samples and got the same error when just running the sample.
https://github.com/DuendeSoftware/Samples/tree/main/IdentityServer/v6/Quickstarts/6_JS_with_backend/src
To Reproduce
Then I get the error IDX20807 as shown below in stacktrace.
Note: If I don't run the IdentityServer I get a different error so I think it is communicating with IdentityServer properly.
Expected behavior
The user should be logged in per the sample docs: https://docs.duendesoftware.com/identityserver/v6/quickstarts/js_clients/js_with_backend/
Log output/exception with stacktrace
System.IO.IOException: IDX20807: Unable to retrieve document from: 'System.String'. HttpResponseMessage: 'System.Net.Http.HttpResponseMessage', HttpResponseMessage.Content: 'System.String'.
at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'.
---> System.IO.IOException: IDX20807: Unable to retrieve document from: 'System.String'. HttpResponseMessage: 'System.Net.Http.HttpResponseMessage', HttpResponseMessage.Content: 'System.String'.
at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
--- End of inner exception stack trace ---
at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleChallengeAsyncInternal(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.ChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
at Duende.Bff.DefaultLoginService.ProcessRequestAsync(HttpContext context) in /_/src/Duende.Bff/Endpoints/DefaultLoginService.cs:line 48
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Duende.Bff.Endpoints.BffMiddleware.Invoke(HttpContext context) in /_/src/Duende.Bff/BffMiddleware.cs:line 108
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Additional context
Add any other context about the problem here.
Thank you for your help!
Tom
Duende IdentityServer V5
Donnet 6 Preview 4
Below code is added to the StartUp class for EFCore based session store implementation.
services.AddBff()
.AddEntityFrameworkServerSideSessions(options=>
{
options.UseSqlServer(cn);
});
When the user tries to log in below exception is thrown:
InvalidOperationException: The DbContextOptions passed to the SessionDbContext constructor must be a DbContextOptions<SessionDbContext>. When registering multiple DbContext types, make sure that the constructor for each context type has a DbContextOptions<TContext> parameter rather than a non-generic DbContextOptions parameter.
Note:
Another DbContext (ApplicationDbContext
) also registered in the same class.
Possible solution:
Changing SessionDbContext
the parameter to a generic parameter.
public SessionDbContext(DbContextOptions<SessionDbContext> options) : base(options)
{
}
This is more a question than a bug.
I need to read the value of the cookie, but for some reason it keeps returning the same hashed value.
var cookiePlainText = HttpUtility.UrlDecode(context.Request.Cookies["__Host_Blazor"]);
Is there any way I can get the plain text for that cookie?
Use the new OnCheckSlidingExpiration event to support the "noslide" feature on the ~/bff/user endpoint.
This code should use Last()
, not First()
.
BFF/src/Duende.Bff/BffMiddleware.cs
Lines 54 to 59 in 7233f88
Which version of Duende IdentityServer are you using? 1.0.0-rc.3
Which version of .NET are you using? .NET 6 RC1
A clear and concise description of what the bug is.
I have a Blazor Hosted App and configured BFF as per the documentation. See below a piece of Configure
method from Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapBffManagementEndpoints();
endpoints.MapRemoteBffApiEndpoint("/api", "https://localhost:5010").RequireAccessToken(TokenType.UserOrClient);
endpoints.MapControllers().RequireAuthorization().AsBffApiEndpoint();
endpoints.MapRazorPages();
endpoints.MapFallbackToFile("index.html");
});
When the app is starts never finishes loading, then I checked the Dev Console and got the error above.
Expected behavior
It is my understanding that any API in Blazor Server will required authorization, which is a problem, because there is an API I need to call anonymously from Blazor Client -Program.cs- in order to get a configuration value before the app starts. Is there any way I can exclude that API from being protected?
Which version of Duende IdentityServer are you using?
5.2.2 / BFF rc3
Which version of .NET are you using?
Net 5.0
Describe the bug
If the user is successfully logged in and redirected to main application then the user clears the cookies (on application only) and sign in again. Identity server signs in the user as cookie is available on identity server, then when redirected to application to store the userSession the store throws unique exception
An unhandled exception occurred while processing the request.
SqlException: Cannot insert duplicate key row in object 'dbo.UserSessions' with unique index 'IX_UserSessions_ApplicationName_SessionId'. The duplicate key value is
To Reproduce
services.AddBff(options =>
{
})
.AddEntityFrameworkServerSideSessions(options =>
{
options.UseSqlServer(sqlIdentityConnectionString);
});
Steps to reproduce the behavior.
If the user is successfully logged in and redirected to main application then the user clears the cookies (on application only) and sign in again. Identity server signs in the user as cookie is available on identity server, then when redirected to application to store the userSession the store throws unique exception
Expected behavior
A clear and concise description of what you expected to happen.
It seems dotnet is trying to store the same ticket with same sessionId
Additional context
Add any other context about the problem here.
for same site frontends
OnSigningOut
event and call HttpContext.RevokeUserRefreshTokenAsync
ITokenEndpointService
Which version of Duende IdentityServer are you using?
Which version of .NET are you using?
Describe the bug
BFF-based ASP.NET Core WebApi application with UsePathBase
set responds to the user endpoint with the bff:logout_url
property ignoring the PathBase.
To Reproduce
Startup.cs
modify Startup.Configure
method by adding as the first statementapp.UsePathBase("/api");
/api/bff/user
type=bff:logout_url
{
"type": "bff:logout_url",
"value": "/bff/logout?sid=E18EF260B13B4E494C0CE1D449EFAFCC"
},
Expected behavior
{
"type": "bff:logout_url",
"value": "/api/bff/logout?sid=E18EF260B13B4E494C0CE1D449EFAFCC"
},
Additional context
In production environment the BFF server is running behind a reverse proxy, so the PathBase is setup to properly route the requests from the SPA application to the BFF server. The logout URL is though returned without the PathBase and could not be properly routed. For example, here is the proxy configuration for dev server setup using http-proxy-middleware:
app.use(
'/api',
createProxyMiddleware({
target: 'https://localhost:5001',
secure: false,
headers: {"Connection": "keep-alive"}
})
);
Remove exact sub/sid combo, or remove all sub.
Line 51 in 2cfddbc
When hosting on IIS as an application under a website (www.mydomain.com/myapp1) the cookie will have a Domain value of /myapp1
This violates draft-west-cookie-prefixes-05, and the cookie is rejected under chrome (Version 92.0.4515.107 (Official Build) (64-bit))
I'm using Blazor BFF from the samples repository witch already sets up the authentication for the "local" api on the server project.
// HTTP client configuration
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"));
Is there a way to register another API passing the token? I.e:
builder.Services.AddScoped<UserService>();
builder.Services.AddHttpClient<UserService>("API", client => client.BaseAddress = new Uri(builder.Configuration["API"]!));
I'm aware of the AddHttpMessageHandler
and could create my own Handler to add the AuthenticationHeaderValue
but i'm wondering if there is already something inbuilt?
PS. The API is protected by the same IdentityServer.
I just recently upgraded my Blazor Server Duende.BFF
package from rc3 to v1 and now the build cannot be completed because of the following error. IntelliSense indeed does not show it.
'IEndpointRouteBuilder' does not contain a definition for 'MapRemoteBffApiEndpoint' and no accessible extension method 'MapRemoteBffApiEndpoint' accepting a first argument of type 'IEndpointRouteBuilder' could be found (are you missing a using directive or an assembly reference?)
The package I upgrade to was this and I was looking for release notes but the page is empty.
Which version of Duende IdentityServer are you using?
6.0.0-preview.2
Which version of .NET are you using?
.NET 6 GA
Describe the bug
This method var logout = await this.interaction.GetLogoutContextAsync(logoutId);
not always return yield the PostLogoutRedirectUri
value I expect. For some reason while the session is active, if I click Logout in the Client I'm redirected to the IdentityServer logout page and I do get the appropriate value. However, when the session is expired due to inactivity -set in the cookie- and I'm sent to the IdentityServer logout page this value comes null.
I want to exclude some endpoints from being checked for antiforgery (GET only). Hence, I'm using the following,
services.AddControllers(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
According to the AutoValidateAntiforgeryTokenAuthorizationFilter implementation, GET will be excluded from checking antiforgery. However, after I'm logged on, the following request is a POST and I get a 400. Somehow, when I remove the above filter then app works as usual. The reason I needed to add that filter was because AsBffApiEndpoint()
is requiring antiforgery header in all endpoints, and I need some of them to be bypassed.
Also, in Blazor6 sample code I see MapRemoteBffApiEndpoint(...).RequireAccessToken(TokenType.UserOrClient)
is not being used. Is this the new pattern?
The anti-forgery check that is applied when using YARP makes testing and debugging API's during development somewhat cumbersome. A simple option to disable this would be very helpful. Something along the lines of:
builder.Services.AddBff()
.AddServerSideSessions();
.AddReverseProxy()
.AddTransforms<AccessTokenTransformProvider>()
.WithAccessToken(...)
.WithAntiforgeryCheck(false)
Hi Brock,
In my Blazor Server project in Startup.cs
I set the cookie to expire after 4 min. Once passed that time, I interact with a component that needs to talk to the server and I see nothing is happening. After opening the dev tools I realize there is a 401 result. I added a breakpoint in the component to see the reason for the 401 hoping it'll say something like token expired or so. To my surprise the Reason property is empty. Most importantly, if the token is expired shouldn't bff middleware sent me back to bff/login or do I have to manually set that?
Thanks in advance
Which version of Duende IdentityServer are you using?
Which version of .NET are you using?
.NET 6.0
Describe the bug
Concurrent/parallel requests with a cookie associated with an expired authentication ticket will result in one request removing the expired session from the store and the other throwing a DbUpdateConcurrencyException
. This generates a server error rather than 401 Unauthorized
for the caller.
To Reproduce
The same behaviour can be reproduced in a contrived test harness that:
DeleteUserSessionAsync
via separate DI scopesRepro in test here.
Expected behaviour
No exception thrown
Log output/exception with stacktrace
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected)
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetWithoutPropagationAsync(Int32 commandIndex, RelationalDataReader reader, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Duende.Bff.EntityFramework.UserSessionStore.DeleteUserSessionAsync(String key, CancellationToken cancellationToken) in /_/src/Duende.Bff.EntityFramework/UserSessionStore.cs:line 65
at Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.ReadCookieTicket()
at Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.HandleAuthenticateAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
Additional context
We see the exceptions regularly, but at low rates (circa 1% of total traffic) in a real world environment
Which version of Duende IdentityServer are you using?
5.2.1
Which version of .NET are you using?
.net 5
Describe the bug
Identity Server + BFF + Cookies + AspNetIdentity results in
[18:05:08 Information] Microsoft.AspNetCore.Authorization.DefaultAuthorizationService
Authorization failed. These requirements were not met:
ClaimsAuthorizationRequirement:Claim.Type=scope and Claim.Value is one of the following values: (myapi)
A clear and concise description of what the bug is.
To Reproduce
Steps to reproduce the behavior.
Expected behavior
To authorize users with correct scope
A clear and concise description of what you expected to happen.
Log output/exception with stacktrace
data
Additional context
in startup.cs
.AddOpenIdConnect("oidc", options =>
{
...
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("myapi");
options.Scope.Add("offline_access");
services.AddAuthorization(options =>
{
options.AddPolicy("MyApiScope", policy =>
{
policy.RequireClaim("scope", "myapi");
...
}
}
...
endpoints.MapControllers().RequireAuthorization("MyApiScope").AsBffApiEndpoint();
id server logs:
[18:05:07 Debug] Duende.IdentityServer.Validation.TokenValidator
Token validation success
{"ClientId": null, "ClientName": null, "ValidateLifetime": true, "AccessTokenType": "Jwt", "ExpectedScope": "openid", "TokenHandle": null, "JwtId": "C1B9ED46ACD5E6472DAD50CAF1E91D36", "Claims": {"iss": "https://localhost:5001", "nbf": 1625825107, "iat": 1625825107, "exp": 1625828707, "aud": "https://localhost:5001/resources", "scope": ["openid", "profile", "myapi", "offline_access"], "amr": "pwd", "client_id": "test", "sub": "89fcb5a9-2cdb-490b-838c-37290534a7be", "auth_time": 1625825106, "idp": "local", "sid": "B827C8AA731BA325A5054A486235D455", "jti": "C1B9ED46ACD5E6472DAD50CAF1E91D36"}, "$type": "TokenValidationLog"}
[18:05:07 Debug] Duende.IdentityServer.ResponseHandling.UserInfoResponseGenerator
Creating userinfo response
[18:05:07 Debug] Duende.IdentityServer.ResponseHandling.UserInfoResponseGenerator
Scopes in access token: openid profile myapi offline_access
[18:05:07 Debug] Duende.IdentityServer.EntityFramework.Stores.ResourceStore
Found ["profile", "openid"] identity scopes in database
[18:05:07 Debug] Duende.IdentityServer.ResponseHandling.UserInfoResponseGenerator
Requested claim types: profile preferred_username nickname middle_name given_name family_name name picture website gender birthdate zoneinfo locale updated_at sub
[18:05:07 Information] Duende.IdentityServer.ResponseHandling.UserInfoResponseGenerator
Profile service returned the following claim types: sub name given_name family_name website preferred_username
[18:05:07 Debug] Duende.IdentityServer.Endpoints.UserInfoEndpoint
End userinfo request
We need to come up with a way to prevent an attacker from just redirecting the top window to ~/logout.
Which version of Duende IdentityServer are you using?
Duende.BFF - 1.0.0-rc.1
Which version of .NET are you using?
.NET 5.0.104
Describe the bug
After setup the Blazer WASM project with 3 projects in place (Blazor.Shared, Blazor.Server, and Blazor.Client). I run the app at https://localhost:5002. I can log in via re-direct to https://localhost:5001 to use bob/bob
to log in successfully in the system. Then it does a redirect back into https://localhost:5002. But on this page, I have got the exception:
Fetching user failed. System.Text.Json.JsonException: The JSON value could not be converted to Blazor.Client.Services.HostAuthenticationStateProvider+ClaimRecord
Expected behavior
I expect that after login, the Blazor.Client.Services.HostAuthenticationStateProvider+ClaimRecord
can access into the claims and extract it as well as display it correctly in MainLayout.razor
, that's mean
<AuthorizeView>
<Authorized>
<strong>Hello, @context.User.Identity?.Name!</strong>
<a href="@context.User.FindFirst("bff:logout_url")?.Value">Log out</a>
</Authorized>
<NotAuthorized>
<a href="bff/login">Log in</a>
</NotAuthorized>
</AuthorizeView>
Log output/exception with stack trace
I pressed F12 on the browser and see the output at the console tab:
blazor.webassembly.js:1 warn: Blazor.Client.Services.HostAuthenticationStateProvider[0]
Fetching user failed.
System.Text.Json.JsonException: The JSON value could not be converted to Blazor.Client.Services.HostAuthenticationStateProvider+ClaimRecord. Path: $[9].value | LineNumber: 0 | BytePositionInLine: 439.
---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Converters.StringConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, String& value)
at System.Text.Json.Serialization.Converters.SmallObjectWithParameterizedConstructorConverter`5[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryRead[String](ReadStack& state, Utf8JsonReader& reader, JsonParameterInfo jsonParameterInfo, String& arg)
at System.Text.Json.Serialization.Converters.SmallObjectWithParameterizedConstructorConverter`5[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadAndCacheConstructorArgument(ReadStack& state, Utf8JsonReader& reader, JsonParameterInfo jsonParameterInfo)
at System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].ReadConstructorArgumentsWithContinuation(ReadStack& state, Utf8JsonReader& reader, JsonSerializerOptions options)
at System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, ClaimRecord& value)
at System.Text.Json.Serialization.JsonConverter`1[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, ClaimRecord& value)
at System.Text.Json.Serialization.Converters.IEnumerableDefaultConverter`2[[System.Collections.Generic.List`1[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, List`1& value)
at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.List`1[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, List`1& value)
at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.List`1[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.Serialization.JsonConverter`1[[System.Collections.Generic.List`1[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore[List`1](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore[List`1](JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& state, JsonConverter converterBase)
at System.Text.Json.JsonSerializer.<ReadAsync>d__20`1[[System.Collections.Generic.List`1[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
at System.Net.Http.Json.HttpContentJsonExtensions.<ReadFromJsonAsyncCore>d__3`1[[System.Collections.Generic.List`1[[Blazor.Client.Services.HostAuthenticationStateProvider.ClaimRecord, Blazor.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
at Blazor.Client.Services.HostAuthenticationStateProvider.FetchUser() in D:\github\clean-architecture-dotnet\samples\WebBlazor\Client\Services\HostAuthenticationStateProvider.cs:line 70
Dirty fix it
I look at the Network tab on the browser:
After looked around in the source code of this repo and found out the code for it at https://github.com/DuendeSoftware/BFF/blob/1.0.0-rc.1/src/Duende.Bff/Endpoints/DefaultUserService.cs#L112
I did a dirty hack in my project by overriding the DefaultUserService as
services.AddBff()
.AddServerSideSessions();
services.Replace(ServiceDescriptor.Transient<IUserService, MyDefaultUserService>());
And in the MyDefaultUserService.cs, I converted this expiresInSeconds
into String type
//...
var expiresInSeconds =
authenticateResult.Properties.ExpiresUtc.Value.Subtract(DateTimeOffset.UtcNow).TotalSeconds;
claims.Add(new ClaimRecord(
Constants.ClaimTypes.SessionExpiresIn,
Math.Round(expiresInSeconds).ToString(CultureInfo.InvariantCulture)));
//...
Finally, I run the code again with this little hack, then everything runs well.
Looks at all the claims values should be a string type on the Blazor client-side.
Let me know if that is a bug or not. And if that is a bug, I'm happy to do a fix for this repository. Thank you!
Version:
Duende IdentityServer 5.2.2
Identity server project on .NET 6.0 with Entity Framework and ASP.NET Identity (with 2 factor authentication).
BBF Blazor sample:
When you choose the option 'Remember me' while logging in, you will be redirected back to the client and the claims will be shown. However, when you restart the application again, the login button will appear again.
In the browser console you will see the following result when starting the application:
Sending HTTP request GET https://localhost:5002/bff/user
Failed to load resource: the server responded with a status of 401 ()
After you click on login again, the following error message appears:
SqlException: Cannot insert duplicate key row in object 'dbo.UserSessions' with unique index 'IX_UserSessions_ApplicationName_SessionId'.
The duplicate key value is (Blazor.Server, BC12C0A9300B154697BF1F184E34AC0E).
When you now empty the UserSessions table and restart the application, you will still see the login button, but after you have clicked on it, you will immediately see your claims without logging in again.
In the identity server account options the AllowRememberLogin property is set to true.
Expected result:
When you choose the option 'Remember me' during login and you restart the application, the user would be immediately retrieved and the claims displayed.
I could imagine wanting to enhance the ~/user result data with something app specific. Might be nice to have some sort of support for that.
e.g. to return current user/client access token for manual tests
Which version of Duende IdentityServer are you using?
Duende.BFF 1.0.0-rc.1
Which version of .NET are you using?
.NET 5.0.104
Describe the bug
Actually, I downloaded the release from version 1.0.0-rc.1. Tried to run it, and I have got the exception that we lack UseBff() in this release.
See this: https://github.com/DuendeSoftware/BFF/blob/1.0.0-rc.1/samples/Blazor/Server/Startup.cs#L86
Expected behavior
I expected when I downloaded the examples from Duende.BFF 1.0.0-rc.1, then it should work correctly.
To fix it
I added the UseBff() method as below
app.UseRouting();
app.UseBff(); // <= add this in
app.UseAuthentication();
app.UseAuthorization();
I hope you guys can update the release 1.0.0-rc.1 with that code to make another people can get starting without build errors. Thank you.
Which version of Duende IdentityServer are you using?
5.2.2 / Bff rc3
Which version of .NET are you using?
Net5.0
Describe the bug
[BffApi] Cannot be applied to Actions
A clear and concise description of what the bug is.
It would be helpful if we can apply the attribute to Actions not on the ApiController, as some will have Allow Anonymous and the antiforgery will reject those requests
We are implementing BFF into a large existing project and want to minimize the changes to our clients. Currently we have a number of claims returned such as "given_name", "email" and others. When implementing the BFF solution the user endpoint is changing the claim types of some of claims to types like "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname". This creates an additional breaking change our consuming clients need to address. Ideally we want to not change anything about the data they are used to mapping, especially as its not clear what triggers some claims to be renamed and what they are renamed too (for example strangling we have a "subjectId" claim that gets changed to "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" which doesn't seem the most obvious match.
The current workaround i have implemented (as i am not aware of a better solution at the moment) is a custom claims transformer to replace the claims with the original type names but this seems sub optimal and requires knowing in advance what claims need transforming.
Ideally a BFF option to disable the claim types being changed would be best so it can transparently just pass through the claims as they were received. If not an easier with to map claims without implementing a custom transformer would be helpful.
Hi there
Quick question, are these redundant checks to ensure that the database has returned the correct session keys?
https://github.com/DuendeSoftware/BFF/blob/main/src/Duende.Bff.EntityFramework/UserSessionStore.cs#L82-L90
Which version of Duende IdentityServer are you using?
Version 1.1.3 of Duende.BFF and Duende.BFF.Yarp
Which version of .NET are you using?
.Net 6
Describe the bug
BFFMiddleware does not check to see if it has already been registered and calls Add
on the Items dictionary which throws an error:
Should use context.Items.TryAdd
rather than context.Items.Add
or simply set it via the index.
To Reproduce
Call app.UseBff
more than once at startup.
Expected behavior
The BFFMiddleware should only be registered once and should check if it has already been registered.
Log output/exception with stacktrace
System.ArgumentException: An item with the same key has already been added. Key: Duende.Bff.BffMiddlewareMarker
at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at Microsoft.AspNetCore.Http.ItemsDictionary.System.Collections.Generic.IDictionary<System.Object,System.Object>.Add(Object key, Object value)
at Duende.Bff.Endpoints.BffMiddleware.Invoke(HttpContext context) in /_/src/Duende.Bff/BffMiddleware.cs:line 43
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
at OrchardCore.Diagnostics.DiagnosticsStartupFilter.<>c__DisplayClass3_0.<<Configure>b__1>d.MoveNext()
`
Additional context
Application startup may be reentrant or UseBff may be called multiple times by mistake but it shouldn't crash the app. Even the AuthorizationMiddleware uses something similar:
context.Items[AuthorizationMiddlewareInvokedWithEndpointKey] = AuthorizationMiddlewareWithEndpointInvokedValue;
Add any other context about the problem here.
Which version of Duende IdentityServer are you using?
1.1.0-preview.2
Which version of .NET are you using?
Dotnet 6
Describe the bug
Login fails the second time against IdentityServer after clearing IdentityServer cookies.
To Reproduce
InvalidOperationException: Session id claim value does not match ticket in database for key `046EFCF5449408B36A8CF1C6CE530D8A9F07E7FD708AF9536D547D738383C0E6`
Duende.Bff.ServerSideTicketStore.RenewAsync(string key, AuthenticationTicket ticket) in ServerSideTicketStore.cs
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
Microsoft.AspNetCore.Authentication.AuthenticationService.SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Duende.Bff.Endpoints.BffMiddleware.Invoke(HttpContext context) in BffMiddleware.cs
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Expected behavior
I get logged in.
And this is how the UserSessions table row looks like:
4,my-client,2021-12-16 15:00:00.000000 +00:00,2021-12-30 15:00:00.000000 +00:00,"{""Version"":1,""Payload"":""CfDJ8LTdhSWxBi1Jtx1WRxlftZTky2-KQPz6oFq7ogdlY_lIOLlCrBRIjf5WoN0yYur6IhK0VhKCSDvO_92TGvQe211Wa0f9tSzJ9Pgu2Kt_pBNKhLh_KEz-022Z0yc_sBkrG_FLuJ02Ct_9U2RY4FHG58luJNE1T86AgyiXpuB5vtBnVEDhtSwP4L0rbEBD6K-rv0JQIjP4qg9E9bNGqC_ZL8Xl5rPnWk2tIKN8zneXREUASAJdYI8RMs5HWtrDNjGIHn0Ulx-S517HyfTrQ9FVgBP5EF2BILB2_zu60x-PyY9C2lWTahI4cPBepBJIvaoNjFt0y4XLt4GJc_lj7soRitjKBM2lNTZAKcQdBxQe_peMlsUQcRMP6G4IVBGGkfPAcK1Cg26rmIWqg7c5lNSDGA05PrDghEZwsl6LgF9guHB6KYugwLX5UuNzGl4u0_398KqMRowCCroRxb9vTzk7xM4qnzDWtf-VqRHCpSWxy3_GDhIiswzfS7g4eRowM9stkvp_btpPp5XXqQrXcyjgAJBJFgpZoi0uEBH2g3uzuQkk8CqFEi8X2TDMtYal-3yy8xBRCP_lo62bLJkIoD9lcjvP0HJO1HQ_QO6IG8gaoUuZVHwMN88iLMH8YmDxGVGVQB8YMgRRO4SpGxVR4PMax-FkMGDnSASXolSpft83J4Bx2AxsDlzPoJMxPQyeGibRAqtNXD7Mes12RRx4EES8bNts9HKm8euaDcGddRGIu7Nc3ZYbi86EiO1qY4FMOe0OU6mGQhLhWTBiQF5wcsuiGbxIoOF95iBbfLtdomeKhOxpD9ifGa9SRIgid5XCyGAJv-k1xPOPF6VSOs-hUF-Gm1fW6_U0mAq9eBfsu3fIKNIft00uL4tfYTs_ATd-7yTG5ZWs-jyr18U7qfeMy1_Vwu7q9Um_vO0TwIOaxGr54VWvBVmfVIHovQcH7bmwuNFU4MmRuAGNHLIXRppx_S10y7RqFqOSUhIXiO3jj2Pjq1iq1HrmXb18kS5slkr0bW8NaiA3p26xgtR4MdCo29ai9HbTLIWAti4lMwRfLgASWxYl8Pg5yZcL5D2tUv5k7tNbifREGgBvD1T_8a0FmYL_XnOBhpc9vIX4Rum4Y2rA1WD3EXDo4uNrGMvud5_CH4XYEkatrdhNes3sq6wCTqVfSAg11LX3RadCLg62i6Bkyzub07ei1OS3B_UQi45Jo3zdWOk4L7trBC_RMp5fOG3AJS-3ANJC2nnjDU4AdHoxQ-aKghl5vze6O_wuRGG4zp5DdTRcepWVh1Z02g5nP_PtO2kC5J0HSolDeN3kOXG3RAcgjIygoUKBJ_uDeEayltbGh73huQvWEAf1lMRDWbqI_W-oXvx_hPakKP6ZSmUw_JrP7tzZf9aAwXpOnOy4QERKlvbtv8tfC4lGIhcuxdp1sDEIAYNyjd26S5Ucri62SH56YZJTuxLPzOO2g_RwgWszx264Ex8claYrU4XX0S6ljp6HJztwWYQg44D20FX-aVsgCm40hlZfCpPVfTNO7z7NBzrDBTzA-u3NdF_T1h_kbw7125AlWWaG3Q9QwlElDHXTYsFRe2-hCXaoXsLoDHbpM2LDZNESd69KYrPznunuqYtj3ElGgqDoVJ6fbGK1ngj75rcV9VKHXsYr02xhnutondFUDw18HeVKU35FgsZdD8LYa3OiyxSPMf3mEGim2YuUxgBwKuHhL924MoWEe8x6GMuN4FErtraOlhU1OBoUSRQtv1wO_Rl0eWLdjP3KZPyB2yafu5opYgY7QjP9PU7ZPCecbM8jmQ4CDr6lqWmlMdBp_-ojGh0JB5pF3kn-RRH6kWG9dA2hi_RIt7H-Qo0QTKcixZbEWvKw5Mg0ePKoLCCXp4lG-57OM9ZOBQEAqCwXWjHtPc6-eLBXkSlB_MSmX9KTDAtTP9W23K3LLSHT3m5QQaXOXhXM7XKA5xjezlSk9fGeCfQO2PBYwR4ms0Za42O5UajVcuYw4hVUmtoKdeskg7H7WRfCIgRDcnpNtzSiJU6mvsLgoqAnstl_qTFFC-ol-zwVAZNgnPKc8l9kgIy8nA8FFxRzL6_So0SGs_XkvaW4knlKu6kgDjBqmEhmej7SlEHIm8Wao-w3KVL0-1iG8B6O1zF1W0Fa0qaVTIoG6ltW6RMrdxgqT5bbmm-9iUO-ExKYWVVYnSmLKZ9cRiP7AWl8cUekyBNYhILp1RKUoqN_sPYHb_PSKkaJbPUHJv1trNx-L1a3OzFCyZErv_O0e0LL3E7WLnLKDNXkkWzR8GjDZvMZwCS3fmApWh74X5W3gZRbZLqlwcN9kfEzx4Ik0my_M-i301L9AtOoFycPz5ETgpy6Yrrw0Hh-zcCh9UDM2ZgvYxEqwqZmxvswCGujV24jnWh-nh7EL8SpcAKt8LMp0rM3408ao_yBmuyj5YOfhAftGZLToHMawnWeQn0WXLdHlF0RCANDZ9lFxfcJTRxrVPLjlWtg6hUHjASyGZ_fUCTEMFRUi2G8120E9ugMY4_-k_B79TCzbeEQZYLeTtdfeCc3sEVeurIZJOqBOrdeTOeMcC8F3CNFAeIMaIbi-ZGNQ3fN7uhtOWJ6awtAytn-58upX0xfW1b_ndMNgAjtTmBXwVK0SWEAKHj6G3gkYGdf1l_LcomJloKJbE81FL3y0vVv8Teh7rJlWOaOuwjFT-2p7Bl0jWgPghqqf_lqv0Abni4JOJtcW7mfYGGcmW2l04wv8mtKTjFQH7_tYZY6llkvFkx50XPcLwRb4Yg7p543bdPJg42h7uKdY88uyxY8k5I6_mzFJRAwefwWc217md4J6vqaOqEoUrJww1bKqFF14X1ffRMziKCH1mcz1gJ5frul9goLXttJsJZIJH8YPezf_tgCKPejKwvCpBTzSZXQhuKLmHB8EhegcMjrE1T6xy48kKZlGbt3hIBfj1rlLxXy5zWQXKRMj0mERab7IBl-lMxQclcNcv_uAEl2d6v9aKh9RWvSsGj8Tpoiv_O5yXqezUfnvbeXWcOsAJgh9ZxZhl0gMINKVpwajMas3Cl2IZYuNyqrPLGpNhyusJPQ1Ga8oqALJ9TY9NRrGUP-F_iAjKI5I9xzhGuSHdDIyUefPNPxFkMofT4SYh_8kUKeHKFhXYV7pwZZQnMpPxwv7EccISWpEbG6JDD61JOXWNgdxUSl_X0epy-BGPMJUapMqHnlYm7lgCKDhxHXco39JcAthzvp1Gxegvs931ls9DcNJs6SNg1B6Sn-B9KEAKZGBksdbeyGYX0FegrfbS7boKjmB-9E-_uZ3UoV82HTGn9VJRHWSnlf4Rvu0rO_PlUcu9lQ8xuz22zaYZyyxsMF63PhQm_JVfFR3cqWGdsj0KPbY1E94H0oWNLVZeSVK-IZlGrWhnEAn3IblzwaAC4WTmjMOSN_A8HHHnlehVGaNP6XfNfzDkgOv9YH9mYKNCmig4R-SI1l2h6afwSeBOOhqp31Ct8Z4gigxu2xfngJa-C90uoN4e4foNm1Vi_029sEWir2t145swgsxTu32Q7Xl8BAPxtbJvszOtWu9erUlqivp-GO1BCq1UPc6ltViglrn786zPcbDwohbe_YNK36KTSWWhBlbcTCHd6-VpXtMreo7iG6qwW5oZsH6BzFiFSHdZ8cFFten0Jqenv2BBt1xk-q4zA05yxBZbTFQozUaLnShUmYjh3xrZCOPjH5fEI2BfWoq2IwqnRcvyrUZWl3bly_XWAgNoe9kimFlGiqoBFyGaE5Qf48LOFBtoDgGCcNZS_ZM7b9ChInaMqYIml6DF9f35oV1aDfxh7vwNOjhNFvf3NuI48e7UtwJKl9GmUA_NOQeC0T5rsm8MF__kPOb2wfOR807jQ1myk26ZCpY-YuEQ8I4EiLfVeSuFUNReShcDgFKupTbBmY-rTddphbICkDD1NR3Xu0g4JkxKQ-6_06QWb2TRSp_VVW134EpAN88XYVrf8IvHZ5iikFYJI8Ev44Iemt98GXVEN6Ioc1Nu627paqzV3bNsVrY36s5iqPpga0YIbAY_tJCtJGi3BStWl0dHRb4bq4D1hPrybv4OA5cbrnoB5w4mk6jee4cCUmylfXhzUtuVpGha5d5Khu4uY9vHD0HhEz73PpwAABbxdPX190I3GG0Wo-pRViA-M6-UmIchDKD4DqhdK7tiCQ8OJMBPMBxkdcl67HJsd-HggRsUvXfSGNgX-Ldo68pG9Uj_W4Tb7EBIypMEZpO5odpS67FfcsEZQriIgEbrFv2EHkAqUJAp0x1Dl-uyp0N9Zdz70RwB9rCwzfTxk09ZaSYiBArQgisC3hnrEph_MJjnnm1eRlI1qZ9qmMSxDghHHOav3Y5Y-V-epPwioj3n5Gw8mZq_CFc33N0Xq-xnznOZJz41gfc3-BkfeVKugDaB-Cekl0Q693c187lIkAz4kD63Qj0-zpQVMAwUVFPhvVXyHMK48bJJtgWwqhbchDBfNiQPgTFqZo7zL1sDLkxOu1_MkWFoeRmXm9z5rAP0-WTe0HMww3dzLzebrmcQtJhQ""}",046EFCF5449408B36A8CF1C6CE530D8A9F07E7FD708AF9536D547D738383C0E6,8d212e57-75d1-4bd6-9890-09d39178159b,0AE42A193FC1E997196A8D675078A833,2021-12-16 15:00:00.000000 +00:00
BFF for SPA scenario is more or less clear. Thanks for that.
How about the mobile apps (web based, native or xamarin)? Is it applicable and how?
Thanks,
Lucian
Rather than having the code in BffManagementEndoints as static methods, we might consider having these simply call a service in DI to do the processing (like we do for MapBackchannelLogout). This might make #3 easier as well.
For session mgmt
Our 302 => 401 clears the Location header, but the Set-Cookie for nonce and correlation cookies from the OIDC handler are allowed thru and if too many pile up the browser gets bricked, due to headers to large.
I have a Blazor app and for some reason there are 2 endpoinst failing with a 401 and when I checked the event logs I see this.
Category: Duende.Bff.Endpoints.BffMiddleware
EventId: 2
SpanId: 6d3fc7c7594838cc
TraceId: b9e4542533b256b89b48a98ea9fad13e
ParentId: 0000000000000000
RequestId: 80000020-0002-c800-b63f-84710c7967bb
RequestPath: /myapipath/
Anti-forgery validation failed. local path: '/myapipath/'
In Startup.cs
I have this
services.AddAuthentication(options =>
{
//hidden for brevity
})
.AddCookie(openIdSettings.OpenIdBrowserUXDefaultScheme, options =>
{
options.Cookie.Name = "__Host_Blazor";
options.Cookie.SameSite = SameSiteMode.Strict;
})
.AddOpenIdConnect(openIdSettings.OpenIdBrowserUXDefaultChallengeScheme, options =>
{
//hidden for brevity
});
Any suggestion as to how this can be fixed?
Thanks beforehand.
Context: DuendeSoftware/Support#90
With this fix the RequireAntiForgeryCheck: false stopped working for the local API when set at the controller action level attribute like this:
// GET productapi/v1/image/5
[BffApi(false)]
[HttpGet("{id:length(24)}")]
public Task<ActionResult> Get(string id) => (
It now requires the anti-forgery header for this action and returns 401. If rollback to 1.2.1 it works as expected.
Originally posted by @dgrozenok in #102 (comment)
Hello,
I am using the BFF .net 6 React sample here https://github.com/DuendeSoftware/Samples/blob/main/IdentityServer/v6/BFF/ReactBffSample/src/FrontendHost/Program.cs
Local API and Remote API each one works fine when enabled alone
But when i want to use both (same endpoint i want them to be redirected to my local controller, and other just a proxy to other api ) it dont work, all routes are redirected to local controller or not found error.
// local APIs
endpoints.MapControllers()
.RequireAuthorization()
.AsBffApiEndpoint();
// login, logout, user, backchannel logout...
endpoints.MapBffManagementEndpoints();
// proxy endpoint for cross-site APIs
// all calls to /api/* will be forwarded to the remote API
// user or client access token will be attached in API call
// user access token will be managed automatically using the refresh token
endpoints.MapRemoteBffApiEndpoint("/api", "https://localhost:5010")
.RequireAccessToken(TokenType.UserOrClient);
thank you for your help.
Into its own assembly/library.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.