Integrating OIDC (Feide) as Fallback and Recovery
Combining WebAuthn and Feide OIDC for recovery, federation, and identity continuity in a VueJS + ASP.NET Core PWA

WebAuthn gave us phishing-resistant, device-bound authentication.
But devices get lost. Browsers reset. Users switch laptops. Institutions manage identities centrally.
That’s where OIDC (Feide) enters — not as a competitor to passwordless, but as structural support.
This article walks through my real implementation:
Frontend: VueJS PWA
Backend: ASP.NET Core
Database: SQL Server
Passwordless: fido2-net-lib
Federation: OpenID Connect (Feide)
Session: HTTP-only cookie
And we’ll focus on four things:
What can Feide bring to the table
How OIDC fits without undermining WebAuthn
Security boundaries between IdP and my system
Account linking in practice
Disclaimer
This article describes architectural patterns and technical approaches based on a real-world implementation. All examples, code snippets, and flow descriptions have been generalized and simplified for educational purposes. No proprietary business logic, confidential configurations, credentials, or organization-specific details are disclosed. The focus is strictly on publicly documented standards (WebAuthn, OIDC) and implementation patterns within a standard VueJS + ASP.NET Core + SQL Server stack.
What can Feide bring to the table
Feide is widely used in Norwegian education and research sectors. That matters for three reasons:
1️⃣ Institutional Identity Already Exists
Users already have:
A managed identity
Centralized credential lifecycle
Organizational trust
Recreating identity inside my PWA would be redundant and weaker.
2️⃣ Compliance & Governance
Institutional IdPs typically enforce:
MFA policies
Password strength
Account revocation
Auditing
By integrating Feide, my system inherits that upstream assurance without storing passwords.
3️⃣ Recovery and Bootstrap
WebAuthn is device-bound.
Feide provides:
Cross-device identity continuity
Secure account recovery
Bootstrap trust for new devices
How OIDC Fits Without Undermining Passwordless
The common fear:
“If I add OIDC fallback, doesn’t that weaken passwordless?”
Only if fallback is careless.
My architecture enforces this model:
WebAuthn = primary authentication
Feide OIDC = bootstrap + recovery
HTTP-only cookie = session integrity
SQL Server = credential persistence

Feide does not authenticate users inside my system directly.
Feide asserts identity.
WebAuthn proves device possession.
Those are different trust layers.
Real OIDC Integration (ASP.NET Core)
My implemented Authorization Code flow with PKCE.
OIDC Configuration
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Lax;
})
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://auth.feide.no";
options.ClientId = Configuration["Feide:ClientId"];
options.ClientSecret = Configuration["Feide:ClientSecret"];
options.ResponseType = "code";
options.SaveTokens = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.TokenValidationParameters.NameClaimType = "name";
});
Important detail:
options.SaveTokens = false;
You do not store IdP tokens in the browser.
You convert identity into a server-controlled session.
OIDC Callback Flow
[HttpGet("callback")]
public async Task<IActionResult> Callback()
{
var authenticateResult = await HttpContext.AuthenticateAsync("oidc");
if (!authenticateResult.Succeeded)
return Unauthorized();
var externalUserId = authenticateResult.Principal.FindFirst("sub")?.Value;
var user = await FindOrCreateUser(externalUserId);
SignInUser(user.Id);
if (!user.WebAuthnCredentials.Any())
return Redirect("/enable-passwordless");
return Redirect("/dashboard");
}
This is critical:
Feide proves identity.
The system maps that identity to internal user record.
The system issues session cookie.
The IdP does not create sessions in my system.
Security Boundaries Between OIDC and My System
Understanding boundaries prevents architectural confusion.
What OIDC Is Responsible For
Authenticating the user upstream
Issuing ID tokens
Managing institutional identity lifecycle
Enforcing upstream MFA policies
What My System Is Responsible For
Mapping external identity (
sub) to internal userManaging WebAuthn credentials
Verifying FIDO2 assertions
Issuing and invalidating session cookies
Authorization within my application

OIDC is not trusted to:
Authorize application actions
Manage WebAuthn devices
Maintain the session integrity
Trust is layered, not delegated.
Account Linking Considerations
This is where real complexity lives.
OIDC provides:
{
"sub": "abcd1234",
"email": "user@example.edu"
}
But what if:
Email changes?
User logs in with different institutional account?
Duplicate local account exists?
You must choose a stable linking strategy.
Recommended Linking Model
Use sub as the primary external identifier.
Database model:
CREATE TABLE ExternalLogins (
Id UNIQUEIDENTIFIER PRIMARY KEY,
UserId UNIQUEIDENTIFIER NOT NULL,
Provider NVARCHAR(50) NOT NULL,
ExternalSubject NVARCHAR(255) NOT NULL
);
Mapping logic:
var externalLogin = await _db.ExternalLogins
.FirstOrDefaultAsync(x =>
x.Provider == "Feide" &&
x.ExternalSubject == externalUserId);
if (externalLogin == null)
{
// First login → create link
var user = CreateNewUser();
_db.ExternalLogins.Add(new ExternalLogin {
UserId = user.Id,
Provider = "Feide",
ExternalSubject = externalUserId
});
}
Never rely solely on email for linking.
Emails change. sub should not.
Recovery Flow Using Feide
Lost device scenario:
User clicks “Login with Feide”
OIDC completes
Identity verified
System invalidates old WebAuthn credentials
User registers new credential
Example revocation:
_db.WebAuthnCredentials.RemoveRange(user.WebAuthnCredentials);
await _db.SaveChangesAsync();
Then redirect to registration.
Recovery is structured. Not improvised.
Why This Does Not Undermine Passwordless
Weak fallback undermines security when:
It bypasses verification
It skips policy
It exists only as emergency shortcut
My implementation ensures:
OIDC must complete successfully
Session is server-issued
WebAuthn remains primary method
Registration after OIDC is explicit

This maintains assurance.
VueJS PWA Integration
From frontend:
function loginWithFeide() {
window.location.href = "/api/auth/feide-login";
}
No tokens stored client-side.
No JWT in localStorage.
No client-managed identity state.
The PWA only reacts to session cookie.
This keeps attack surface small.
What This Architecture Achieves
By combining:
WebAuthn (device-bound proof)
Feide OIDC (identity continuity)
SQL Server (credential persistence)
HTTP-only cookies (session security)
You achieve:
Phishing resistance
Device lifecycle resilience
Institutional identity integration
Controlled fallback
Clear trust boundaries

Most importantly:
You avoid false dichotomy.
This is not:
“Passwordless vs Federation.”
It is:
“Passwordless for authentication. Federation for identity continuity.”
Final Reflection
Integrating OIDC did not weaken the system.
It completed it.
WebAuthn without federation is brittle.
Federation without WebAuthn is phishable.
Together, they form a layered trust architecture.
In the next article, we’ll examine operational lessons learned after deploying this combined system — including monitoring, auditing, and real-world behavioral patterns that only surface after production traffic begins.
Because authentication design doesn’t end at implementation.
It evolves under pressure.
☰ Series Navigation
Core Series
Article 7 — A Real Passwordless PWA Flow (Architecture Walkthrough)
→ Article 9 — Integrating OIDC (Feide) as Fallback and Recovery






