Skip to main content

Overview

The Sessions API handles user authentication in the Adoptme system. It provides endpoints for user registration, login with JWT token generation, and retrieving the current authenticated user. Base Path: /api/sessions Source Files:
  • Routes: src/routes/sessions.router.js
  • Controller: src/controllers/sessions.controller.js

Authentication Method

The API uses JWT (JSON Web Tokens) stored in HTTP cookies for authentication:
  • Cookie Name: coderCookie (protected) or unprotectedCookie (unprotected)
  • Token Expiration: 1 hour
  • JWT Secret: tokenSecretJWT (hardcoded in source)
  • Cookie Max Age: 3600000ms (1 hour)
The JWT secret tokenSecretJWT is hardcoded in the controller. For production, move this to environment variables.

Register User

curl -X POST http://localhost:8080/api/sessions/register \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "John",
    "last_name": "Doe",
    "email": "[email protected]",
    "password": "securePassword123"
  }'

Endpoint

POST /api/sessions/register
Registers a new user in the system. Passwords are hashed using bcrypt before storage.

Request Body

first_name
string
required
User’s first name
last_name
string
required
User’s last name
email
string
required
User’s email address (must be unique)
password
string
required
User’s password (will be hashed with bcrypt before storage)

Example Request Body

{
  "first_name": "John",
  "last_name": "Doe",
  "email": "[email protected]",
  "password": "securePassword123"
}

Response

status
string
“success”
payload
string
The newly created user’s ObjectId

Example Response

{
  "status": "success",
  "payload": "6893eaba2ac0b16fa177be7c"
}

Implementation Details

Password hashing (from src/controllers/sessions.controller.js:12):
const hashedPassword = await createHash(password);
const user = {
    first_name,
    last_name,
    email,
    password: hashedPassword
}
let result = await usersService.create(user);

Error Responses


Login

curl -X POST http://localhost:8080/api/sessions/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "email": "[email protected]",
    "password": "securePassword123"
  }'

Endpoint

POST /api/sessions/login
Authenticates a user and returns a JWT token in a cookie.

Request Body

email
string
required
User’s email address
password
string
required
User’s password (plain text - will be validated against hashed password)

Example Request Body

{
  "email": "[email protected]",
  "password": "securePassword123"
}

Response

status
string
“success”
message
string
“Logged in”
The response includes a Set-Cookie header with the JWT token:
Set-Cookie: coderCookie=<jwt_token>; Max-Age=3600000; Path=/; HttpOnly

Example Response

{
  "status": "success",
  "message": "Logged in"
}

JWT Token Payload

The JWT token contains a UserDTO with the following fields (from src/controllers/sessions.controller.js:35-36):
const userDto = UserDTO.getUserTokenFrom(user);
const token = jwt.sign(userDto, 'tokenSecretJWT', {expiresIn:"1h"});
The UserDTO typically includes:
  • User ID
  • Email
  • Role
  • Other non-sensitive user information

Error Responses


Get Current User

curl -X GET http://localhost:8080/api/sessions/current \
  -b cookies.txt

Endpoint

GET /api/sessions/current
Retrieves the currently authenticated user’s information from the JWT token stored in the coderCookie cookie.

Headers Required

Cookie: coderCookie=<jwt_token>
The cookie is automatically sent by the browser if you’re using credentials: 'include' in fetch or similar options in other HTTP clients.

Response

status
string
“success”
payload
object
Decoded JWT token payload containing user information

Example Response

{
  "status": "success",
  "payload": {
    "_id": "6893eaba2ac0b16fa177be7c",
    "email": "[email protected]",
    "role": "user"
  }
}

Implementation Details

From src/controllers/sessions.controller.js:43-51:
const current = async(req,res) =>{
    try {
        const cookie = req.cookies['coderCookie']
        const user = jwt.verify(cookie,'tokenSecretJWT');
        if(user)
            return res.send({status:"success",payload:user})        
    } catch (error) {
        res.status(500).send("Ha ocurrido un error en la petición, por favor ver detalle: ",error)
    }
}

Error Responses


Unprotected Login

curl -X GET "http://localhost:8080/api/sessions/[email protected]&password=pass123"

Endpoint

GET /api/sessions/unprotectedLogin
An alternative login endpoint that uses query parameters instead of request body and stores the full user object (not just a DTO) in the JWT token.
This endpoint is called “unprotected” because it stores the complete user object (including hashed password) in the JWT token, which is a security risk. Use the regular /login endpoint in production.

Query Parameters

email
string
required
User’s email address
password
string
required
User’s password

Response

Sets cookie unprotectedCookie and returns:
{
  "status": "success",
  "message": "Unprotected Logged in"
}

Implementation Note

From src/controllers/sessions.controller.js:62:
const token = jwt.sign(user, 'tokenSecretJWT', {expiresIn:"1h"});
res.cookie('unprotectedCookie', token, {maxAge:3600000})
Notice it signs the entire user object, not a sanitized DTO.

Unprotected Current User

curl -X GET http://localhost:8080/api/sessions/unprotectedCurrent \
  -b cookies.txt

Endpoint

GET /api/sessions/unprotectedCurrent
Retrieves the current user from the unprotectedCookie cookie.

Response

{
  "status": "success",
  "payload": {
    "_id": "6893eaba2ac0b16fa177be7c",
    "first_name": "John",
    "last_name": "Doe",
    "email": "[email protected]",
    "password": "$2b$10$hashedpassword...",
    "role": "user",
    "pets": []
  }
}
The response includes the hashed password, which should never be exposed. This is why this endpoint is “unprotected” - it’s less secure.

Complete Authentication Flow

1. Register

curl -X POST http://localhost:8080/api/sessions/register \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Smith",
    "email": "[email protected]",
    "password": "mypassword"
  }'
Response:
{
  "status": "success",
  "payload": "6893eaba2ac0b16fa177be7d"
}

2. Login

curl -X POST http://localhost:8080/api/sessions/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "email": "[email protected]",
    "password": "mypassword"
  }'
Response:
{
  "status": "success",
  "message": "Logged in"
}

3. Access Protected Resources

curl -X GET http://localhost:8080/api/sessions/current \
  -b cookies.txt
Response:
{
  "status": "success",
  "payload": {
    "_id": "6893eaba2ac0b16fa177be7d",
    "email": "[email protected]",
    "role": "user"
  }
}

Implementation Details

Password Hashing

Passwords are hashed using bcrypt via the createHash utility function from src/utils/index.js.

Password Validation

Password validation uses the passwordValidation utility function (from src/controllers/sessions.controller.js:33):
const isValidPassword = await passwordValidation(user, password);
if(!isValidPassword) return res.status(400).send({status:"error",error:"Incorrect password"});

Router Configuration

Routes are defined in src/routes/sessions.router.js:
router.post('/register', sessionsController.register);
router.post('/login', sessionsController.login);
router.get('/current', sessionsController.current);
router.get('/unprotectedLogin', sessionsController.unprotectedLogin);
router.get('/unprotectedCurrent', sessionsController.unprotectedCurrent);

Security Considerations

Hardcoded JWT Secret: The JWT secret tokenSecretJWT is hardcoded in the controller. Move this to environment variables:
const token = jwt.sign(userDto, process.env.JWT_SECRET, {expiresIn:"1h"});
Unprotected Endpoints: The /unprotectedLogin and /unprotectedCurrent endpoints store/expose the full user object including the hashed password. These should not be used in production.
Cookie Security: Consider adding httpOnly, secure, and sameSite flags to cookies:
res.cookie('coderCookie', token, {
  maxAge: 3600000,
  httpOnly: true,
  secure: true, // HTTPS only
  sameSite: 'strict'
})
Token Expiration: Tokens expire after 1 hour. After expiration, users must log in again. Consider implementing refresh tokens for better UX.

Users API

Manage user profiles after authentication

Adoptions API

Create adoptions as an authenticated user

Build docs developers (and LLMs) love