Omni2FA.Core 0.7.2

dotnet add package Omni2FA.Core --version 0.7.2
                    
NuGet\Install-Package Omni2FA.Core -Version 0.7.2
                    
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="Omni2FA.Core" Version="0.7.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Omni2FA.Core" Version="0.7.2" />
                    
Directory.Packages.props
<PackageReference Include="Omni2FA.Core" />
                    
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 Omni2FA.Core --version 0.7.2
                    
#r "nuget: Omni2FA.Core, 0.7.2"
                    
#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 Omni2FA.Core@0.7.2
                    
#: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=Omni2FA.Core&version=0.7.2
                    
Install as a Cake Addin
#tool nuget:?package=Omni2FA.Core&version=0.7.2
                    
Install as a Cake Tool

Omni2FA

Drop-in multi-method two-factor authentication for self-hosted apps — TOTP, Email OTP, WebAuthn/passkeys, recovery codes — behind one OpenAPI contract.

npm NuGet License Status

You verify the password and mint your session; Omni2FA handles everything 2FA in between — enrollment, the login challenge, OTP/WebAuthn ceremonies, recovery codes, persistence, rate limiting, audit. Backend service + endpoints + EF store on .NET; headless hooks on React. Other stacks implement the same contract (roadmap below).

For apps that own their user table (ASP.NET Core Identity, custom JWT/cookie auth, …). Not for managed identity providers (Auth0, Clerk, Cognito, Firebase, Supabase, Okta, WorkOS) — they already ship 2FA.


Packages

Stack Install Notes
.NET (ASP.NET Core) Omni2FA.AspNetCore + Omni2FA.AspNetCore.EntityFrameworkCore Omni2FA.Core comes transitively
React @omni2fa/core + @omni2fa/react hooks; styled MUI dialogs (@omni2fa/react-mui) — planned

Other backends (Node, Python) and frontends (Angular, Vue) are on the roadmap; any stack can implement the OpenAPI contract.


Backend — ASP.NET Core

dotnet add package Omni2FA.AspNetCore
dotnet add package Omni2FA.AspNetCore.EntityFrameworkCore

Program.cs

builder.Services.AddOmni2Fa(o => builder.Configuration.GetSection("Omni2Fa").Bind(o));
builder.Services.AddOmni2FaEntityFrameworkStore<AppDbContext>();   // or implement the store interfaces yourself

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapOmni2Fa();                                                  // mounts /api/2fa/*

Your DbContext

protected override void OnModelCreating(ModelBuilder modelBuilder) {
    base.OnModelCreating(modelBuilder);
    modelBuilder.ApplyOmni2FaConfiguration();                      // 2FA tables (names configurable)
}

Hook the pre-auth token into your existing login — the seam between your password check and the 2FA step:

public class AuthService(IPreAuthTokenIssuer preAuth, ITwoFactorMethodStore methods) {
    // after you verify the password:
    if (await methods.HasActiveMethodsAsync(userId)) {
        var ticket = preAuth.Issue(userId);                        // short-lived JWT
        var available = await methods.ListActiveByUserAsync(userId);
        return Challenge(ticket.Token, ticket.ExpiresAt, available); // your DTO → frontend
    }
    // else: mint your session as usual

    // when the frontend finishes 2FA, it calls your "finalize" with the verifiedToken from the verify response:
    var verifiedUserId = preAuth.ValidateVerified(verifiedToken);  // null if not actually verified → reject
}

Use the DTOs the library already ships at the host seam — don't reinvent them (all in Omni2FA.Core.Dtos / .Services):

DTO Where you use it
PreAuthTokenInfo returned by Issue / IssueVerified{ Token, ExpiresAt }
PreAuthChallengeResponse your login response when 2FA is required — { PreAuthToken, AvailableMethods, ExpiresAt }
TwoFactorMethodDto shape of an enrolled method (AvailableMethods items)
VerifySuccessResponse the /challenge/verify body — { Verified, UserId, VerifiedToken, ExpiresAt }
ErrorResponse + Omni2FaErrorCodes error envelope and the stable error-code constants

appsettings.json

"Omni2Fa": {
  "PreAuth":  { "SigningKey": "<32+ char HMAC key — from env/secrets>" },
  "Totp":     { "Issuer": "MyApp" },
  "Email":    { "FromAddress": "no-reply@myapp.com",
                "Smtp": { "Host": "smtp.example.com", "Port": 587, "Username": "...", "Password": "...", "UseStartTls": true } },
  "WebAuthn": { "RelyingPartyId": "myapp.com", "Origins": [ "https://myapp.com" ] }
}

That's the whole backend: endpoints, the three methods, recovery codes, rate limiting and audit are live.


Frontend — React

npm i @omni2fa/core @omni2fa/react

Once, at the app root

import { createOmni2Fa } from '@omni2fa/core';
import { Omni2FaProvider } from '@omni2fa/react';

export const omni = createOmni2Fa({ baseUrl: '/api/2fa' });
// after your login, hand the client your host session token (or use cookies: createOmni2Fa({ credentials: 'include' })):
omni.client.setSessionToken(sessionToken);

<Omni2FaProvider value={omni}>{children}</Omni2FaProvider>

The hooks expose state + actions; you render the UI (headless).

Login challenge

import { useChallenge } from '@omni2fa/react';

const { status, context, pick, submit, useRecoveryCode } = useChallenge();
// pick(methodId) → submit(code)  (WebAuthn auto-runs the browser ceremony)
// status: 'idle' | 'awaitingCode' | 'asserting' | 'verifying' | 'verified' | 'failed' | …
// on 'verified': send context.verifiedToken to your finalize endpoint (not the pre-auth token)

Hooks: useMethods, useTotpEnrollment, useEmailEnrollment, useWebAuthnEnrollment, useChallenge (+ *Selector variants). A full headless UI you can copy lives in examples/full/frontend. Styled drop-in components (@omni2fa/react-mui) are planned.


Configuration (key options, under Omni2Fa)

Option Default Purpose
PreAuth.SigningKey — (required, ≥32 chars) HMAC key for the pre-auth ticket; validated at startup
PreAuth.Ttl 5 min Pre-auth ticket lifetime
PreAuth.VerifiedTtl 2 min Verified-handoff token lifetime (the finalize proof)
Totp.Issuer Omni2FA Name shown in authenticator apps
Email.Smtp.* / Email.BackgroundDelivery — / true SMTP transport; codes sent on a background worker by default
WebAuthn.RelyingPartyId / Origins localhost / http://localhost:5173 Must match your real hostname (HTTPS off-localhost)
WebAuthn.MaxCredentialsPerUser 3 Passkey cap per user
RateLimit.{PermitLimit,Window} 20 / 1 min Per-IP limit on verify/enroll endpoints
AspNetCore.AllowDisablingLastMethod true Set false to forbid removing the last method
EF table/column names Omni2Fa* Override via ApplyOmni2FaConfiguration(o => …) for migrations

Extension points (swap any piece — TryAdd, host wins)

Interface Replace to…
IEmailSender send via your own infra (SendGrid/SES/relay) instead of MailKit/SMTP
IEmailMessageBuilder customize/localize the OTP email copy
IOmni2FaAuditSink forward audit events to your log/SIEM (default → ILogger)
ITwoFactorMethodStore / ITwoFactorChallengeStore / IRecoveryCodeStore use Mongo/Dapper/raw ADO instead of EF Core
IUserContextAccessor derive the current user id from a custom claim/header
IPreAuthTokenIssuer change how the pre-auth ticket is minted/validated
IWebAuthnCeremonyService swap the FIDO2 implementation

Methods & status

Method State
TOTP (authenticator apps)
Email OTP (SMTP)
WebAuthn (passkeys / security keys)
Recovery codes (one-time, hashed)
Rate limiting · audit sink

🚧 Status — pre-1.0 (0.6.x). Functionally complete for .NET + React, verified by a live end-to-end run, but young: no automated test suite yet (planned for v1.0), and WebAuthn/email not yet battle-tested across many environments. Suitable for your own apps; harden before betting a production product on it.


More

License

MIT — see 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 (2)

Showing the top 2 NuGet packages that depend on Omni2FA.Core:

Package Downloads
Omni2FA.AspNetCore

Omni2FA — ASP.NET Core integration. Endpoints (/api/2fa/*), DI extensions (AddOmni2Fa), filters, default SMTP email sender. Drop-in 2FA for ASP.NET Core apps.

Omni2FA.AspNetCore.EntityFrameworkCore

Omni2FA — Entity Framework Core store adapter. Implements ITwoFactorMethodStore and ITwoFactorChallengeStore on EF Core. Works with any relational provider (PostgreSQL, SQL Server, SQLite, MySQL, Oracle). Plug into your existing DbContext via modelBuilder.ApplyOmni2FaConfiguration().

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.7.2 0 6/9/2026
0.7.1 0 6/9/2026
0.7.0 51 6/8/2026
0.6.1 49 6/8/2026