# Building a Secure REST API with GORM, Echo, JWT Token Authentication, and PostgreSQL in Go.

Combining GORM, a robust ORM library for Go, with Echo, a high-performance web framework, along with JWT token-based authentication and PostgreSQL, offers a solid foundation for developing secure and scalable RESTful APIs. In this detailed tutorial, we'll create a practical example showcasing the integration of GORM, Echo, JWT token authentication, and PostgreSQL to build a fully functional and secure REST API in Go.

## **Prerequisites**

Ensure you have the following prerequisites:

* Go installed on your machine
    
* PostgreSQL installed and running
    
* Basic knowledge of Go, SQL, and RESTful APIs
    

## **Setting Up the Project**

### **Initializing the Project**

Start by initializing a new Go module:

```go
go mod init your_project_name
```

Install the required dependencies:

```go
go get -u github.com/labstack/echo/v4
go get -u github.com/labstack/echo/v4/middleware
go get -u github.com/dgrijalva/jwt-go
go get -u github.com/jinzhu/gorm
go get -u github.com/jinzhu/gorm/dialects/postgres
```

### **Creating Database**

Create a PostgreSQL database and define a `users` table with columns `id`, `username`, `password`, and `email`.

## **Building the Secure REST API**

### **Setting Up Echo Server**

Create a new Go file, e.g., `main.go`, and set up the Echo server:

```go
package main

import (
	"time"

	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
	"github.com/dgrijalva/jwt-go"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/postgres"
)

var (
	db *gorm.DB
)

func init() {
	var err error
	dsn := "postgresql://user:password@localhost/database_name?sslmode=disable" // Update with your database credentials
	db, err = gorm.Open("postgres", dsn)
	if err != nil {
		panic("failed to connect to database")
	}

	// Auto migrate the User model
	db.AutoMigrate(&User{})
}

type User struct {
	gorm.Model
	Username string `json:"username"`
	Password string `json:"password"`
	Email    string `json:"email"`
}

func login(c echo.Context) error {
	username := c.FormValue("username")
	password := c.FormValue("password")

	var user User
	if err := db.Where("username = ?", username).First(&user).Error; err != nil {
		return echo.ErrUnauthorized
	}

	if user.Password != password {
		return echo.ErrUnauthorized
	}

	// Create JWT token
	token := jwt.New(jwt.SigningMethodHS256)
	claims := token.Claims.(jwt.MapClaims)
	claims["username"] = user.Username
	claims["exp"] = time.Now().Add(time.Hour * 24).Unix()

	t, err := token.SignedString([]byte("secret")) // Replace with your secret key
	if err != nil {
		return err
	}

	return c.JSON(200, map[string]string{
		"token": t,
	})
}

func restricted(c echo.Context) error {
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	username := claims["username"].(string)
	return c.String(200, "Welcome "+username+"!")
}

func main() {
	e := echo.New()

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())

	// Routes
	e.POST("/login", login)
	r := e.Group("/restricted")
	r.Use(middleware.JWT([]byte("secret"))) // Replace with your secret key
	r.GET("", restricted)

	// Start server
	e.Logger.Fatal(e.Start(":8080"))
}
```

### **Implementing JWT Token Authentication**

#### Login Endpoint

The POST `/login` endpoint authenticates users and generates a JWT token:

```go
func login(c echo.Context) error {
	// Authenticating user credentials
	// ...

	// Creating JWT token
	token := jwt.New(jwt.SigningMethodHS256)
	claims := token.Claims.(jwt.MapClaims)
	claims["username"] = user.Username
	claims["exp"] = time.Now().Add(time.Hour * 24).Unix()

	t, err := token.SignedString([]byte("secret")) // Replace with your secret key
	if err != nil {
		return err
	}

	return c.JSON(200, map[string]string{
		"token": t,
	})
}
```

#### Restricted Endpoint

The GET `/restricted` endpoint is restricted and requires a valid JWT token for access:

```go
func restricted(c echo.Context) error {
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	username := claims["username"].(string)
	return c.String(200, "Welcome "+username+"!")
}
```

### **Registering API Endpoints**

Add the new API endpoints to the Echo server:

```go
func main() {
	e := echo.New()

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())

	// Routes
	e.POST("/login", login)
	r := e.Group("/restricted")
	r.Use(middleware.JWT([]byte("secret"))) // Replace with your secret key
	r.GET("", restricted)

	// Start server
	e.Logger.Fatal(e.Start(":8080"))
}
```

## **Testing the Secure API**

Build and run the application:

```go
go run main.go
```

### **Testing Endpoints**

* To log in and obtain a token: `POST` [`http://localhost:8080/login`](http://localhost:8080/login) with credentials
    
* To access restricted endpoint: `GET` [`http://localhost:8080/restricted`](http://localhost:8080/restricted) with an obtained token in the Authorization header as `Bearer YOUR_TOKEN`
    

## **Conclusion**

The integration of GORM with Echo, along with JWT token-based authentication and PostgreSQL, enables the creation of secure and scalable RESTful APIs in Go. This example demonstrates the implementation of JWT token authentication to secure endpoints and provides a foundation for building authentication-based APIs in Go.

By extending this example, developers can implement user registration, authorization, token expiration, and further functionalities, leveraging the capabilities of GORM, Echo, and JWT tokens to build robust and secure APIs in Go.

I hope this helps, you!!

**More such articles:**

[https://medium.com/techwasti](Link)

[https://www.youtube.com/@maheshwarligade](https://www.youtube.com/@maheshwarligade)

[https://techwasti.com/series/spring-boot-tutorials](https://techwasti.com/series/spring-boot-tutorials)

[https://techwasti.com/series/go-language](https://techwasti.com/series/go-language)
