Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

A CRUD API with Go, using the Gin framework and MongoDB.

Hi, here we want to create a simple and clean RESTful API built with Golang (Gin), MongoDB, and JWT Authentication. This API allows you to register, log in, and perform user management operations securely. you can find the source code here…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Hi, here we want to create a simple and clean RESTful API built with Golang (Gin), MongoDB, and JWT Authentication.

This API allows you to register, log in, and perform user management operations securely.

you can find the source code here : sourcecode



Image description





📦 Features of Project




  • 🔑 User registration and login with secure password hashing

  • 🛡️ JWT-based authentication

  • 🔄 Full ‍‍CRUD operations for users

  • ✅ Input validation using go-playground/validator

  • 📚 Swagger documentation with swaggo/gin-swagger

  • 💾 MongoDB integration using mongo-driver

  • 🧪 Tests for core functionalities



⚙️ Prerequisites

‌Befor starting make sure that you have these :




  • latest version of go

  • postman or curl for api testing







🔨 Initializing a Go project:



First of all create a folder for project :




mkdir go-crud-api
cd go-crud-api






For initializing a Go project we usually run this command : go mod init . this command create a file (go.mod) in your directory , this file is using for dependency management of your project. so open your terminal & run this command go mod init then write this go mod init github.com/yourusername/go-crud-api in the file if you doesn't create any repo for your project you can just write go mod init my-project then change it to your repo address.




  • we use Gin for creating api :go get -u github.com/gin-gonic/gin









📁 Project structure






go-crud-api/

├── main.go
├── config/ ← Database settings and ...
│ └── db.go
├── controller/ ← Controllers (logic related to APIs)
│ └── user.go
├── model/ ← Data structures and models
│ └── user.go
├── middleware/ ← Middlewares (like auth)
│ └── authMiddleware.go
├── routes/ ← Routing
│ └── userRoutes.go
├── utils/ ← Helper functions (like ValidateToken)
│ └── jwt.go
├── go.mod / go.sum ← Package information
└── README.md ← Project description












🧠 Explain Code






1. go-crud-api/main.go






package main

import (
"crud-api-go/config"
"crud-api-go/routes"
"github.com/gin-gonic/gin"
)

func main() {
config.ConnectDB()
router := gin.Default()
routes.UserRoutes(router)
router.Run("localhost:8080")
}







  • The main function is the entry point of our program.


  • config.ConnectDB() : this line calls a function(ConnectDB)from config package. this function is responsible for establishing connection to your database.


  • router := gin.Default() : A router is a core of a web app , it determines how the app responds to different client request at different URL.


  • routes.UserRoutes(router) : This line calls a function userRoutes from the routes package,passing the Gin router as an argument.this function is responsible for defining all the API routes related to users (like creating, reading, updating, and deleting users).


  • router.Run("localhost:8080") : This line starts the Gin web server makes it listen for incoming HTTP requests on the address localhost:8080.







2. go-crud-api/config/db.go



Setting Up Our MongoDB Connection in Go**



Packages We Rely On:





  • time, context: Used for managing timeouts during the database connection process.


  • os, log, fmt: Essential for interacting with the operating system (reading environment variables), logging errors, and printing informational messages.


  • github.com/joho/godotenv: A library for loading environment variables from a .env file.

  • go.mongodb.org/mongo-driver/mongo & go.mongodb.org/mongo-driver/mongo/options: The official Go driver for MongoDB.


  • var DB *mongo.Database : Here, we declare a global variable DB of type *mongo.Database. This allows us to easily access the established database connection from anywhere in our Go application.


  • err := godotenv.Load() : We use the godotenv.Load() function to read key-value pairs from our .env file and make them available as environment variables within our application.





if err != nil {
log.Fatal("❌ Error loading .env file")
}






If the .env file failed to load the program execution will be halted.




mongoURI := os.Getenv("MONGO_URI")
databaseName := os.Getenv("DB_NAME")






with os.Getenv we get the environmental variable for connecting to database.



clientOptions := options.Client().ApplyURI(mongoURI) : This line is using for setup connection settings.




ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()






A context is created with a 10-second timeout to prevent the connection from hanging indefinitely. The defer cancel() ensures that the context's resources are released when the function exits.



client, err := mongo.Connect(ctx, clientOptions) : Here, we attempt to establish a connection to our MongoDB instance using the configured clientOptions and the context we created.



DB = client.Database(databaseName) : Finally we setup the database instance, so it's accessible through out the entire application.




package config

import (
"context"
"fmt"
"log"
"os"
"time"

"github.com/joho/godotenv"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)

var DB *mongo.Database

func ConnectDB() {
// Load environment variables
err := godotenv.Load()
if err != nil {
log.Fatal("❌ Error loading .env file")
}

// Get URI and database name from .env file
mongoURI := os.Getenv("MONGO_URI")
databaseName := os.Getenv("DB_NAME")

if mongoURI == "" {
log.Fatal("❌ MONGO_URI is not set in .env")
}
if databaseName == "" {
log.Fatal("❌ DB_NAME is not set in .env")
}

// Set up connection options
clientOptions := options.Client().ApplyURI(mongoURI)

// Create context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

// Connect to MongoDB
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal("❌ MongoDB connection error:", err)
}

// Ping the database to test connection
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal("❌ MongoDB ping error:", err)
}

fmt.Println("✅ Connected to MongoDB Atlas!")

// Set the selected database
DB = client.Database(databaseName)
}









3. go-crud-api/routes/userRoutes.go



This file is related to defining HTTP routes.we define public routes such as signup & login then we created a group of routes that are connected to the authentication middleware and include CRUD operations on users.




package routes

import (
"crud-api-go/controller"
"crud-api-go/middleware"

"github.com/gin-gonic/gin"
)

func UserRoutes(router *gin.Engine) {
router.POST("/signup", controller.Signup)
router.POST("/login", controller.Login)

protected := router.Group("/")
protected.Use(middleware.AuthMiddleware())
{
protected.GET("/users", controller.GetUsers)
protected.GET("/users/:id", controller.GetUserByID)
protected.POST("/users", controller.CreateUser)
protected.PUT("/users/:id", controller.UpdateUser)
protected.DELETE("/users/:id",controller.DeleteUser)
}
}







we define a function named UserRoutes.this function will be responsible for defining all the API endpoints related to the users. this function take a pointer to a gin .Engine as an argument. the gin.Engin is the main instance of the Gin router.




  • protected := router.Group("/") : this line creates a new route group using the router.Group("/") method.The / shows that all routes defined within this group will have a common base path.


  • protected.Use(middleware.AuthMiddleware()) : This means that for any request made to the routes defined within this group, the AuthMiddleware() function will be executed first.







4. go-crud-api/model/user.go



Model structures in this file are designed for three purposes: storing data in MongoDB (User), securely responding to clients (UserResponse and AuthResponse), and receiving input from clients for registration, login, or editing.




package model

import "go.mongodb.org/mongo-driver/bson/primitive"

type User struct {
ID primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"`
Name string `json:"name" bson:"name" validate:"required,min=2,max=50"`
Email string `json:"email" bson:"email" validate:"required,email"`
Password string `json:"password,omitempty" bson:"password,omitempty" validate:"required,min=6"`
}

type UserResponse struct {
ID primitive.ObjectID `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}

type AuthResponse struct {
Token string `json:"token"`
User UserResponse `json:"user"`
}

type SignupInput struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
}

type LoginInput struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
}

type CreateUserInput struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
}

type UpdateUserInput struct {
Name string `json:"name" validate:"required,min=2,max=50"`
Email string `json:"email" validate:"required,email"`
}









5. go-crud-api/controller/user.go



In this file we have 5 main controller functions for CRUD operations on users, all written using Gin and connected to the MongoDB database. We utilize input validation, and all requests, except for signup and login, require JWT authentication.




  • First of all we import packages , these packages are for interacting with the MongoDB database, managing time, performing validation, and the Gin framework for handling HTTP requests, config for database access and model for defining data structures.


  • Helper Function and Validation





func getUserCollection() *mongo.Collection {
return config.DB.Collection("users")
}






This function retrieves the MongoDB collection named users from the existing DB connection in the config package.




var validate = validator.New()






We use the 'validator' package to check user inputs (e.g., whether fields are required or the email structure is correct).




  • GetUsers : The GetUsers function retrieves a list of users from the database and responds in JSON format.


  • GetUserByID : Retrieving a specific user from the database by ID and responding in JSON format.


  • CreateUser : Creating a new user and saving it to MongoDB.


  • UpdateUser : Updating user information in the database based on the ID.


  • DeleteUser : Deleting a user from the database based on the ID.





package controller

import (
"context"
"crud-api-go/config"
"crud-api-go/model"
"net/http"
"time"

"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
)

func getUserCollection() *mongo.Collection {
return config.DB.Collection("users")
}

var validate = validator.New()

func GetUsers(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

cursur, err := getUserCollection().Find(ctx, bson.M{})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "error fetching users"})
return
}
defer cursur.Close(ctx)

var users []model.User
if err := cursur.All(ctx, &users); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "error parsing users"})
return
}

var userslist []model.UserResponse
for _, u := range users {
userslist = append(userslist, model.UserResponse{
ID: u.ID,
Name: u.Name,
Email: u.Email,
})
}
c.JSON(http.StatusOK, userslist)

}

func GetUserByID(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

idParam := c.Param("id")
objectId, err := primitive.ObjectIDFromHex(idParam)

if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID Format"})
return
}

var user model.User
err = getUserCollection().FindOne(ctx, bson.M{"_id": objectId}).Decode(&user)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
return
}
c.JSON(http.StatusOK, user)
}

func CreateUser(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

var input model.CreateUserInput
if err := c.BindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
return
}

if err := validate.Struct(input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

newUser := model.User{
ID: primitive.NewObjectID(),
Name: input.Name,
Email: input.Email,
Password: input.Password,
}

_, err := getUserCollection().InsertOne(ctx, newUser)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create user"})
return
}

c.JSON(http.StatusCreated, model.UserResponse{
ID: newUser.ID,
Name: newUser.Name,
Email: newUser.Email,
})
}

func UpdateUser(c *gin.Context) {
idParam := c.Param("id")

objectId, err := primitive.ObjectIDFromHex(idParam)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
}

var updatedUser model.UpdateUserInput
if err := c.BindJSON(&updatedUser); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON"})
return
}

if err := validate.Struct(updatedUser); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

update := bson.M{
"$set": bson.M{
"name": updatedUser.Name,
"email": updatedUser.Email,
},
}

res, err := getUserCollection().UpdateOne(ctx, bson.M{"_id": objectId}, update)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user"})
return
}

if res.MatchedCount == 0 {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}

c.JSON(http.StatusOK, gin.H{"message": "User updated successfully"})
}

func DeleteUser(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

idParam := c.Param("id")
objectId, err := primitive.ObjectIDFromHex(idParam)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID format"})
return
}

res, err := getUserCollection().DeleteOne(ctx, bson.M{"_id": objectId})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete user"})
return
}

if res.DeletedCount == 0 {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}

c.JSON(http.StatusOK, gin.H{"message": "User deleted"})
}









6. go-crud-api/controller/auth.go



In this file, we have two functions: Signup and Login. Signup registers a new user, hashes their password, and generates a JWT. Login verifies the user's email and password and, upon successful authentication, sends back a JWT. This token is subsequently used by the middleware for authentication.



Signup: This function handles new user registration. It takes user information, checks if the email is not already taken, hashes the password, and saves the user to the database. Finally, it returns a JWT token.



Login: This function is used for user login. It receives the email and password, and if they are valid, it generates a JWT token.




package controller

import (
"context"
"crud-api-go/model"
"crud-api-go/utils"
"net/http"
"strings"
"time"

"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"golang.org/x/crypto/bcrypt"
)

func Signup(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

var input model.SignupInput
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
return
}

var existingUser model.User
err := getUserCollection().FindOne(ctx, bson.M{"email": input.Email}).Decode(&existingUser)
if err == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "User already exists"})
return
}

hashedPassword, err := bcrypt.GenerateFromPassword([]byte(input.Password), bcrypt.DefaultCost)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to hash password"})
return
}

newUser := model.User{
ID: primitive.NewObjectID(),
Name: input.Name,
Email: strings.ToLower(input.Email),
Password: string(hashedPassword),
}

_, err = getUserCollection().InsertOne(ctx, newUser)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})
return
}

token, err := utils.GenerateJWT(newUser.Email)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create token"})
return
}

c.JSON(http.StatusCreated, model.AuthResponse{
Token: token,
User: model.UserResponse{
ID: newUser.ID,
Name: newUser.Name,
Email: newUser.Email,
},
})
}


func Login(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

var input model.LoginInput
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
return
}

var foundUser model.User
err := getUserCollection().FindOne(ctx, bson.M{"email": input.Email}).Decode(&foundUser)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid email or password"})
return
}

err = bcrypt.CompareHashAndPassword([]byte(foundUser.Password), []byte(input.Password))
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials. Please check your email and password"})
return
}

token, err := utils.GenerateJWT(foundUser.Email)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create token"})
return
}

c.JSON(http.StatusOK, model.AuthResponse{
Token: token,
User: model.UserResponse{
ID: foundUser.ID,
Name: foundUser.Name,
Email: foundUser.Email,
},
})
}










7. go-crud-api/middleware/authMiddleware.go



Here we createa middleware to protect sensitive routes that require authentication, using JWT tokens.

This middleware (AuthMiddleware()) checks the Authorization header. If it's in the Bearer <token> format, it extracts the token, validates it using the JWT secret, and if valid, adds the user's email to the context for subsequent use. If there's an issue, the request is aborted.




package middleware

import (
"crud-api-go/utils"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)

func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header missing"})
c.Abort()
return
}
const bearerPrefix = "Bearer "
if !strings.HasPrefix(authHeader, bearerPrefix) {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid Authorization header format"})
c.Abort()
return
}
tokenString := strings.TrimPrefix(authHeader, bearerPrefix)
claims, err := utils.ValidateToken(tokenString)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
c.Abort()
return
}
c.Set("userEmail", claims.Email)
c.Next()
}
}










8. ‍‍go-crud-api/utils/jwt.go



This file contains two key functions for working with JWT tokens.





  • GenerateJWT is used to create a token with the user's email and a 24-hour expiration time.


  • ValidateToken is used to verify the token's validity and retrieve the information it contains. The HS256 algorithm and an environment variable are used for signing to enhance security.




package utils

import (
"os"
"time"

"github.com/golang-jwt/jwt/v5"
)

var jwtKey = []byte(os.Getenv("JWT_SECRET"))

type Claims struct {
Email string `json:"email"`
jwt.RegisteredClaims
}

// Generate token
func GenerateJWT(email string) (string, error) {
expirationTime := time.Now().Add(24 * time.Hour)

claims := &Claims{
Email: email,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(expirationTime),
},
}

token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(jwtKey)
if err != nil {
return "", err
}

return tokenString, nil
}

// validate Token
func ValidateToken(tokenString string) (*Claims, error) {
claims := &Claims{}

token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})

if err != nil {
return nil, err
}

if !token.Valid {
return nil, jwt.ErrTokenInvalidClaims
}

return claims, nil
}










Now We've reached the end of this tutorial! I hope this guide has been helpful for you in building a simple and secure API with Go, Gin, MongoDB, and JWT.

go-crud-api



Thank you for reading! 🍀

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten A CRUD API with Go, using the Gin framework and MongoDB.

Thematisch verwandte Begriffe: CRUD, with, using, framework · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-18163 | IBM Financial Transaction Manager (FTM) for RedHat OpenShift could allow…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick