HackIndia Logo
HackathonsNewsSkillsGrowth
HackIndia LogoContact: +91 9910125804

General

  • Companies
  • Colleges
  • Board of Advisors
  • Brand Ambassadors
  • FAQ
  • Contact
  • Report a Bug

Hackathons

  • Upcoming Hackathons
  • Judges
  • Mentors
  • Partners
  • Participating Colleges
  • Testimonials

Resources

  • About Us
  • Branding
  • Latest News
  • Growth
  • Skills
  • Builders
  • Ecosystem
  • Forum
  • Ideas
  • Prompt Optimizer
  • Games

© 2026 HackIndia. All rights reserved.

Privacy PolicyTerms of ServiceCode of ConductSitemap

Build 2.139 · 05 Nov 2026, 10:27 UTC

    HackIndia
    HackathonsNewsInternshipsSkillsGrowthPro Perks
    ← Add safe sign-in

    All the reading

    Authentication

    7 lessons, about 29 minutes. The check's questions come from these.

    Contents
    Planning auth and choosing state
    1. 1. Avoid the common auth traps
    2. 2. Hash passwords correctly
    3. 3. Choose sessions or tokens
    Cookies and OAuth sign-in
    1. 4. Use cookies safely
    2. 5. Add OAuth sign-in
    Protecting routes and shipping repo
    1. 6. Protect routes and data
    2. 7. Ship an auth-ready repo

    Planning auth and choosing state

    1. Avoid the common auth traps

    4 min

    In 30 seconds
    • Spot the auth traps that make apps unsafe, even when sign-in seems to work.
    • Write a small auth plan before you code login, signup, and protected pages.
    • Add a README checklist recruiters can inspect in your public repo.
    Key point

    One idea

    Auth is not one feature. It is a chain. If one link is weak, the whole sign-in flow becomes easy to break.

    Your job is not to invent security. Your job is to use proven tools, make clear choices, and document what you checked.

    What goes wrong

    Most broken student auth is not broken by advanced hacking. It is broken by simple mistakes: saving plain passwords, trusting the browser too much, leaking secrets, or protecting only the button instead of the server route.

    A recruiter inspecting your repo will not expect bank-grade security. They will expect you to know the basic traps and avoid them on purpose.

    Common mistake

    Common traps

    Do not store passwords as plain text. Do not write your own encryption or hashing logic. Do not put API keys, OAuth secrets, JWT secrets, or database URLs in public code.

    Do not rely on frontend checks alone. Hiding a dashboard link is not protection. The server must verify the signed-in user before returning private data.

    Your to-do

    Plan before coding

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    2. Hash passwords correctly

    4 min

    In 30 seconds
    • Store password hashes, not passwords, in your database.
    • Use bcrypt or Argon2 with a unique salt per password.
    • Verify a login by comparing the password with the stored hash.
    Key point

    One rule

    Never store a user’s password. Store a slow password hash created by a trusted library.

    A password hash is one-way. During login, you hash-check the typed password against the stored hash.

    Why slow hashes

    Normal hashes like SHA-256 are too fast for passwords. If your database leaks, an attacker can try crores of guesses quickly.

    Password hash functions like bcrypt and Argon2 are built to be slow. They also include a unique salt so two users with the same password get different hashes.

    Common mistake

    Do not do this

    Do not encrypt passwords so you can decrypt them later. Your app never needs to know the original password again.

    Do not write your own salting or hashing logic. Use a maintained library and store the full hash string it returns.

    3. Choose sessions or tokens

    5 min

    In 30 seconds
    • Pick sessions or tokens based on your app, not trends.
    • Explain where auth state lives and how logout works.
    • Add a short auth-choice note to your README.
    Key point

    Main choice

    Use sessions for most server-rendered web apps. Use tokens when your API must be called by separate clients like a mobile app, another backend, or a separate frontend domain.

    The real question is simple: where will you store the signed-in state, and how will you revoke it when the user logs out?

    What sessions mean

    With sessions, the server stores the login state. The browser only keeps a random session ID, usually in a cookie.

    On each request, the server reads the session ID, looks it up, and knows the user. Logout is easy because the server can delete that session.

    What tokens mean

    With tokens, the client stores a signed token. The server checks the token on each request and trusts its contents if the signature is valid.

    Tokens are common for APIs and mobile apps. Logout is harder because a valid token can remain valid until it expires, unless you add a denylist or use short expiry with refresh tokens.

    Your to-do

    Cookies and OAuth sign-in

    4. Use cookies safely

    4 min

    In 30 seconds
    • Set auth cookies with HttpOnly, Secure, SameSite, and expiry.
    • Avoid storing tokens where JavaScript can read them.
    • Test cookie behaviour before you submit your repo.
    Key point

    One rule

    Treat an auth cookie like a house key. Send it only where needed, hide it from browser JavaScript, and give it an expiry.

    The safest default for most college projects is an HttpOnly, Secure cookie with SameSite=Lax and a sensible maxAge.

    What flags do

    HttpOnly means JavaScript cannot read the cookie using document.cookie. This reduces damage if one page gets an XSS bug.

    Secure means the browser sends the cookie only over HTTPS. SameSite controls when the browser sends the cookie during cross-site requests.

    Your to-do

    Set safe defaults

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Protecting routes and shipping repo

    6. Protect routes and data

    4 min

    In 30 seconds
    • Protect pages and API routes by checking auth on the server.
    • Return only the data the signed-in user is allowed to read or change.
    • Add simple tests and README notes that prove your route protection works.
    Key point

    The core rule

    Protect the server, not just the screen. Hiding a button in React is useful for UX, but it does not stop someone from calling your API with Postman or curl.

    Every private route must check who the user is before it reads or writes data.

    What to protect

    Protect two things: routes and records. A route check asks, “Is anyone signed in?” A record check asks, “Does this signed-in user own this data or have this role?”

    For example, /dashboard needs a signed-in user. /api/orders/123 also needs to confirm that order 123 belongs to that user.

    Your to-do

    Route protection flow

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    10 questions, 7 to pass.

    Sign in to take the test
    Example

    README auth plan

    Add a small auth section before you build. It keeps you honest and helps a reviewer understand your choices.

    You can ask an AI tool to improve the wording, but check that it does not claim features you have not built.

    Auth plan
    
    Public routes:
    - /
    - /login
    - /signup
    
    Protected routes:
    - /dashboard
    - /profile
    
    Auth method:
    - Email and password sign-in
    - Passwords will not be stored as plain text
    - Secrets will be stored in .env and not committed
    
    Checks before submission:
    - A logged-out user cannot open /dashboard directly
    - Logout removes access to protected routes
    - Invalid login shows a safe error message
    - Public repo does not contain real secrets
    Tip

    Use boring tools

    Use the auth support that fits your stack. For example, use a known library, framework middleware, or managed provider instead of building crypto yourself.

    If you use AI to generate auth code, ask it this: “What security assumptions does this code make?” Then verify the answer against your framework docs.

    Common mistake

    Unsafe errors

    Login errors should not reveal too much. “No account found for this email” helps attackers check which emails are registered.

    Use a safer message like “Invalid email or password”. Keep detailed errors in server logs, not on the page.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Your to-do

    Signup flow

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Node example

    This example uses bcrypt in an Express-style app. The same idea applies in Next.js, FastAPI, Django, Rails, or Laravel.

    Install with npm install bcrypt. If bcrypt gives install trouble on your laptop, bcryptjs can work for learning, but use bcrypt or Argon2 in serious projects.

    import bcrypt from "bcrypt";
    
    const SALT_ROUNDS = 12;
    
    export async function createUser(email, password) {
      const passwordHash = await bcrypt.hash(password, SALT_ROUNDS);
    
      const user = await db.user.create({
        data: {
          email,
          passwordHash
        }
      });
    
      return { id: user.id, email: user.email };
    }
    
    export async function loginUser(email, password) {
      const user = await db.user.findUnique({ where: { email } });
      if (!user) return null;
    
      const ok = await bcrypt.compare(password, user.passwordHash);
      if (!ok) return null;
    
      return { id: user.id, email: user.email };
    }
    Tip

    What to store

    Name the database column passwordHash, not password. That small choice helps reviewers see you did the right thing.

    Store the full hash string returned by the library. With bcrypt, it contains the algorithm, cost, salt, and hash in one string.

    Common mistake

    AI check

    If you ask ChatGPT or Gemini for auth code, check the output carefully. Reject code that uses SHA-256, MD5, crypto.createHash, reversible encryption, or a hardcoded salt for passwords.

    Also check that signup stores only passwordHash, and login uses bcrypt.compare or the equivalent verify function.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Choose by app shape

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Common mistake

    Common mistake

    Do not use JWTs only because they sound more advanced. A JWT is not automatically safer than a session.

    Also do not store long-lived tokens in localStorage without thinking through theft by injected JavaScript. You will handle storage details in the cookie lesson, but your choice starts here.

    Example

    README note

    Add a small section like this to your repo. It tells a recruiter that you made an auth design choice, not just copied a package setup.

    Auth choice
    
    This app uses server-side sessions.
    
    Reason:
    - The app is a normal web app with browser users.
    - The backend can store and revoke sessions.
    - Logout deletes the server session, so access stops immediately.
    - The browser only receives a session id, not the user password or user record.
    
    Security checks:
    - Passwords are hashed before storage.
    - Protected pages check the session before returning user data.
    - Session cookie settings are documented in the cookie section.
    Tip

    Ask AI well

    AI can help you compare choices, but give it your app shape. Ask for risks, not just code.

    Check the answer for three things: where state is stored, how expiry works, and how logout or revocation works.

    Prompt:
    I am building a web app with Express and React for college event registrations.
    Users sign in from a browser. The backend and frontend are on the same domain in production.
    Should I use server-side sessions or JWT access tokens?
    Compare storage, logout, expiry, and what I should write in my README.
    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Express example

    This example sets a session cookie after your login check has already passed. The value should be a random session id or a signed token created by your server.

    In local development, Secure cookies may not work on plain http://localhost. Use an environment check, then make sure production uses HTTPS.

    app.post('/login', async (req, res) => {
      // 1. Verify email and password first.
      // 2. Create a server-side session or signed token.
      const sessionId = await createSessionForUser(user.id);
    
      res.cookie('sid', sessionId, {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'lax',
        maxAge: 1000 * 60 * 60 * 24 * 7,
        path: '/'
      });
    
      res.json({ ok: true });
    });
    
    app.post('/logout', (req, res) => {
      res.clearCookie('sid', {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'lax',
        path: '/'
      });
    
      res.json({ ok: true });
    });
    Common mistake

    Common mistake

    Do not store access tokens in localStorage because it is easy for JavaScript on the page to read them. If an attacker gets script execution, localStorage is a simple target.

    Also do not put user roles, email, or secrets in a cookie and trust them directly. A cookie is sent by the browser, but your server must still verify it.

    Tip

    Check in DevTools

    After sign-in, open your browser DevTools and inspect Application or Storage, then Cookies. You should see the cookie name, expiry, HttpOnly, Secure, and SameSite values.

    For your README, add a small section called Auth cookie choices. Mention the flags you used and how you tested logout removes the cookie.

    CSRF note

    Cookies are sent automatically by the browser. That is useful, but it can create CSRF risk on state-changing routes like payment, profile update, or delete account.

    SameSite=Lax helps for many normal cases. If you use SameSite=None for cross-site needs, you must use Secure and add a CSRF protection plan.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    5. Add OAuth sign-in

    4 min

    In 30 seconds
    • Add Google or GitHub sign-in without handling the user’s password.
    • Set the OAuth callback URL and environment secrets correctly.
    • Store only the user identity you need, then continue with your session or token flow.
    Key point

    Use a provider

    OAuth lets a trusted provider like Google or GitHub confirm who the user is. Your app receives a verified identity and does not see the user’s provider password.

    The idea to remember: OAuth is for sign-in delegation. Your app still must create its own app session or token after the provider confirms the user.

    What OAuth adds

    In a college project, OAuth sign-in is useful because users can join with an account they already have. For a hackathon app, Google is common for student emails. GitHub is common for developer tools.

    The flow has four parts: your app redirects to the provider, the user approves, the provider redirects back to your callback URL, and your app signs the user into your own app.

    Your to-do

    Set up provider app

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    NextAuth example

    If your project uses Next.js, Auth.js / NextAuth is a common free choice. This example adds Google sign-in and stores the provider credentials in env vars.

    Check the docs for the exact setup for your Next.js version before copying. AI tools often mix old and new NextAuth file paths.

    // app/api/auth/[...nextauth]/route.js
    import NextAuth from "next-auth";
    import GoogleProvider from "next-auth/providers/google";
    
    const handler = NextAuth({
      providers: [
        GoogleProvider({
          clientId: process.env.GOOGLE_CLIENT_ID,
          clientSecret: process.env.GOOGLE_CLIENT_SECRET,
        }),
      ],
      callbacks: {
        async session({ session, token }) {
          session.user.id = token.sub;
          return session;
        },
      },
    });
    
    export { handler as GET, handler as POST };
    
    // .env.local
    GOOGLE_CLIENT_ID="your-client-id"
    GOOGLE_CLIENT_SECRET="your-client-secret"
    NEXTAUTH_URL="http://localhost:3000"
    NEXTAUTH_SECRET="make-a-long-random-secret"
    Common mistake

    Do not trust extras

    Do not treat every field from the provider as proof. The email, name, and photo help build a profile, but you should store only what your app needs.

    Also do not skip your own auth state. After OAuth succeeds, your app still needs a session cookie or token, with the safe handling from earlier lessons.

    Tip

    Use AI carefully

    Ask AI for a provider checklist, not secret values. Paste your framework version and ask for the correct callback route and env variable names.

    Then check three things yourself: secrets are not committed, callback URLs match exactly, and the app creates its own session after provider sign-in.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    0 of 5 done

    Example

    Express middleware

    This example assumes an earlier lesson already stored userId in the session after sign-in. The important part is that every private API route uses requireUser before doing work.

    function requireUser(req, res, next) {
      if (!req.session || !req.session.userId) {
        return res.status(401).json({ error: "Sign in required" });
      }
    
      req.user = { id: req.session.userId };
      next();
    }
    
    app.get("/api/me", requireUser, async (req, res) => {
      const user = await db.user.findUnique({
        where: { id: req.user.id },
        select: { id: true, name: true, email: true }
      });
    
      res.json({ user });
    });
    
    app.get("/api/projects/:id", requireUser, async (req, res) => {
      const project = await db.project.findFirst({
        where: { id: req.params.id, ownerId: req.user.id },
        select: { id: true, name: true, description: true }
      });
    
      if (!project) {
        return res.status(404).json({ error: "Project not found" });
      }
    
      res.json({ project });
    });
    Common mistake

    Common leak

    A common mistake is to fetch by id only, then check the owner later or not at all. That creates an IDOR bug, where a user changes /api/projects/1 to /api/projects/2 and sees someone else’s data.

    Filter by both record id and owner id in the database query when you can. It is simple and harder to forget.

    Tip

    Use AI carefully

    You can ask ChatGPT, Gemini, or Claude to review your route protection. Paste one route at a time and ask: “Can a signed-in user access another user’s records here?”

    Check the answer yourself. AI may miss framework details, but it is good at spotting missing ownerId filters, missing middleware, and over-returned fields like passwordHash.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    7. Ship an auth-ready repo

    4 min

    In 30 seconds
    • Turn your auth work into a repo a reviewer can run and inspect.
    • Add a README that explains sign-in, protected routes, and security checks.
    • Submit proof with clean env setup, screenshots, and a short test plan.
    Key point

    Proof beats claims

    Your repo should show working auth, not just say it has auth. A recruiter or judge should be able to clone it, add env values, run it, sign in, and see protected routes behave correctly.

    Your to-do

    Make it runnable

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Add env example

    Create a sample env file with names only. Never paste real OAuth client secrets, JWT secrets, database passwords, or production URLs with credentials.

    # .env.example
    DATABASE_URL="your_database_url_here"
    SESSION_SECRET="use_a_long_random_secret_here"
    GOOGLE_CLIENT_ID="your_google_client_id_here"
    GOOGLE_CLIENT_SECRET="your_google_client_secret_here"
    NEXTAUTH_URL="http://localhost:3000"
    Your to-do

    Write the README

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    README auth section

    Use direct language. The goal is to help someone inspect your choices fast.

    ## Auth overview
    
    Sign-in methods:
    - Email and password
    - Google OAuth
    
    Protected routes:
    - /dashboard requires a signed-in user
    - /api/notes requires a signed-in user
    - /login is public
    
    Security choices:
    - Passwords are hashed with bcrypt before storage
    - Session is stored in an httpOnly cookie
    - Cookie uses secure in production and sameSite=lax
    - Server checks the session before returning private data
    - Secrets are loaded from environment variables
    
    How to test:
    1. Run the app locally
    2. Visit /dashboard while signed out. You should be redirected to /login
    3. Sign in with a test account
    4. Visit /dashboard again. You should see private content
    5. Sign out and confirm /dashboard is blocked again
    Common mistake

    Do not hide gaps

    Do not write “secure auth added” if your API routes still return private data without checking the user. Reviewers often test APIs directly, not only pages.

    Also avoid committing screenshots that show real user emails, tokens, cookies, or OAuth secrets. Use a demo account and fake data.

    Tip

    Use AI carefully

    Ask ChatGPT, Gemini, or Claude to review your README and test plan. Paste only non-secret code or file snippets.

    Check what it returns. It may suggest fake package flags, wrong cookie names, or security claims your app does not actually implement.

    Prompt:
    Review this README auth section for clarity and missing security checks.
    Do not add features I have not implemented.
    Point out any claims that need proof in code.
    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done