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

Update Blazor Samples For .NET 8 #142

Open
josephdecock opened this issue Aug 18, 2023 · 12 comments
Open

Update Blazor Samples For .NET 8 #142

josephdecock opened this issue Aug 18, 2023 · 12 comments
Assignees
Milestone

Comments

@josephdecock
Copy link
Member

No description provided.

@josephdecock josephdecock added this to the 7.0 milestone Aug 18, 2023
@josephdecock josephdecock self-assigned this Aug 18, 2023
@b1tzer0
Copy link

b1tzer0 commented Oct 9, 2023

I second this, I have been looking all over the web trying to find an example of how to properly implement SSR with Auto Mode (SignalR and WASM). I have tried various configurations with BFF and Server Side but have not had much luck. If there is a working example out there that would be greatly that we could repost or if one could be added to this repo, that would be great help in trying to solve my problem.

@lnaie
Copy link

lnaie commented Nov 27, 2023

It needs a BlazorSSR example with Asp.Net Core Identity, so to have the default user management solution handled.

@leastprivilege
Copy link
Member

What we need is a Blazor Web App sample that uses BFF for coordinating authentication and API calls that works for all render modes.

@hugh-maaskant
Copy link

If possible, an example (or explanation somewhere) of how to use it with SignalR from a Blazor WASM page/component would be very welcome.

@lnaie
Copy link

lnaie commented Nov 28, 2023

What we need is a Blazor Web App sample that uses BFF for coordinating authentication and API calls that works for all render modes.

One sample that covers all rendering modes is ideal (https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?view=aspnetcore-8.0). I was thinking that it would help, for now, to target the Interactive WebAssembly, which renders on the server, as well on the client.

@Liandrel
Copy link

Liandrel commented May 21, 2024

Is there any approximate date when we can expect the release of the updated samples?

@b1tzer0
Copy link

b1tzer0 commented May 21, 2024

@Liandrel , I managed to get this working with an app I am working on. While I can't show source, I can point you to the same location where I found my starting point. One caveat is that while it does work; it is not integrated into Duende at this time. https://github.com/josephdecock/InteractiveBlazorAuth/tree/main

Hope this helps

@ThomasBarnekow
Copy link

@b1tzer0, did you get "all of it" working based on that InteractiveBlazorAuth example? Based on your post, I also tried it out and run into issues, some of which are mentioned further above. For example:

@josephdecock, I would essentially like to set up a new ASP.NET 8.0 Blazor Web App with Interactive WebAssembly (avoiding SignalR) plus a Web API and then add IdentityServer-based authentication and authorization. While your InteractiveBlazorAuth example looks like a good starting point (which does more than what I need because it demonstrates render modes that I likely don't need), it has the issues mentioned above. So, unfortunately, there is currently no adequate, working example that demonstrates the mere basics.

@b1tzer0
Copy link

b1tzer0 commented Jun 25, 2024

@ThomasBarnekow, I can confirm the /bff/user appears to work in both WASM and Blazor Server (SignalR)
image

Here you can see the only websocket is the browser refresh:
image

Logout is hit and miss, while in debug it does in fact take me to the logout page, but if I am running outside of debug mode the page just refreshes. Looking at it, I feel like I messed that up myself, when I go directly to the URL it works with no problem.

This is the code I am using for my bff authentication state provider.

public class BffAuthenticationStateProvider : AuthenticationStateProvider
{
    private static readonly TimeSpan UserCacheRefreshInterval
    = TimeSpan.FromSeconds(60);

    private readonly HttpClient _client;
    private readonly ILogger<BffAuthenticationStateProvider> _logger;

    private DateTimeOffset _userLastCheck
        = DateTimeOffset.FromUnixTimeSeconds(0);
    private ClaimsPrincipal _cachedUser
        = new ClaimsPrincipal(new ClaimsIdentity());

    public BffAuthenticationStateProvider(
        HttpClient client,
        ILogger<BffAuthenticationStateProvider> logger)
    {
        _client = client;
        _logger = logger;
    }

    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var user = await GetUser();
        var state = new AuthenticationState(user);

        // checks periodically for a session state change and fires event
        // this causes a round trip to the server
        // adjust the period accordingly if that feature is needed
        if (user.Identity.IsAuthenticated)
        {
            _logger.LogInformation("starting background check..");
            Timer? timer = null;

            timer = new Timer(async _ =>
            {
                var currentUser = await GetUser(false);
                if (currentUser.Identity.IsAuthenticated == false)
                {
                    _logger.LogInformation("user logged out");
                    NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(currentUser)));
                    await timer.DisposeAsync();
                }
            }, null, 1000, 5000);
        }

        return state;
    }

    private async ValueTask<ClaimsPrincipal> GetUser(bool useCache = true)
    {
        var now = DateTimeOffset.Now;
        if (useCache && now < _userLastCheck + UserCacheRefreshInterval)
        {
            _logger.LogDebug("Taking user from cache");
            return _cachedUser;
        }

        _logger.LogDebug("Fetching user");
        _cachedUser = await FetchUser();
        _userLastCheck = now;

        return _cachedUser;
    }

    record ClaimRecord(string Type, object Value);

    private async Task<ClaimsPrincipal> FetchUser()
    {
        try
        {
            _logger.LogInformation("Fetching user information.");
            var response = await _client.GetAsync("bff/user?slide=false");

            if (response.StatusCode == HttpStatusCode.OK)
            {
                var claims = await response.Content.ReadFromJsonAsync<List<ClaimRecord>>();

                var identity = new ClaimsIdentity(
                    nameof(BffAuthenticationStateProvider),
                    "name",
                    "role");

                foreach (var claim in claims)
                {
                    identity.AddClaim(new Claim(claim.Type, claim.Value.ToString()));
                }

                return new ClaimsPrincipal(identity);
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Fetching user failed.");
        }

        return new ClaimsPrincipal(new ClaimsIdentity());
    }
}

Here is where I wire it up in my .Client startup file

builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<AuthenticationStateProvider, BffAuthenticationStateProvider>();

// HTTP client configuration
builder.Services.AddTransient<AntiforgeryHandler>();

builder.Services.AddHttpClient("HostUri", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<AntiforgeryHandler>();

@thesilverbadger
Copy link

Is there an update to this issue? We've got an existing set of Blazor WASM applications that are using BFF, and we want to move across to the new rendering modes in .NET 8/9. I can't see any updated documentation unfortunately.

@VictorioBerra
Copy link

Second this, looking for updated samples.

@b1tzer0
Copy link

b1tzer0 commented Oct 4, 2024

I did notice some updated samples in the BFF repo in the tag for release 3 preview 2
https://github.com/DuendeSoftware/BFF/tree/3.0.0-preview.2/samples/Blazor

Not sure if it is what you are looking for though. I didn't notice anything that was glaring at me saying this is what you want for auto.

Sorry for the short response, on my mobile device

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

No branches or pull requests

10 participants