codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🐹

Go (Golang)

59 / 72 topics
55Security Best Practices for Go Apps56Input Validation57Secure Coding Practices58Encryption and Decryption in Go59Authentication and Authorization
Tutorials/Go (Golang)/Authentication and Authorization
🐹Go (Golang)

Authentication and Authorization

Updated 2026-04-20
2 min read

Authentication and Authorization in Go (Golang)

Introduction

Authentication and authorization are fundamental aspects of securing any application, ensuring that only authorized users can access specific resources. In this tutorial, we'll explore how to implement robust authentication and authorization mechanisms using Go (Golang). We'll cover the basics of authentication, including user registration, login, and token-based sessions, as well as authorization strategies such as role-based access control (RBAC).

Prerequisites

Before diving into the implementation, ensure you have the following:

  • Basic knowledge of Go programming.
  • Familiarity with HTTP servers in Go using packages like net/http.
  • Understanding of JSON for data interchange.

Setting Up the Project

First, create a new directory for your project and initialize it with Go modules:

mkdir auth-tutorial
cd auth-tutorial
go mod init auth-tutorial

We'll use the following dependencies:

  • github.com/gorilla/mux for routing.
  • github.com/dgrijalva/jwt-go for JSON Web Tokens (JWT) handling.
  • golang.org/x/crypto/bcrypt for password hashing.

Install these packages using:

go get -u github.com/gorilla/mux
go get -u github.com/dgrijalva/jwt-go
go get -u golang.org/x/crypto/bcrypt

User Registration and Login

Step 1: Define the User Model

Create a models directory and define a user model:

// models/user.go
package models

type User struct {
    ID       string `json:"id"`
    Username string `json:"username"`
    Password string `json:"password,omitempty"`
}

Step 2: Implement Registration

Create a handlers directory and implement the registration handler:

// handlers/auth.go
package handlers

import (
    "auth-tutorial/models"
    "encoding/json"
    "golang.org/x/crypto/bcrypt"
    "net/http"
)

func Register(w http.ResponseWriter, r *http.Request) {
    var user models.User
    err := json.NewDecoder(r.Body).Decode(&user)
    if err != nil {
        http.Error(w, "Invalid request payload", http.StatusBadRequest)
        return
    }

    // Hash the password
    hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
    if err != nil {
        http.Error(w, "Failed to hash password", http.StatusInternalServerError)
        return
    }
    user.Password = string(hashedPassword)

    // Save the user (in-memory for simplicity)
    users[user.Username] = user

    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(user)
}

var users = make(map[string]models.User)

Step 3: Implement Login

Add the login handler:

func Login(w http.ResponseWriter, r *http.Request) {
    var credentials struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    err := json.NewDecoder(r.Body).Decode(&credentials)
    if err != nil {
        http.Error(w, "Invalid request payload", http.StatusBadRequest)
        return
    }

    user, exists := users[credentials.Username]
    if !exists {
        http.Error(w, "User not found", http.StatusUnauthorized)
        return
    }

    // Compare the provided password with the stored hash
    err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(credentials.Password))
    if err != nil {
        http.Error(w, "Invalid credentials", http.StatusUnauthorized)
        return
    }

    // Generate a JWT token
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
        "username": user.Username,
    })
    signedToken, err := token.SignedString([]byte("secret"))
    if err != nil {
        http.Error(w, "Failed to generate token", http.StatusInternalServerError)
        return
    }

    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(map[string]string{"token": signedToken})
}

Authorization with JWT

Step 1: Middleware for Authentication

Create a middleware to authenticate requests using JWT:

// middlewares/auth.go
package middlewares

import (
    "auth-tutorial/models"
    "encoding/json"
    "github.com/dgrijalva/jwt-go"
    "net/http"
)

func AuthMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        tokenString := r.Header.Get("Authorization")
        if tokenString == "" {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }

        token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
            if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
                return nil, jwt.ErrSignatureInvalid
            }
            return []byte("secret"), nil
        })

        if err != nil || !token.Valid {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }

        claims, ok := token.Claims.(jwt.MapClaims)
        if !ok {
            http.Error(w, "Invalid token claims", http.StatusInternalServerError)
            return
        }

        username := claims["username"].(string)
        user, exists := users[username]
        if !exists {
            http.Error(w, "User not found", http.StatusUnauthorized)
            return
        }

        r = r.WithContext(context.WithValue(r.Context(), "user", &user))
        next.ServeHTTP(w, r)
    })
}

Step 2: Role-Based Access Control (RBAC)

Define roles and implement RBAC:

// models/user.go
type User struct {
    ID       string `json:"id"`
    Username string `json:"username"`
    Password string `json:"password,omitempty"`
    Role     string `json:"role"`
}

const (
    AdminRole = "admin"
    UserRole  = "user"
)

// middlewares/rbac.go
package middlewares

import (
    "auth-tutorial/models"
    "net/http"
)

func RBACMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        user := r.Context().Value("user").(*models.User)
        if user.Role != models.AdminRole {
            http.Error(w, "Forbidden", http.StatusForbidden)
            return
        }
        next.ServeHTTP(w, r)
    })
}

Putting It All Together

Create the main application file:

// main.go
package main

import (
    "auth-tutorial/handlers"
    "auth-tutorial/middlewares"
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

func main() {
    r := mux.NewRouter()

    // Public routes
    r.HandleFunc("/register", handlers.Register).Methods("POST")
    r.HandleFunc("/login", handlers.Login).Methods("POST")

    // Protected routes with authentication and RBAC
    protectedRoutes := r.PathPrefix("/admin").Subrouter()
    protectedRoutes.Use(middlewares.AuthMiddleware)
    protectedRoutes.Use(middlewares.RBACMiddleware)
    protectedRoutes.HandleFunc("/dashboard", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Welcome to the admin dashboard!"))
    }).Methods("GET")

    log.Println("Server is running on :8080")
    if err := http.ListenAndServe(":8080", r); err != nil {
        log.Fatal(err)
    }
}

Testing the Application

You can test the application using tools like curl or Postman. Here are some example requests:

Register a User

curl -X POST http://localhost:8080/register \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "password123"}'

Login and Get Token

curl -X POST http://localhost:8080/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "password123"}'

Access Protected Route

Use the token obtained from login to access protected routes:

curl -X GET http://localhost:8080/admin/dashboard \
-H "Authorization: <token>"

Best Practices

  • Secure Password Storage: Always hash passwords using a strong algorithm like bcrypt.
  • Token Expiry and Refresh: Implement token expiry and refresh mechanisms for better security.
  • Environment Variables: Store sensitive information like JWT secret keys in environment variables.
  • HTTPS: Use HTTPS to encrypt data in transit.

Conclusion

In this tutorial, we've covered the basics of authentication and authorization in Go using JWT. We implemented user registration, login, and protected routes with RBAC. These concepts are essential for securing your applications and ensuring that only authorized users can access sensitive resources.


PreviousEncryption and Decryption in GoNext Performance Tuning Techniques

Recommended Gear

Encryption and Decryption in GoPerformance Tuning Techniques