Skip to main content

Overview

The Church Management System API uses JSON Web Tokens (JWT) for secure authentication. After logging in, you’ll receive a token that must be included in the Authorization header for all protected endpoints.

Authentication Flow

1

Register a new account

Create a user account with an email, password, and role.
2

Login with credentials

Receive a JWT token valid for 1 hour.
3

Include token in requests

Add the token to the Authorization header as Bearer <token>.
4

Token verification

The API verifies your token and extracts user ID and role.

Registration

Create a new user account by sending a POST request to /api/auth/register.

Endpoint

POST /api/auth/register

Request Body

{
  "email": "[email protected]",
  "password": "yourPassword123",
  "role": "member",
  "invitedBy": "admin"
}

Parameters

FieldTypeRequiredDescription
emailstringYesUser’s email address (must be unique)
passwordstringYesPassword (minimum 6 characters)
rolestringYesUser role: pastor or member (case-insensitive)
invitedBystringNoWho invited this user

Example Request

curl -X POST http://localhost:3001/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "securePass456",
    "role": "member",
    "invitedBy": "[email protected]"
  }'

Response

{
  "success": true,
  "message": "Registeration Successful",
  "data": "A verification link has been sent to you. Kindly verify your email address"
}
Passwords are hashed using bcrypt with 10 salt rounds before storage. Plain text passwords are never stored.

Login

Authenticate with your credentials to receive a JWT token.

Endpoint

POST /api/auth/login

Request Body

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

Example Request

curl -X POST http://localhost:3001/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "securePassword123"
  }'

Response

{
  "success": true,
  "message": "Login Successful",
  "data": {
    "User": {
      "email": "[email protected]",
      "role": "pastor",
      "profile": {},
      "invitedBy": "admin",
      "isProfileComplete": false,
      "createdAt": "2026-03-07T10:30:00.000Z"
    },
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY1YTFjMmQ0ZTVmNmE3YjhkOWMxMjM0NSIsInJvbGUiOiJwYXN0b3IiLCJpYXQiOjE3MDk4MTQ2MDAsImV4cCI6MTcwOTgxODIwMH0.xYz123..."
  }
}

JWT Token Structure

The JWT token contains the following payload:
{
  "id": "65a1c2d4e5f6a7b8d9c12345",
  "role": "pastor",
  "iat": 1709814600,
  "exp": 1709818200
}
FieldDescription
idUser’s MongoDB ObjectId
roleUser’s role (pastor or member)
iatIssued at timestamp
expExpiration timestamp (1 hour from issue)
Tokens expire after 1 hour. You’ll need to login again to get a new token when it expires.

Using the Token

Include the JWT token in the Authorization header of all authenticated requests.

Header Format

Authorization: Bearer <your-token-here>

Example Authenticated Request

curl -X GET http://localhost:3001/api/users/profile \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Token Verification Process

The API’s verifyToken middleware performs the following checks:
  1. Looks for Authorization header (case-insensitive)
  2. Verifies the header starts with “Bearer”
  3. Extracts the token from Bearer <token>
  4. Verifies the token signature using JWT_SECRET
  5. Decodes and attaches user data to req.theUser
Implementation (src/middleware/authmiddleware.js:3-39):
const verifyToken = (req, res, next) => {
  let authHeader = req.headers.authorization || req.headers.Authorization;
  
  if (authHeader && authHeader.startsWith("Bearer")) {
    const theToken = authHeader.split(" ")[1];

    if (!theToken) {
      return res.status(400).send({
        success: false,
        message: "Access Denied",
        data: "Access Token not Found"
      });
    } else {
      try {
        const decode = jwt.verify(theToken, process.env.JWT_SECRET);
        req.theUser = decode; // Contains { id, role }
        next();
      } catch (err) {
        res.status(500).send({
          success: false,
          message: "Access Denied",
          data: err.message
        });
      }
    }
  } else {
    return res.status(400).send({
      success: false,
      message: "Access Denied",
      data: "Authorization missing"
    });
  }
};

Role-Based Access Control

The API implements role-based authorization to restrict access to certain endpoints.

Available Roles

RoleDescriptionAccess Level
pastorChurch pastor/leaderFull access to church management features
memberRegular church memberLimited access to member features

How Authorization Works

Protected routes use the authorizeRoles middleware to check user roles: Implementation (src/middleware/rolemidddleware.js:1-14):
const authorizeRoles = (theTokenRole) => {
  return (req, res, next) => {
    if (theTokenRole == req.theUser.role) {
      next();
    } else {
      res.status(403).send({
        success: false,
        message: "Access Denied",
        data: `The role '${req.theUser.role}' is not allowed for this route`
      });
    }
  }
}

Example: Role-Protected Endpoint

const verifyToken = require('./middleware/authmiddleware');
const authorizeRoles = require('./middleware/rolemidddleware');

// Only pastors can access this route
router.post('/church/create', 
  verifyToken, 
  authorizeRoles('pastor'), 
  createChurch
);

// Both pastors and members can access this route
router.get('/users/profile', 
  verifyToken, 
  getProfile
);

Authorization Error Response

If a user tries to access a route they don’t have permission for:
403 Forbidden
{
  "success": false,
  "message": "Access Denied",
  "data": "The role 'member' is not allowed for this route"
}

Common Authentication Errors

Missing Authorization Header

400 Bad Request
{
  "success": false,
  "message": "Access Denied",
  "data": "Authorization missing"
}
Solution: Include the Authorization: Bearer <token> header in your request.

Invalid or Expired Token

500 Internal Server Error
{
  "success": false,
  "message": "Access Denied",
  "data": "jwt expired"
}
Solution: Login again to get a new token.

Malformed Token Format

400 Bad Request
{
  "success": false,
  "message": "Access Denied",
  "data": "Access Token not Found"
}
Solution: Ensure your header is formatted as Bearer <token> with a space between “Bearer” and the token.

Security Best Practices

Environment Variables: Store your JWT_SECRET in the .env file and use a strong, random string (at least 32 characters).
Token Storage:
  • Frontend: Store tokens in memory or httpOnly cookies, not localStorage (XSS risk)
  • Mobile: Use secure storage like Keychain (iOS) or Keystore (Android)
  • Never expose tokens in URLs or logs
Password Security:
  • Passwords are hashed with bcrypt (10 salt rounds)
  • Minimum 6 characters enforced
  • Plain text passwords are never stored

Next Steps

API Reference

Explore all available endpoints and their authentication requirements

User Management

Learn how to manage user profiles and permissions

Build docs developers (and LLMs) love