<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Saheb Irani</title>
    <description>The latest articles on DEV Community by Saheb Irani (@sinjulmsbh).</description>
    <link>https://dev.to/sinjulmsbh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F825588%2F50d62320-3a3d-40c7-9c02-861669b3f37d.jpg</url>
      <title>DEV Community: Saheb Irani</title>
      <link>https://dev.to/sinjulmsbh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sinjulmsbh"/>
    <language>en</language>
    <item>
      <title>Fullstack Authentication with Next.js and ASP.NET Core over Secure Cross-Domain Cookies</title>
      <dc:creator>Saheb Irani</dc:creator>
      <pubDate>Thu, 22 May 2025 20:36:35 +0000</pubDate>
      <link>https://dev.to/sinjulmsbh/fullstack-authentication-with-nextjs-and-aspnet-core-over-secure-cross-domain-cookies-4i3g</link>
      <guid>https://dev.to/sinjulmsbh/fullstack-authentication-with-nextjs-and-aspnet-core-over-secure-cross-domain-cookies-4i3g</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A complete, production-ready fullstack authentication setup using Next.js frontend and ASP.NET Core backend, with secure session cookies, OTP login via SMS, reCAPTCHA validation, and multi-device setup over local or public networks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Building a Secure Authentication System with ASP.NET Core and Next.js
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🚀 Overview
&lt;/h2&gt;

&lt;p&gt;This guide walks through setting up a secure user authentication system in a microservices-like architecture with a React-based frontend (Next.js) and a .NET Core backend (ASP.NET Core). It features:&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Introduction
&lt;/h2&gt;

&lt;p&gt;In modern web development, creating a robust authentication system that works seamlessly across separate frontend and backend services can be challenging. In this article, I'll walk through how to implement a secure authentication flow using ASP.NET Core for the backend API and Next.js for the frontend, with special attention to cookie-based authentication across different subdomains.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Our system will consist of:&lt;/li&gt;
&lt;li&gt;Backend: ASP.NET Core 9 API running on api.app.local&lt;/li&gt;
&lt;li&gt;Frontend: Next.js 15 application running on app.local&lt;/li&gt;
&lt;li&gt;Authentication: Cookie-based with Identity, supporting:&lt;/li&gt;
&lt;li&gt;Email/password login&lt;/li&gt;
&lt;li&gt;Cross-subdomain cookie sharing&lt;/li&gt;
&lt;li&gt;Secure development setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔐 Cookie-based session authentication (HttpOnly, Secure, SameSite=None)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;📱 OTP login via SMS (phone number-based authentication)&lt;/li&gt;
&lt;li&gt;✅ Google reCAPTCHA integration&lt;/li&gt;
&lt;li&gt;🔁 Session sliding expiration&lt;/li&gt;
&lt;li&gt;🌐 Cross-device and cross-network communication&lt;/li&gt;
&lt;li&gt;📦 Deployment-ready structure&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🧩 Tech Stack
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Frontend: Next.js (Server-Side Rendering, API routes)&lt;/li&gt;
&lt;li&gt;Backend: ASP.NET Core (v7 or later)&lt;/li&gt;
&lt;li&gt;Identity: ASP.NET Core Identity for user management&lt;/li&gt;
&lt;li&gt;SMS Gateway: Custom or Twilio/Any SMS service&lt;/li&gt;
&lt;li&gt;Security: reCAPTCHA v2/v3, Rate Limiting, IP restriction, Anti-spam&lt;/li&gt;
&lt;li&gt;Tunnel: Dev Tunnel (VS) or ngrok for public exposure&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🏗 Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
/next-app
  /pages
    /login
    /verify
    /dashboard
  /middleware.ts
  /lib/session.ts
  /components
  next.config.js

/aspnet-api
  /Controllers
  /Services
  /Models
  /Startup.cs
  /Program.cs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔧 Step-by-Step Setup
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;🔐 ASP.NET Core Secure Cookie Setup
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.Configure&amp;lt;CookieAuthenticationOptions&amp;gt;(IdentityConstants.ApplicationScheme, options =&amp;gt;
{
    options.Cookie.Name = "RFUM";
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.Cookie.HttpOnly = true;
    options.Cookie.SameSite = SameSiteMode.None;
    options.Cookie.Domain = ".dev.rfum.local";
    options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
    options.SlidingExpiration = true;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. 🧠 Identity OTP Token Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var token = await _userManager.GenerateChangePhoneNumberTokenAsync(user, user.PhoneNumber);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. 🌐 Cross-Origin &amp;amp; Cookie Setup
&lt;/h2&gt;

&lt;p&gt;In Startup.cs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddCors(options =&amp;gt;
{
    options.AddPolicy("AllowClient",
        builder =&amp;gt;
        {
            builder.WithOrigins("https://app.dev.rfum.local")
                   .AllowCredentials()
                   .AllowAnyHeader()
                   .AllowAnyMethod();
        });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. 🛡 Next.js Session Middleware
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export async function middleware(req: NextRequest) {
  const cookie = req.cookies.get('RFUM');
  if (!cookie) {
    return NextResponse.redirect(new URL('/login', req.url));
  }
  return NextResponse.next();
}
In fetch calls:
await fetch("https://api.dev.rfum.local/api/auth/status", {
  credentials: "include"
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. 🤖 Google reCAPTCHA v3
&lt;/h2&gt;

&lt;p&gt;In Next.js login form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const token = await grecaptcha.execute('site_key', { action: 'login' });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send to backend and verify with Google API.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. 📱 OTP SMS Flow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;On login with phone, server generates token.&lt;/li&gt;
&lt;li&gt;Sends SMS to phone with 6-digit code.&lt;/li&gt;
&lt;li&gt;User enters code.&lt;/li&gt;
&lt;li&gt;Backend verifies token with Identity.&lt;/li&gt;
&lt;li&gt;Add rate limit per IP, session TTL, and block after X retries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fox2egnb7orxhkusa88ej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fox2egnb7orxhkusa88ej.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Setup
&lt;/h2&gt;

&lt;h2&gt;
  
  
  7. 🌍 Networking Across Devices
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Option A: Dev Tunnel (Visual Studio)&lt;br&gt;
Expose ASP.NET Core app via:&lt;br&gt;
https://purple-tiger-12345.devtunnels.ms&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Use same domain in Next.js.&lt;br&gt;
Option B: Local DNS + nginx reverse proxy&lt;br&gt;
&lt;code&gt;Add in /etc/hosts:&lt;br&gt;
127.0.0.1 api.dev.rfum.local&lt;br&gt;
127.0.0.1 app.dev.rfum.local&lt;/code&gt;&lt;br&gt;
Use nginx to proxy /api/ to ASP.NET Core, and / to Next.js.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Local DNS Configuration&lt;br&gt;
Add to your hosts file:&lt;br&gt;
&lt;code&gt;127.0.0.1 app.local&lt;br&gt;
127.0.0.1 api.app.local&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;HTTPS Certificates&lt;/p&gt;
&lt;h1&gt;
  
  
  Create trusted local certificates
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;mkcert -install&lt;br&gt;
mkcert "app.local" "api.app.local"&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Running the Projects&lt;br&gt;
ASP.NET Core:&lt;br&gt;
&lt;code&gt;dotnet run --urls "https://api.app.local:5001"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next.js:&lt;br&gt;
&lt;code&gt;NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem" next dev -H app.local -p 3000&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Store refresh timestamps client-side, refetch session every 10 minutes.&lt;/li&gt;
&lt;li&gt;Use HttpOnly cookies with .dev.rfum.local as domain.&lt;/li&gt;
&lt;li&gt;Use separate ports and subdomains for frontend and backend.&lt;/li&gt;
&lt;li&gt;Protect OTP with IP throttling + CAPTCHA.&lt;/li&gt;
&lt;li&gt;Centralize session and token management.&lt;/li&gt;
&lt;li&gt;Add MFA with Google Authenticator for enterprise-ready auth.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔚 Final Words
&lt;/h2&gt;

&lt;p&gt;This authentication architecture is ideal for scalable, secure fullstack applications. Whether you're building a dashboard, SaaS platform, or enterprise portal — combining ASP.NET Identity with Next.js's SSR gives you the best of both worlds.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📦 If you'd like the full zip with source code, ping me and I’ll share it!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqo7bcffpgvgna8ebegcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqo7bcffpgvgna8ebegcl.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aspnet</category>
      <category>authentication</category>
      <category>cookies</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
