Skip to content

Instantly share code, notes, and snippets.

View SteveSandersonMS's full-sized avatar

Steve Sanderson SteveSandersonMS

View GitHub Profile
public class RevalidatingAuthenticationStateProvider : AuthenticationStateProvider, IDisposable
{
private static TimeSpan RefreshInterval = TimeSpan.FromMinutes(30);
private readonly CancellationTokenSource _cts;
private ClaimsPrincipal _currentUser;
public RevalidatingAuthenticationStateProvider(SignInManager<IdentityUser> signInManager)
{
_cts = new CancellationTokenSource();
@SteveSandersonMS
SteveSandersonMS / blazor-auth.md
Created June 11, 2019 10:49
Blazor authentication and authorization

Authentication and Authorization

Authentication means determining who a particular user is. Authorization means applying rules about what they can do. Blazor contains features for handling both aspects of this.

It worth remembering how the overall goals differ between server-side Blazor and client-side Blazor:

  • Server-side Blazor applications run on the server. As such, correctly-implemented authorization checks are both how you determine which UI options to show (e.g., which menu entries are available to a certain user) and where you actually enforce access rules.
  • Client-side Blazor applications run on the client. As such, authorization is only used as a way of determining what UI options to show (e.g., which menu entries). The actual enforcement of authorization rules must be implemented on whatever backend server your application operates on, since any client-side checks can be modified or bypassed.

Authentication-enabled templates for Server-Side Blazor

@SteveSandersonMS
SteveSandersonMS / sequence-number.md
Last active November 28, 2023 20:28
Why sequence numbers should relate to code line numbers, not execution order

Why sequence numbers should relate to code line numbers, not execution order

Or in other words, why you should hard-code sequence numbers, and not generate them programmatically.

Unlike .jsx files, .razor/.cshtml files are always compiled. This is potentially a great advantage for .razor, because we can use the compile step to inject information that makes things better or faster at runtime.

A key example of this are sequence numbers. These indicate to the runtime which outputs came from which distinct and ordered lines of code. The runtime uses this information to generate efficient tree diffs in linear time, which is far faster than is normally possible for a general tree diff algorithm.

Example

@SteveSandersonMS
SteveSandersonMS / auth.md
Last active September 28, 2022 19:30
Authentication and Authorization

This document describes options and proposals for #4048.

Overall goals

Principles:

  • In Razor Components, enable customers to use as much of ASP.NET Core's existing authentication/authorization/identity feature set as possible. Minimize the invention of new stuff; maximize orthogonality.
  • Provide a programming model that can be consistent across Razor Components (server-side) and Blazor (client-side), so components that use authorization can still be portable across the two, even if app-level Startup.cs logic is completely different for the two runtime environments.

The Razor Components auth feature set will be mostly the same as for MVC/Pages. We'll get the same long-tail features such as integration with 3rd-party social logins, 2FA, etc. The Razor Components template will support the same four auth options during project creation, and the "Scaffold Identity" feature will be usable on existing Razor Components projects.

@SteveSandersonMS
SteveSandersonMS / ITab.cs
Created November 15, 2018 11:33
Blazor tab example
using Microsoft.AspNetCore.Blazor;
public interface ITab
{
RenderFragment ChildContent { get; }
}

Cross-component interactions

Blazor should make it easy to build all the classic high-level UI widgets, such as forms, grids, tabs, dialogs, and so on. One of the big technical pieces needed for this is templated components, and since 0.6.0 we have strong support for that. Another necessary bit of infrastructure is a mechanism for components to collaborate based on ancestor/descendant relationships. For example:

  • In a Form component, you'd want nested Input components to be able to affect the form's validation on submit.
  • In a TabSet component, you'd want the TabSet to discover nested Tab components so it knows what tab titles to display, and to render only the active one (either by TabSet choosing which child to render, or by Tab knowing whether it's currently the active one).
  • In a NavBar component, you'd want a HamburgerButton component to be able to send a "toggle expansion" signal to the NavBar.

As of today, all these are possible but only through manual wiring. For exa

@SteveSandersonMS
SteveSandersonMS / BlazorForm.cshtml
Created September 21, 2018 16:29
Validation mockup A: explicit <ValidateXyz> components that take a Func<T>
@* Unfortunately this has to be named BlazorForm, not Form, because we can't differentiate based on casing *@
<form onsubmit=@HandleSubmit>
@ChildContent(_context)
</form>
@functions {
private FormContext _context = new FormContext();
[Parameter] protected RenderFragment<FormContext> ChildContent { get; set; }
[Parameter] protected Action<FormContext> OnSubmit { get; set; }

Blazor: Adding a custom linker config

In your csproj file, add the following:

  <Target Name="AddCustomLinkerDescriptor" AfterTargets="_CollectBlazorLinkerDescriptors">
    <ItemGroup>
      <BlazorLinkerDescriptor Include="CustomLinkerConfig.xml" />
    </ItemGroup>
 
class TaskResultUtil
{
private static ConcurrentDictionary<Type, ITaskResultGetter> _cachedGetters = new ConcurrentDictionary<Type, ITaskResultGetter>();
private interface ITaskResultGetter
{
object GetResult(Task task);
}
private class TaskResultGetter<T> : ITaskResultGetter
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;