YG.Authentication 2.2.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package YG.Authentication --version 2.2.1
                    
NuGet\Install-Package YG.Authentication -Version 2.2.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="YG.Authentication" Version="2.2.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="YG.Authentication" Version="2.2.1" />
                    
Directory.Packages.props
<PackageReference Include="YG.Authentication" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add YG.Authentication --version 2.2.1
                    
#r "nuget: YG.Authentication, 2.2.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package YG.Authentication@2.2.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=YG.Authentication&version=2.2.1
                    
Install as a Cake Addin
#tool nuget:?package=YG.Authentication&version=2.2.1
                    
Install as a Cake Tool

YGAuthentication

YGAuthentication provides authentication and authorization for Blazor applications using either a local JWT-based identity system or OpenID Connect (OIDC) Single Sign-On.

Features:

Local JWT Authentication Authentication and authorization for Blazor applications using JWT claims. Works with or without a WebAPI. BCrypt password hashing support. Login through WebAPI: api/loginEncr (BCrypt) api/login (plain text) Direct authentication without a WebAPI: _authEncr.Authenticate(...) _auth.Authenticate(...) Built-in authorization support for protected pages. WebAPI endpoints: api/login api/auth

OpenID Connect (OIDC) Single Sign-On

Starting July 2026, Authentication is renamed to YG.Authentication, and it also supports OpenID Connect providers such as Auth0, Microsoft Entra ID (Azure AD), Okta, Keycloak, and other standards-compliant identity providers.

Simply add your OIDC configuration to appsettings.json and register the services.

YG.Authentication Service Registration:

builder.Services.AddYGOpenIdConnect(config); 
builder.Services.AddScoped<IYGOpenIdConnectEventHandler, YourCustomOpenIdConnectUserHandler>();

Middleware:

app.MapYGOpenIdConnectEndpoints(config);

Hosting Your Own Identity Provider

You can use the built-in local JWT identity system or integrate with an external OpenID Connect provider.

If you need help getting started, feel free to reach out:

Email: cs@yogigrantz.com CodeMentor: Yogi Grantz

Installation

Include this package in the project file

!!! Be sure to follow the working POC example [YGEnvAuthenticationTestApp]. The source code includes POC Blazor Web app.

This is an advanced library. It requires special IoC registrations in program.cs, and the login page requires a bunch of usings and injects to include the necessary libraries and retrieve instances of DI objects from IoC Container. The sample project YGEnvAuthenticationTestApp contains 4 sample login pages:

Login 1: Direct authentication without encrypted password Login 2: Direct authentication with encrypted password Login 3: WebAPI authentication without encrypted password Login 4: WebAPI authentication with encrypted password

Usage

.csproj file:

<PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>disable</ImplicitUsings> </PropertyGroup>

<ItemGroup> <PackageReference Include="Blazored.LocalStorage" Version="4.5.0" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="YG.Authentication" Version="2.2.0" /> </ItemGroup>

AppSettings.json for custom jwt:

{
  "AuthName": "AnyNameOfYourChoice",
  "LoginPage":  "/Login"
}

With OpenIDC, these are required:

  "YGAuthentication": {
    "OpenIdConnect": {
      "Provider": "Auth0",

      "Domain": "yourtenant.us.auth0.com",

      "ClientId": "xxxxxxxx",
      "ClientSecret": "xxxxxxxx",

      "LoginPath": "/login?redirectUri=/",
      "LogoutPath": "/logout",

      "CallbackPath": "/signin-oidc",
      "SignedOutCallbackPath": "/signout-callback-oidc",
      "SignedOutRedirectUri": "/",

      "ClaimsIssuer": "Auth0",

      "DefaultRedirectPath": "/",
      "CookieExpireDays": 2
    }
  },

program.cs:

using BlazorApp3.Components;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components;
using YGAuthentication.ActionFilters;
using YGAuthentication.Jwt;
using YGAuthentication.States;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();

IConfiguration config = builder.Configuration;

string authName = config.GetValue<string>("AuthName");
string loginPage = config.GetValue<string>("LoginPage");
builder.Services.AddHttpClient(authName);
builder.Services.AddControllers();
builder.Services.AddBlazoredLocalStorage();

//sample one username and password. In reality you would populate the dictionary with username and pwd from IDS
string username = "yogi";
string pwd = "123";

int jwtExpMinutes = 60;

builder.Services.AddScoped<IAuthorizationJWT, AuthorizationJWT>(_ => {
    Dictionary<string, string> userCreds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
    userCreds.Add(username, pwd); // Populate this with username and password from DB. The password is clear text

    return new AuthorizationJWT(userCreds, "username", jwtExpMinutes, "YourCompanyName", "General Audience");
    });

builder.Services.AddScoped<IAuthorizationJWTEncrypted, AuthorizationJWTEncrypted>(_ => {

    Dictionary<string, string> userCredsHashed = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

    string pwdEncrypted = BCrypt.Net.BCrypt.HashPassword(pwd);
    userCredsHashed.Add(username, pwdEncrypted); // Populate this with username and password from DB. The password is BCrypt-hashed

    return new AuthorizationJWTEncrypted(userCredsHashed, "username", jwtExpMinutes, "YourCompanyName", "General Audience");
    });

builder.Services.AddScoped<IAppState, AppState>(_ => new AppState());
builder.Services.AddScoped<BasicAuthentication>();
builder.Services.AddScoped<IPageAuthCheck, PageAuthCheck>(ioc => new PageAuthCheck(ioc.GetService<NavigationManager>(), ioc.GetService<IHttpClientFactory>(), ioc.GetService<ILocalStorageService>(), authName, loginPage));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();
app.UseRouting();

app.MapControllerRoute(
name: "mvc",
pattern: "{controller}/{action}/{id?}");

app.UseAntiforgery();
app.MapControllers();

app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();

app.Run();

For OIDC, the middleware should follow this sequence: ---------------------

        // OpenIDC - Auth0 ----------------

        builder.Services.AddYGOpenIdConnect(builder.Configuration);

        // For checking user role against local database, create DI class that inherits from IYGOpenIdConnectEventHandler
        // Then Register it in DI, like this: 

        builder.Services.AddScoped<IYGOpenIdConnectEventHandler, YourCustomHandler>();

        //  code all the necessary actions upon successful login and logout in this class: YourCustomHandler - name it appropriately to suit your needs  


        // OpenIDC ---- end


        var app = builder.Build();


        app.UseHttpsRedirection();

        app.UseStaticFiles();

        app.UseRouting();

        app.MapControllerRoute(
           name: "mvc",
           pattern: "{controller}/{action}/{id?}");

        app.MapBlazorHub();
        app.MapFallbackToPage("/_Host");

        app.UseAuthentication();
        app.UseAuthorization();

        string oidcProvider = builder.Configuration["YGAuthentication:OpenIdConnect:Provider"] ?? "Auth0";
        app.MapYGOpenIdConnectEndpoints(oidcProvider);

        app.Run();

// if you ever need help setting this up, please connect and message me in LinkedIn: Yogi Grantz

Login Page - UI:

Please see the source code - YGAuthenticationTestApp:

Login1 - straight authentication without password encryption
Login2 - straight authentication with password encryption
Login3 - WebAPI authentication without password encryption
Login4 - WebAPI authentication with password encryption

App.razor:

@using YGAuthentication.Jwt
@inject IPageAuthCheck _pageCheck

@using YGAuthentication.States
@inject IAppState _appstate


<Router AppAssembly="@typeof(App).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
    <NotFound>
        <PageTitle>Not found</PageTitle>
        <LayoutView Layout="@typeof(MainLayout)">
            <p role="alert">Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

@code {

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await _pageCheck.AuthCheckAsync();
            _appstate.ErrorMessage = _pageCheck.ErrorMessage;

            if (_pageCheck.IsAuthorized)
                _appstate.LoggedIn = true;
            else
                _appstate.LoggedIn = false;
        }
    }
}
@using YGAuthentication.Jwt
@inject IPageAuthCheck _pageCheck
@using YGAuthentication.States
@inject IAppState _appstate

protected override void OnInitialized()
{
    _appState.OnChange += StateHasChanged;
}

public void Dispose()
{
    _appState.OnChange -= StateHasChanged;
}

Any Page:

@using YGAuthentication.States
@inject IAppState _appstate
protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        if (_appstate.LoggedIn)
        {
            _message = "Authorized";
            _msgClass = "alert-success";
        }
        else
            _message = $"You are NOT Authorized {_appstate.ErrorMessage}";

    }

Logout Page:

    @page "/Logout"
    @using Blazored.LocalStorage
    @using YGAuthentication.Jwt
    @inject ILocalStorageService _localStorage
    @inject IPageAuthCheck _pageAuth
    <h3>Logout</h3>

    <div>@_errMsg</div>

    @code {
        private string _errMsg = "";

        protected override async Task OnInitializedAsync()
        {
            await base.OnInitializedAsync();

            try
            {
                var result = await _pageAuth.LogoutAsync(_localStorage);

                if (!result.Item1)
                    _errMsg = result.Item2;
                else
                    _errMsg = $"Logged out: {result.Item2}";
            }
            catch (Exception ex)
            {
                _errMsg = ex.Message;
            }
        }
    }

Examples

A full working POC SampleAuthTest (MudBlazor) and YGEnvAuthenticationTestApp (Plain Blazor) are provided in the Repo.

Output:

Blazor Web Application that uses log in

Dependencies

<ItemGroup> <PackageReference Include="BCrypt.Net-Next" Version="4.0.3" /> <PackageReference Include="Blazored.LocalStorage" Version="4.5.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" /> <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.0.2" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" /> </ItemGroup>

Contributing

Any new ideas on how to enhance this class without adding much complexity, please adhere to SOLID principle

License

This project is licensed under the MIT License(LICENSE).

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.3.3 116 8/8/2026
2.3.2 114 8/8/2026
2.3.1 119 7/14/2026
2.3.0 112 7/14/2026
2.2.2 118 7/9/2026
2.2.1 113 7/8/2026
2.2.0 133 7/8/2026

Updated Readme.md