Skip to main content
The Clínica Vitalis platform implements a role-based access control (RBAC) system with two distinct user roles. This ensures that sensitive administrative operations are protected while providing standard users with appropriate access to their required functionality.

User Roles

The system defines two roles in backend/helpers/constants.ts:
backend/helpers/constants.ts
export const ROLES = {
    admin: "50yun4dmin",
    user: "50yunUs3r",
}

User Role (50yunUs3r)

This is the default role assigned to all new registrations unless the admin key is provided. Capabilities:
  • Access standard application features
  • View their own data
  • Create and manage appointments
  • Update personal information
Restrictions:
  • Cannot access administrative endpoints
  • Cannot modify other users’ data
  • Cannot manage system-wide settings

Admin Role (50yun4dmin)

Administrative users have elevated privileges for managing the platform. Capabilities:
  • All user role capabilities
  • Access administrative endpoints
  • Manage all users, appointments, and resources
  • Configure system settings
  • Access analytics and reports
Admin access should be granted sparingly and only to trusted personnel. The admin key must be kept confidential.

User Model

The user data structure is defined using Sequelize ORM:
backend/models/user.ts
export interface IUser {
    id: number;
    name: string;
    surname: string;
    email: string;
    password: string;
    rol?: string;
}

export const User = sequelize.define<UserInstance>('Usuarios', {
    id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
    },
    name: {
        type: DataTypes.STRING,
        allowNull: false,
    },
    surname: {
        type: DataTypes.STRING,
        allowNull: false,
    },
    email: {
        type: DataTypes.STRING,
        unique: true,
        allowNull: false,
    },
    password: {
        type: DataTypes.STRING,
        allowNull: false,
    },
    rol: {
        type: DataTypes.STRING,
        defaultValue: ROLES.user,
        allowNull: false,
    },
})

Key Fields

  • id: Auto-incremented primary key
  • name: User’s first name (required)
  • surname: User’s last name (required)
  • email: Unique identifier for login (required, must be valid email)
  • password: Bcrypt-hashed password (required, min 6 characters)
  • rol: User role, defaults to standard user

Registration Process

Standard User Registration

1

Submit Registration Data

Client sends name, surname, email, and password to /auth/register
2

Validation

Express-validator checks all required fields and email format
3

Password Hashing

System generates salt and hashes password using bcrypt
4

User Creation

User is saved to database with default user role
backend/controllers/auth.ts
const user = await User.create({name, surname, email, password, rol})

const salt = bycryptjs.genSaltSync();
user.password = bycryptjs.hashSync(password, salt)

await user.save()

Admin User Registration

To create an admin user, include the admin-key header:
1

Include Admin Key

Client includes admin-key header with the secret key value
2

Key Validation

System checks if admin-key matches KEY_FOR_ADMIN environment variable
3

Role Assignment

If valid, user role is set to admin before saving
backend/controllers/auth.ts
const adminKey = req.headers["admin-key"]

if (adminKey === process.env.KEY_FOR_ADMIN) {
    user.rol = ROLES.admin
}

await user.save()
curl -X POST http://localhost:3000/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "name": "María",
    "surname": "González",
    "email": "maria@example.com",
    "password": "securePass123"
  }'

Permission Validation

Admin Middleware

Protected administrative routes use the isAdmin middleware:
backend/middlewares/validatorAdmin.ts
export const isAdmin = (req: Request, res: Response, next: NextFunction) => {

    const { userConfirmated } = req.body;

    if (!userConfirmated) {
        res.status(404).json({
            msg: 'No hay usuario confirmado'
        });
        return
    }

    if (userConfirmated.rol !== ROLES.admin) {
        return res.status(401).json({
            msg: "El usuario no es un administrador"
        });
    }

    next();
}

Middleware Chain

Admin-protected routes typically use both JWT validation and role checking:
router.delete('/resource/:id',
    [
        validatorJWT,      // Validates token and attaches user
        isAdmin,           // Checks if user has admin role
    ],
    deleteResource
)

Validation Rules

The registration endpoint enforces strict validation rules:
backend/routes/auth.ts
router.post(
    '/register',
    [
        check("name", "El nombre es obligatorio").not().isEmpty(),
        check("surname", "El apellido es obligatorio").not().isEmpty(),
        check("email", "El email es obligatorio").not().isEmpty(),
        check("email", "El email no es válido").isEmail(),
        check("email").custom(existEmail),  
        check("password", "La contraseña debe tener al menos 6 caracteres").isLength({min: 6}),
        collectionErrors
    ],
    register
)

Validation Checks

  • Name: Required, cannot be empty
  • Surname: Required, cannot be empty
  • Email: Required, must be valid email format, must not already exist in database
  • Password: Required, minimum 6 characters
Custom validation existEmail prevents duplicate email registrations. Each email can only be associated with one account.

Error Handling

Registration Errors

{
  "errors": {
    "errors": [
      {
        "msg": "El email no es válido",
        "param": "email",
        "location": "body"
      }
    ]
  }
}

Authentication Errors

{
  "msg": "El usuario no es un administrador"
}

Best Practices

While the system requires minimum 6 characters, implement stronger requirements:
  • Minimum 12 characters recommended
  • Mix of uppercase, lowercase, numbers, and symbols
  • Regular password rotation for admin accounts
  • Store KEY_FOR_ADMIN in environment variables only
  • Rotate admin keys periodically
  • Use different keys for development, staging, and production
  • Never log or expose the admin key in responses
Consider implementing email verification for new registrations to:
  • Confirm email ownership
  • Prevent fake account creation
  • Enable password recovery functionality

Next Steps

JWT Implementation

Learn how JWT tokens are generated and validated

Authentication Overview

Return to authentication system overview

Build docs developers (and LLMs) love