Skip to content
Kanishq Sharma

↑↓ to move · enter to open · esc to close

Projects

Re-Medi

Healthcare platform with appointments and role-separated access.

Python · REST APIs · MongoDB · JWT

Overview

Re-Medi handles appointments between patients and clinic staff. Different roles see different things, which made access control the central problem rather than an afterthought.

It was the first project where I implemented JWT authentication and role-based access control myself instead of reaching for a framework that hid them.

Architecture

A REST API in front of MongoDB, with authorisation applied as a dependency so every protected route declares what it needs.

  1. Client

    Separate views for patients and staff.

  2. REST API

    Routing and request validation.

  3. JWT auth

    Role checks

    Identity from the token, permission from the role.

  4. MongoDB

    Users, appointments, and records as documents.

Listing appointments

  1. 1. GET /appointments

    The same endpoint serves patients and doctors; the caller decides what it returns.

  2. 2. Verify the token

    The JWT is decoded and rejected if expired, before any handler logic runs.

  3. 3. Read the role

    Identity comes from the token and permission from the role, never from a query parameter.

  4. 4. Scope the query

    Patients get their own rows, doctors get their schedule. The filter is derived, not supplied.

Database schema

users

Patients and staff in one collection, separated by role.

_id
ObjectId
email
string · unique index
passwordHash
string
role
string · patient, doctor, admin
createdAt
Date

appointments

A booking between a patient and a doctor.

_id
ObjectId
patientId
ObjectId · reference to users
doctorId
ObjectId · reference to users
slot
Date · unique index with doctorId
status
string · requested, confirmed, cancelled

API design

  • POST/auth/registerCreate a patient account.
  • POST/auth/loginIssue a JWT.
  • GET/appointmentsauthScoped to the caller: patients see theirs, doctors see their schedule.
  • POST/appointmentsauthRequest a slot.
  • PATCH/appointments/{id}authConfirm or cancel. Staff only.

Challenges

Authorisation scattered across handlers

Role checks written inline in each route were easy to forget. Moving them into a reusable dependency made the requirement visible in the route signature instead of buried in its body.

Leaking other people’s data through filters

A list endpoint that trusted a query parameter for the patient id would happily return someone else’s appointments. Scoping every query by the caller, not by input, fixed it.

Lessons learned

  • Never let the client tell you who it is; derive it from the token.
  • Role checks belong in one place, declared per route.
  • Authentication is the easy half. Authorisation is where the bugs live.

Other case studies