A robust and modular RESTful API built with Golang, using Firebase (Firestore) for data persistence. This project demonstrates professional backend development practices including a clean, layered architecture, JWT authentication, role-based authorization, input validation, and structured error handling.
- Modular Architecture: Clean separation of concerns using a layered structure (Handler, Service, Repository).
- JWT Authentication: Secure endpoints using a JWT-based authentication middleware.
- Role-Based Authorization (RBAC): Securely restricts access based on user roles. Features separate endpoints for public registration and admin-level user management.
- Configuration Management: Securely manages configuration and secrets using environment variables (
.env
file). - Input Validation: Strong server-side validation of request data using
go-playground/validator
. - Structured Error Handling: A custom error handling system to provide clear, consistent error responses for different scenarios.
- Firebase Integration: Uses the Firebase Admin SDK for Go to interact with Cloud Firestore.
The project follows a standard layered architecture to ensure maintainability and scalability.
.
├── cmd/
│ └── api/
│ └── main.go # Application entry point
├── internal/
│ ├── apierror/
│ │ └── apierror.go # Custom error types
│ ├── auth/
│ │ └── auth.go # JWT generation and middleware
│ ├── config/
│ │ └── firebase.go # Firebase initialization
│ ├── handler/
│ │ ├── auth_handler.go # HTTP handler for authentication
│ │ └── user_handler.go # HTTP handler for user resources
│ ├── model/
│ │ └── user.go # User data structure
│ ├── repository/
│ │ └── user_repository.go# Data access layer (Firestore)
│ ├── role/
│ │ └── role.go # Role constants and logic
│ └── service/
│ └── user_service.go # Business logic layer
├── .env # Local environment variables (gitignored)
├── .gitignore
├── go.mod
├── go.sum
└── serviceAccountKey.json # Firebase credentials (gitignored)
- Go version 1.18 or higher.
- A Google Firebase project with Firestore enabled.
Follow these steps to get the project running on your local machine.
-
Clone the repository:
git clone https://github.com/hermantrym/go-firebase-api.git cd go-firebase-api
-
Set up Firebase Credentials:
- Go to your Firebase project settings > Service Accounts.
- Click "Generate new private key" to download a JSON file.
- Rename the downloaded file to
serviceAccountKey.json
and place it in the root directory of the project.
-
Configure Environment Variables:
- Create a new file named
.env
in the root directory. You can copy the.env.example
file if it exists. - Open the
.env
file and set the required variables. See the Environment Variables section below for details.
- Create a new file named
-
Install Dependencies:
go mod tidy
-
Run the Application:
go run ./cmd/api/main.go
The server will start on
http://localhost:8080
.
- Method:
POST
- Path:
/login
- Description: Authenticates a user based on their email and returns a JWT if successful.
- Access: Public
Request Body:
{
"email": "user@example.com"
}
Success Response (200 OK):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
- Method:
POST
- Path:
/users
- Description: Creates a new user with a default "user" role. Any
role
field provided in the request body will be ignored for security reasons. - Access: Public
Request Body:
{
"name": "Budi Santoso",
"email": "budi.santoso@example.com"
}
Success Response (201 Created):
{
"id": "some-generated-id",
"name": "Budi Santoso",
"email": "budi.santoso@example.com",
"role": "user"
}
- Method:
GET
- Path:
/users/:id
- Description: Retrieves the details of a specific user.
- Access: Protected (Requires a valid JWT for any authenticated user)
Example Request:
TOKEN="<your-jwt>"
USER_ID="<user-id-to-fetch>"
curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/users/$USER_ID
Success Response (200 OK):
{
"id": "some-user-id",
"name": "Budi Santoso",
"email": "budi.santoso@example.com",
"role": "user"
}
- Method:
GET
- Path:
/admin/users
- Description: Retrieves a list of all users in the system.
- Access: Protected (Admin Only)
Example Request:
# Ensure this token belongs to a user with the 'admin' role
ADMIN_TOKEN="<your-admin-jwt>"
curl -H "Authorization: Bearer $ADMIN_TOKEN" http://localhost:8080/admin/users
Success Response (200 OK):
[
{
"id": "user-id-1",
"name": "Admin User",
"email": "admin@example.com",
"role": "admin"
},
{
"id": "user-id-2",
"name": "Budi Santoso",
"email": "budi.santoso@example.com",
"role": "user"
}
]
- Method:
POST
- Path:
/admin/users
- Description: Allows an admin to create a new user with a specific role. If the
role
is omitted, it defaults to "user". - Access: Protected (Admin Only)
Request Body:
{
"name": "Admin Baru",
"email": "admin.baru@example.com",
"role": "admin"
}
Example Request:
ADMIN_TOKEN="<your-admin-jwt>"
curl -X POST -H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Admin Baru", "email": "admin.baru@example.com", "role": "admin"}' \
http://localhost:8080/admin/users
Success Response (200 OK):
{
"id": "another-generated-id",
"name": "Admin Baru",
"email": "admin.baru@example.com",
"role": "admin"
}
These variables must be defined in a .env
file in the project root.
Variable | Description | Example |
---|---|---|
FIREBASE_SERVICE_ACCOUNT_KEY_PATH |
The file path to your Firebase service account JSON credentials. | ./serviceAccountKey.json |
JWT_SECRET_KEY |
A long, random, and secret string used to sign and verify JWTs. | a-very-strong-and-random-secret-key |
- Go: The core programming language.
- Gin: A high-performance HTTP web framework.
- Firebase Admin SDK: For connecting to Cloud Firestore.
- JWT-Go: For generating and validating JSON Web Tokens.
- Go-Playground Validator: For request data validation.
- Role-Based Access Control (RBAC): Restricts access to specific endpoints based on user roles.
- Password Hashing: Implement
bcrypt
for secure password storage and authentication. - Unit & Integration Tests: Write comprehensive tests for all layers of the application.
- Structured Logging: Integrate a logging library like
Logrus
orZap
for better log management. - Dockerize the Application: Create a
Dockerfile
to containerize the application for easier deployment.
This project is licensed under the MIT License. See the LICENSE file for details.