Passwordless member authentication for Umbraco 17, distributed as NuGet packages. Three pluggable authentication methods — magic links, one-time passwords (OTP), and WebAuthn/FIDO2 passkeys — can be used individually or together.
| Package | Description |
|---|---|
HCS.Passwordless.MagicLink |
Magic link authentication |
HCS.Passwordless.Otp |
Add-on — email OTP codes |
HCS.Passwordless.WebAuthn |
Add-on — FIDO2/passkey authentication |
HCS.Passwordless.Core is a shared dependency installed automatically by any of the above.
- .NET 10.0
- Umbraco 17.x
- An existing Umbraco member type
dotnet add package HCS.Passwordless.MagicLink
# optional add-ons:
dotnet add package HCS.Passwordless.Otp
dotnet add package HCS.Passwordless.WebAuthnbuilder.CreateUmbracoBuilder()
.AddBackOffice()
.AddWebsite()
.AddPasswordlessMagicLink() // magic link sign-in
.AddPasswordlessOtp() // optional
.AddPasswordlessWebAuthn() // optional
.Build();{
"HCS": {
"Authentication": {
"LoginPath": "/login",
"PostLoginRedirectPath": "/member",
"MagicLink": {
"Enabled": true,
"TokenLifespan": "00:15:00",
"SingleUse": true
},
"Notifications": {
"FromAddress": "noreply@example.com",
"FromName": "My Site"
}
}
}
}In your login view, render the built-in partials for the factors you've installed:
@* Magic link request form *@
@await Html.PartialAsync("Passwordless/MagicLinkForm")
@* OTP request and code-entry form *@
@await Html.PartialAsync("Passwordless/OtpLoginForm")
@* Passkey sign-in button *@
@await Html.PartialAsync("Passwordless/PasskeySignInButton")The core method. The user enters their email; a signed, single-use link is emailed to them. Clicking it signs them in instantly. Tokens are stored in distributed cache and validated server-side.
An email is sent containing a short numeric code (default 6 digits). The user enters the code on a second screen. Includes configurable attempt limits and lockout.
FIDO2 hardware-backed authentication (Touch ID, Face ID, security keys). Requires credential registration before first sign-in. Credentials are stored in the Umbraco database via a migration.
- Constant-time token comparison to prevent timing attacks
- Single-use tokens (invalidated on first use)
- Sliding-window rate limiting — per-IP and per-email
- Fake-work delay on all auth endpoints to flatten timing differences
ReturnUrlvalidation to prevent open redirects- SHA-256 token hashing in storage
All settings live under HCS:Authentication. See individual package READMEs for full option tables.
Default templates are Razor partials shipped in the RCL. Override any template by adding a matching path under your host project's /Views folder:
Views/Emails/Passwordless/MagicLink.cshtmlViews/Emails/Passwordless/MagicLink.Text.cshtmlViews/Emails/Passwordless/Otp.cshtmlViews/Emails/Passwordless/Otp.Text.cshtmlViews/Emails/Passwordless/_Layout.cshtml
| Branch | Umbraco | .NET |
|---|---|---|
dev/v1 |
13.x | 8 |
dev/v2 |
17.x | 10 |
Releases are published as NuGet packages and tagged directly on the relevant dev/ branch. There is no main branch.
Passwordless.slnx
├── src/
│ ├── HCS.Passwordless.Core # Shared infrastructure
│ ├── HCS.Passwordless.MagicLink # Magic link add-on
│ ├── HCS.Passwordless.Otp # OTP add-on
│ └── HCS.Passwordless.WebAuthn # WebAuthn add-on
├── tests/
│ └── HCS.Passwordless.Tests # xUnit test suite
└── demo/
└── HCS.Passwordless.Demo # Full demo Umbraco site
dotnet build
dotnet testcd demo/HCS.Passwordless.Demo
dotnet runThen open https://localhost:44391 and complete the Umbraco install. The demo exposes /login and /member.
MIT — Nik Rimington