Gin framework: add HTTP basic authentication Middleware

introduce

Through a complete example, add HTTP basic authentication middleware to the micro service based on Gin framework.

What is HTTP basic authentication middleware?

The verification middleware will intercept each API request and verify the verification of Basic Auth or X-API-Key.

We will use rk-boot To start the microservices of the Gin framework.

Please visit the following address for a complete tutorial: https://rkdocs.netlify.app/cn

install

go get github.com/rookie-ninja/rk-boot

Quick start

The boot.yaml file describes the original information of Gin framework startup. Rk boot starts Gin by reading boot.yaml.

For verification, we started commonService. commonService contains a series of general API s.
Details: CommonService

sw is also launched to provide the Swagger UI.

In this step, we start Basic Auth with the user name and password user:pass.

---
gin:
  - name: greeter                   # Required, name of gin entry
    port: 8080                      # Required, port of gin entry
    enabled: true                   # Required, enable gin entry
    commonService:
      enabled: true                 # Optional, enable common service
    sw:
      enabled: true                 # Optional, enabled Swagger UI
    interceptors:
      auth:
        enabled: true               # Optional, enable auth middleware
        basic: ["user:pass"]        # Optional, basic auth credentials

2. Create main.go

The basic auth & API key option is added in the Swagger Config file of CommonService by default.

If you want to add Swagger validation options to your API, refer to swag security Official website, we will introduce it in other examples.

package main

import (
    "context"
    "github.com/rookie-ninja/rk-boot"
)

// Application entrance.
func main() {
    // Create a new boot instance.
    boot := rkboot.NewBoot()

    // Bootstrap
    boot.Bootstrap(context.Background())

    // Wait for shutdown sig
    boot.WaitForShutdownSig(context.Background())
}

3. Folder structure

$ tree
.
├── boot.yaml
├── go.mod
├── go.sum
└── main.go

0 directories, 4 files

4. Start main.go

$ go run main.go

5. Verification

Without Basic Auth, we get 401 error code.

$ curl -X GET localhost:8080/rk/v1/healthy
# This is RK style error code if unauthorized
{
    "error":{
        "code":401,
        "status":"Unauthorized",
        "message":"Missing authorization, provide one of bellow auth header:[Basic Auth]",
        "details":[]
    }
}

Try it with the Swagger UI. visit http://localhost : 8080/sw, send the request directly, and we will still get 401 error.

Basic Auth is provided. For security reasons, Auth in the Request Header needs to be encoded with Base64. We Base64 encode the user:pass string.

$ curl localhost:8080/rk/v1/healthy -H "Authorization: Basic dXNlcjpwYXNz"
{
    "healthy":true
}

Click [lock] in Swagger UI to add Basic Auth.

Use X-API-Key authorization mode

1. Modify boot.yaml

In this step, we start X-API-Key, and the value of the key is token.

---
gin:
  - name: greeter                   # Required, name of gin entry
    port: 8080                      # Required, port of gin entry
    enabled: true                   # Required, enable gin entry
    commonService:
      enabled: true                 # Optional, enable common service
    sw:
      enabled: true                 # Optional, enabled Swagger UI
    interceptors:
      auth:
        enabled: true               # Optional, enable auth middleware
        apiKey: [ "token" ]         # Optional, enable X-API-Key auth

2. Start main.go

$ go run main.go

3. Verification

In the same case, we get 401 error code without providing X-API-Key.

$ curl  -X GET localhost:8080/rk/v1/healthy
# This is RK style error code if unauthorized
{
    "error":{
        "code":401,
        "status":"Unauthorized",
        "message":"Missing authorization, provide one of bellow auth header:[X-API-Key]",
        "details":[]
    }
}
$ curl localhost:8080/rk/v1/healthy -H "X-API-Key: token"
{
    "healthy":true
}

Ignore request path

We can add a series of API request paths to make the middleware ignore and verify these API requests.

---
gin:
  - name: greeter                           # Required, name of gin entry
    port: 8080                              # Required, port of gin entry
    enabled: true                           # Required, enable gin entry
    commonService:
      enabled: true                         # Optional, enable common service
    sw:
      enabled: true                         # Optional, enabled Swagger UI
    interceptors:
      auth:
        enabled: true                       # Optional, enable auth middleware
        basic: ["user:pass"]                # Optional, basic auth credentials
        ignorePrefix: ["/rk/v1/healthy"]    # Optional, ignoring path with prefix

Add Swag Security Annotation

This time, let's see how to add security related annotation s to swag.

Add the following annotation in the main() function to define security.

// @securityDefinitions.basic BasicAuth
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name X-API-Key

Add the following annotation to the Handler function.

// @Security ApiKeyAuth
// @Security BasicAuth

Examples are as follows:

// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main

import (
    "context"
    "fmt"
    "github.com/gin-gonic/gin"
    "github.com/rookie-ninja/rk-boot"
    "net/http"
)

// @title RK Swagger for Gin
// @version 1.0
// @description This is a greeter service with rk-boot.

// @securityDefinitions.basic BasicAuth

// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name X-API-Key

// Application entrance.
func main() {
    // Create a new boot instance.
    boot := rkboot.NewBoot()

    // Register handler
    boot.GetGinEntry("greeter").Router.GET("/v1/greeter", Greeter)

    // Bootstrap
    boot.Bootstrap(context.Background())

    // Wait for shutdown sig
    boot.WaitForShutdownSig(context.Background())
}

// @Summary Greeter service
// @Id 1
// @version 1.0
// @produce application/json
// @Param name query string true "Input name"
// @Security ApiKeyAuth
// @Security BasicAuth
// @Success 200 {object} GreeterResponse
// @Router /v1/greeter [get]
func Greeter(ctx *gin.Context) {
    ctx.JSON(http.StatusOK, &GreeterResponse{
        Message: fmt.Sprintf("Hello %s!", ctx.Query("name")),
    })
}

// Response.
type GreeterResponse struct {
    Message string
}

Regenerate the swagger config file with the swag command line and start main.go.

Tags: security Microservices api Middleware

Posted by pastijalan on Tue, 09 Nov 2021 23:57:05 +0530