Content displayed during asynchronous authentication in ASP.NET Blazor

<AuthorizeView>
    <Authorized>
        <h1>Hello, @context.User.Identity.Name!</h1>
        <p>You can only see this content if you're authenticated.</p>
    </Authorized>
    <Authorizing>
        <h1>Authentication in progress</h1>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

This approach isn’t normally applicable to Blazor Server apps. Blazor Server apps know the authentication state as soon as the state is established. Authorizing content can be provided in a Blazor Server app’s AuthorizeView component, but the content is never displayed.

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-6.0#content-displayed-during-asynchronous-authentication

Role-based and policy-based authorization in ASP.NET Blazor

The AuthorizeView component supports role-based or policy-based authorization.

For role-based authorization, use the Roles parameter:

<AuthorizeView Roles="admin, superuser">
    <p>You can only see this if you're an admin or superuser.</p>
</AuthorizeView>

For policy-based authorization, use the Policy parameter:

<AuthorizeView Policy="content-editor">
    <p>You can only see this if you satisfy the "content-editor" policy.</p>
</AuthorizeView>

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-6.0#role-based-and-policy-based-authorization

AuthorizeView component in ASP.NET Blazor

The AuthorizeView component selectively displays UI content depending on whether the user is authorized. This approach is useful when you only need to display data for the user and don’t need to use the user’s identity in procedural logic.

The component exposes a context variable of type AuthenticationState, which you can use to access information about the signed-in user:

<AuthorizeView>
    <h1>Hello, @context.User.Identity.Name!</h1>
    <p>You can only see this content if you're authenticated.</p>
</AuthorizeView>

You can also supply different content for display if the user isn’t authorized:

<AuthorizeView>
    <Authorized>
        <h1>Hello, @context.User.Identity.Name!</h1>
        <p>You can only see this content if you're authorized.</p>
        <button @onclick="SecureMethod">Authorized Only Button</button>
    </Authorized>
    <NotAuthorized>
        <h1>Authentication Failure!</h1>
        <p>You're not signed in.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void SecureMethod() { ... }
}

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-6.0#authorizeview-component

Expose the authentication state as a cascading parameter in ASP.NET Blazor

@page "/"

<button @onclick="LogUsername">Log username</button>

<p>@authMessage</p>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private string authMessage;

    private async Task LogUsername()
    {
        var authState = await authenticationStateTask;
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

Set up the Task<AuthenticationState> cascading parameter using the AuthorizeRouteView and CascadingAuthenticationState components in the App component (App.razor):

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" 
                DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

In a Blazor WebAssembly App, add services for options and authorization to Program.cs:

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

In a Blazor Server app, services for options and authorization are already present, so no further action is required.

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-6.0#expose-the-authentication-state-as-a-cascading-parameter

Custom AuthenticationStateProvider in ASP.NET Blazor

public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        // user is anonymous
        // ClaimsIdentity claimsIdentity = new ClaimsIdentity();
        
        // user is authenticated
        ClaimsIdentity claimsIdentity = new ClaimsIdentity("test");
        claimsIdentity.AddClaim(new Claim("AccessUserPages","true"));

        ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
        AuthenticationState authenticationState = new AuthenticationState(claimsPrincipal);
        return await Task.FromResult(authenticationState);
    }
}

Program.cs

builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();

Index,razor

@page "/"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<div>
    Authentication : @authMessage
</div>

<div>
    <h5>Claims</h5>
    @if (claims.Any())
    {
        <ul>
            @foreach (var claim in claims)
            {
                <li>@claim.Type : @claim.Value</li>
            }
        </ul>   
    }
</div>

@code
{
    private string authMessage;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();


    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            authMessage = "user is authenticated";
            claims = user.Claims;
        }
        else
        {
            authMessage = "user is not authenticated";
        }
    }
}

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-6.0#authenticationstateprovider-service

Configure ASP.NET Core Data Protection to Persist Keys To DbContext

PersistKeysToDbContext

dotnet add package Microsoft.AspNetCore.DataProtection.EntityFrameworkCore

Add using Microsoft.AspNetCore.DataProtection; to Startup.cs

builder.Services.AddDataProtection()
    .PersistKeysToDbContext<SampleDbContext>();

The preceding code stores the keys in the configured database. The database context being used must implement IDataProtectionKeyContextIDataProtectionKeyContext exposes the property DataProtectionKeys

public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = null!;

References
https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-6.0
https://stackoverflow.com/questions/57216907/how-to-fix-idataprotectionbuilder-does-not-contain-a-definition-for-persist

Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core

Antiforgery middleware is added to the Dependency injection container when one of the following APIs is called in Program.cs:

The FormTagHelper injects antiforgery tokens into HTML form elements. The following markup in a Razor file automatically generates antiforgery tokens:

<form method="post">
    <!-- ... -->
</form>

Explicitly add an antiforgery token to a <form> element without using Tag Helpers with the HTML helper @Html.AntiForgeryToken:

<form asp-action="Index" asp-controller="Home" method="post">
    @Html.AntiForgeryToken()

    <!-- ... -->
</form>

In each of the preceding cases, ASP.NET Core adds a hidden form field similar to the following example:

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">

Configure antiforgery with AntiforgeryOptions

Customize AntiforgeryOptions in Program.cs:

builder.Services.AddAntiforgery(options =>
{
    // Set Cookie properties using CookieBuilder properties†.
    options.FormFieldName = "AntiforgeryFieldname";
    options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
    options.SuppressXFrameOptionsHeader = false;
});

References
https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-6.0
https://stackoverflow.com/questions/51248053/antiforgery-cookie-in-asp-net-core-2-0

Turn off Wireless power management permanently in Ubuntu 22.04

sudo nano /etc/NetworkManager/conf.d/default-wifi-powersave-on.conf

And change wifi.powersave to 2

or

sudo sed -i 's/3/2/' /etc/NetworkManager/conf.d/*

Possible values for the wifi.powersave field are:

NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (0): use the default value
NM_SETTING_WIRELESS_POWERSAVE_IGNORE  (1): don't touch existing setting
NM_SETTING_WIRELESS_POWERSAVE_DISABLE (2): disable powersave
NM_SETTING_WIRELESS_POWERSAVE_ENABLE  (3): enable powersave

References
https://askubuntu.com/questions/1403773/22-04-wifi-keeps-disconnecting-for-a-few-seconds-frequently
https://unix.stackexchange.com/questions/269661/how-to-turn-off-wireless-power-management-permanently