Authentication

Introduction

Most web applications require some form of authentication. Spark provides this out of the box by using .NET’s authentication with it’s own custom cookie provider.

Spark also builds the login, logout, register and profile edit pages for you. Feel free to customize their look and feel how you see fit.

Configuration

Authentication settings can be configured in your appsettings.json file.

{
    "Spark": {
        "Auth": {
            "LoginPath": "/login",
            "LogoutPath": "/logout",
            "AccessDeniedPath": "/access-denied",
            "CookieExpirationDays": 5,
            "EmailConfirmation": false,
            "Password": {
                "MinimumLength": 8,
                "MaximumLength": 32,
                "RequireDigit": true,
                "RequireUppercase": true,
                "RequireNonAlphanumeric": true
            }
        },
    }
}

Setup

Spark’s authentication is setup for you in AppServiceRegistration.AddAppServices().

services.AddAuthentication<IAuthValidator>(config);

The implementation for IAuthValidator is the Application.Services.Auth.SparkAuthValidator.cs class.

This service comes with 1 method that is called behind the scenes whenever an authentication check needs to occur, ValidateAsync().

User Data

The User Model

Every Spark app comes with a User.cs class in the Application/Models directory. This acts as your schema for your users table and also the class that is used during authentication.

public class User : BaseModel
{
    public User()
    {
        UserRoles = new HashSet<UserRole>();
    }

    public int Id { get; set; }

    public string Name { get; set; }

    public string Email { get; set; }

    public string Password { get; set; }

    public string? RememberToken { get; set; }

    public DateTime? EmailVerifiedAt { get; set; }

    public virtual ICollection<UserRole> UserRoles { get; set; }

    [NotMapped]
    public bool IsAuthenticated { get; set; }
}

Users also have Roles tied to them for authorization. You can read more about that on the Authorization page.

Accessing User Data

Spark comes with out of the box methods to make it easy to query the authenticated User’s model.

The Application/Services/Auth/AuthService.cs class comes with a GetAuthenticatedUser(ClaimsPrincipal User) method. This will return the User model if the person logged in or null otherwise.

The AuthService can be dependency injected in your services or Razor components.

@page "/"
@inject AuthService AuthService

@code {
	[CascadingParameter] HttpContext Context { get; set; } = default!;

    protected override void OnInitialized()
    {
        _developers = await DeveloperService.GetAll();
        var user = AuthService.GetAuthenticatedUser(Context.User);
    }
}

...

Protecting Routes & Pages

If you have routes in your app you only want logged in users to see, use the Authorize attribute.

@page "/dashboard"
@attribute [Authorize]
<section class="max-w-5xl mx-auto py-28 min-h-screen px-4">
    <article>
        <h1 class="text-2xl font-bold text-gray-800">
            User Dashboard
        </h1>
    </article>
</section>

Protecting parts of a page

Sometimes you need to display different content on a page depending on if a user is authenticated or not. For example, showing a login button or a users profile name in the nav bar.

A cascading parameter called PageState is provided to your Razor components to help you do this.

@code {
	[CascadingParameter]
    public PageState PageState { get; set; } = default!;
}
<div>
    @if (PageState.User.IsAuthenticated)
    {
        <div>@PageState.User.Name</div>
    }
    else
    {
        <a href="/login">Login</a>
    }
</div>

Custom Authentication

You may a different authentication implementation than the one Spark provides out of the box.

You can swap to your own implementation fairly easily.

First, you will need to add your own auth registration. You can replace Spark’s auth registration in Application/Startup/AuthServiceRegistration.cs with your own.

Then create your own implementation of the IAuthValidator interface. You can see Spark’s implementation of this interface as a reference at Application/Services/Auth/SparkAuthValidator.cs.

Finally, register your IAuthValidator implementation in the AddCustomServices() method in Application/Startup/AppServiceRegistration.cs.