Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
🟣 Data, Server और APIs  ·  Lesson 24

Login और Authentication

Login कैसे काम करता है

BrowserNext.jsMySQLemail + password POST (Server Action)SELECT user WHERE email = ?password_hashbcrypt.compare ✔Set-Cookie: session=<signed JWT>; HttpOnlyGET /dashboard (cookie अपने आप जाती है)signature + expiry verifypersonal dashboard HTML
Session cookie flow

Packages और users table

Terminal + .env.local
npm install jose bcryptjs

# .env.local – a long random secret (generate with: openssl rand -base64 32)
SESSION_SECRET=ZmJ4b3Y5c2VjcmV0LWtleS1jaGFuZ2UtbWUtMTIzNDU2
SQL – users table
CREATE TABLE users (
  id            INT AUTO_INCREMENT PRIMARY KEY,
  name          VARCHAR(80)  NOT NULL,
  email         VARCHAR(120) NOT NULL UNIQUE,
  password_hash VARCHAR(100) NOT NULL,
  role          ENUM('student','admin') DEFAULT 'student'
);
-- create a hash in Node:  require('bcryptjs').hashSync('admin123', 10)

lib/session.js – signed cookie

Session एक छोटा JWT (JSON Web Token) है जो आपके secret से signed है। कोई भी signature तोड़े बिना role: 'student' को 'admin' नहीं बना सकता।

JS – lib/session.js
// lib/session.js
import 'server-only'
import { SignJWT, jwtVerify } from 'jose'
import { cookies } from 'next/headers'

const key = new TextEncoder().encode(process.env.SESSION_SECRET)
const COOKIE = 'session'

export async function createSession(user) {
  const expires = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)   // 7 days
  const token = await new SignJWT({ id: user.id, name: user.name, role: user.role })
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuedAt()
    .setExpirationTime('7d')
    .sign(key)
  const store = await cookies()
  store.set(COOKIE, token, { httpOnly: true, secure: process.env.NODE_ENV === 'production',
                             sameSite: 'lax', path: '/', expires })
}

export async function readSession(token) {
  if (!token) return null
  try {
    const { payload } = await jwtVerify(token, key, { algorithms: ['HS256'] })
    return payload                       // { id, name, role, iat, exp }
  } catch {
    return null                          // expired or tampered
  }
}

export async function getSession() {
  const store = await cookies()
  return readSession(store.get(COOKIE)?.value)
}

export async function deleteSession() {
  const store = await cookies()
  store.delete(COOKIE)
}

Login Server Action

JS – app/login/actions.js
// app/login/actions.js
'use server'
import bcrypt from 'bcryptjs'
import { redirect } from 'next/navigation'
import { query } from '@/lib/db'
import { createSession, deleteSession } from '@/lib/session'

export async function login(prevState, formData) {
  const email = String(formData.get('email') || '').trim().toLowerCase()
  const password = String(formData.get('password') || '')
  if (!email || !password) return { error: 'Enter email and password.' }

  const [user] = await query('SELECT id, name, password_hash, role FROM users WHERE email = ?', [email])
  const ok = user && (await bcrypt.compare(password, user.password_hash))
  if (!ok) return { error: 'Wrong email or password.' }   // same message for both cases

  await createSession(user)
  redirect(user.role === 'admin' ? '/admin' : '/dashboard')
}

export async function logout() {
  await deleteSession()
  redirect('/login')
}

Login form

JSX – login form और page
// app/login/LoginForm.jsx
'use client'
import { useActionState } from 'react'
import { login } from './actions'

export default function LoginForm() {
  const [state, action, pending] = useActionState(login, {})
  return (
    <form action={action} style={{ display: 'grid', gap: 12, maxWidth: 340 }}>
      <input name="email" type="email" placeholder="Email" required />
      <input name="password" type="password" placeholder="Password" required />
      {state.error && <p style={{ color: 'crimson' }}>{state.error}</p>}
      <button className="btn" disabled={pending}>{pending ? 'Checking…' : 'Login'}</button>
    </form>
  )
}

// app/login/page.jsx
import LoginForm from './LoginForm'
export const metadata = { title: 'Login', robots: { index: false } }
export default function LoginPage() {
  return <main className="container section"><h1>Student login</h1><LoginForm /></main>
}
🔒 localhost:3000/loginEduSiteLoginCoursesHomeStudent loginEmailPasswordLoginWrong email or password.

Pages protect करना (DAL)

JS + JSX – lib/dal.js और dashboard
// lib/dal.js — Data Access Layer: every protected read goes through here
import 'server-only'
import { cache } from 'react'
import { redirect } from 'next/navigation'
import { getSession } from './session'

export const requireUser = cache(async () => {
  const session = await getSession()
  if (!session) redirect('/login')
  return session
})

export async function requireAdmin() {
  const user = await requireUser()
  if (user.role !== 'admin') redirect('/dashboard')
  return user
}

// app/dashboard/page.jsx
import { requireUser } from '@/lib/dal'
import { logout } from '../login/actions'

export default async function Dashboard() {
  const user = await requireUser()
  return (
    <main className="container section">
      <h1>Welcome, {user.name} 👋</h1>
      <form action={logout}><button className="btn light">Logout</button></form>
    </main>
  )
}

proxy.js से तेज़ redirects

Next.js 16 में middleware.js का नाम proxy.js हो गया है। यह page render शुरू होने से पहले ही logged-out users को redirect कर सकता है। इसे पहला gate मानें, अकेला नहीं।

JS – proxy.js
// proxy.js (project root) — runs before matching requests
import { NextResponse } from 'next/server'
import { readSession } from '@/lib/session'   // proxy runs on the Node.js runtime in Next.js 16

export async function proxy(request) {
  const token = request.cookies.get('session')?.value
  const session = await readSession(token)
  if (!session) {
    const url = new URL('/login', request.url)
    url.searchParams.set('next', request.nextUrl.pathname)
    return NextResponse.redirect(url)
  }
  return NextResponse.next()
}

export const config = { matcher: ['/dashboard/:path*', '/admin/:path*'] }
Request /admin/studentsproxy.jsvalid cookie नहीं → /loginpage: requireAdmin()admin नहीं → /dashboardData queryसिर्फ़ verified admin के लिए
Checks की दो layers

Logout

logout action cookie delete करके redirect करता है। छोटे form में use करें: <form action={logout}><button>Logout</button></form>।

Auth libraries (Auth.js, Clerk)

"Login with Google", magic links या 2FA के लिए Auth.js, Better Auth या Clerk जैसी library use करें। जो concepts आपने सीखे (session cookie, server checks, protected routes) वे बिल्कुल वही रहते हैं।

आम गलतियाँ

  • Session को localStorage में रखना → कोई भी XSS script पढ़ सकती है; httpOnly cookies use करें।
  • "Email नहीं मिला" और "गलत password" के अलग messages → attackers को accounts ढूँढने में मदद।
  • Login सिर्फ़ Client Component में check करना → data फिर भी पहुँच में; server पर check करें।
  • छोटा या commit किया हुआ SESSION_SECRET → कोई भी sessions forge कर सकता है।

सारांश

  • Passwords के लिए bcrypt, sessions के लिए httpOnly cookie में signed JWT।
  • Login/logout Server Actions हैं; requireUser() pages और actions protect करता है।
  • proxy.js = तेज़ redirect gate; data के पास हमेशा दोबारा check करें।
✅ Practice

bcrypt hash के साथ admin user बनाइए, /login, /dashboard और /admin बनाइए। Student के रूप में login करके confirm कीजिए कि /admin आपको redirect करता है।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

क्या JWT को cookie में रखना safe है?
हाँ, अगर cookie httpOnly (JavaScript नहीं पढ़ सकता), secure (सिर्फ़ HTTPS), sameSite=lax हो और token strong secret से signed हो और उसकी expiry हो।
क्या pages protect करने के लिए proxy.js काफ़ी है?
नहीं। proxy.js सिर्फ़ तेज़ redirects के लिए use करें। जहाँ data पढ़ा जाता है (page, Server Action या Route Handler) वहाँ session दोबारा verify करें, क्योंकि proxy matchers कुछ routes छोड़ सकते हैं।
Passwords को bcrypt से hash क्यों करें?
Database leak होने पर attackers को असली passwords की जगह सिर्फ़ slow, salted hashes मिलते हैं। Plain-text या MD5 passwords कभी store न करें।
← Next.js Tutorial
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicProxy (Middleware) और Redirects आपकी प्रगति: 24 / 37 (65%) · Lesson 25 / 37 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें