auth

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2025 License: MIT Imports: 15 Imported by: 1

README

Authentication Module

The Authentication module provides comprehensive authentication capabilities for the Modular framework, including JWT tokens, session management, password hashing, and OAuth2/OIDC integration.

Features

  • JWT Token Management: Generate, validate, and refresh JWT tokens with custom claims
  • Password Security: Secure password hashing using bcrypt with configurable strength requirements
  • Session Management: Create, manage, and track user sessions with configurable storage backends
  • OAuth2/OIDC Support: Integration with OAuth2 providers like Google, GitHub, etc.
  • Flexible Storage: Pluggable user and session storage interfaces with in-memory implementations included
  • Security: Built-in protection against common authentication vulnerabilities

Installation

go get github.com/GoCodeAlone/modular/modules/auth

Configuration

Basic Configuration
auth:
  jwt:
    secret: "your-jwt-secret-key"
    expiration: "24h"
    refresh_expiration: "168h"
    issuer: "your-app-name"
  
  password:
    min_length: 8
    require_upper: true
    require_lower: true
    require_digit: true
    require_special: false
    bcrypt_cost: 12
  
  session:
    store: "memory"
    cookie_name: "session_id"
    max_age: "24h"
    secure: true
    http_only: true
OAuth2 Configuration
auth:
  oauth2:
    providers:
      google:
        client_id: "your-google-client-id"
        client_secret: "your-google-client-secret"
        redirect_url: "http://localhost:8080/auth/google/callback"
        scopes: ["openid", "email", "profile"]
        auth_url: "https://accounts.google.com/o/oauth2/auth"
        token_url: "https://oauth2.googleapis.com/token"
        user_info_url: "https://www.googleapis.com/oauth2/v2/userinfo"

Usage

Basic Setup
package main

import (
    "github.com/GoCodeAlone/modular"
    "github.com/GoCodeAlone/modular/modules/auth"
)

func main() {
    app := modular.NewApplication()
    
    // Register the auth module
    app.RegisterModule(auth.NewModule())
    
    // Start the application
    app.Start()
}
Using the Auth Service
// Get the auth service from the application
var authService auth.AuthService
err := app.GetService(auth.ServiceName, &authService)
if err != nil {
    log.Fatal(err)
}

// Hash a password
hashedPassword, err := authService.HashPassword("userpassword123")
if err != nil {
    log.Fatal(err)
}

// Verify a password
err = authService.VerifyPassword(hashedPassword, "userpassword123")
if err != nil {
    log.Println("Invalid password")
}

// Generate JWT tokens
customClaims := map[string]interface{}{
    "email": "user@example.com",
    "roles": []string{"user", "admin"},
    "permissions": []string{"read", "write"},
}

tokenPair, err := authService.GenerateToken("user-123", customClaims)
if err != nil {
    log.Fatal(err)
}

// Validate a token
claims, err := authService.ValidateToken(tokenPair.AccessToken)
if err != nil {
    log.Println("Invalid token:", err)
    return
}

log.Printf("User ID: %s, Email: %s", claims.UserID, claims.Email)
Session Management
// Create a session
metadata := map[string]interface{}{
    "ip_address": "127.0.0.1",
    "user_agent": "Mozilla/5.0...",
}

session, err := authService.CreateSession("user-123", metadata)
if err != nil {
    log.Fatal(err)
}

// Get a session
retrievedSession, err := authService.GetSession(session.ID)
if err != nil {
    log.Println("Session not found:", err)
    return
}

// Refresh a session (extend expiration)
refreshedSession, err := authService.RefreshSession(session.ID)
if err != nil {
    log.Fatal(err)
}

// Delete a session
err = authService.DeleteSession(session.ID)
if err != nil {
    log.Fatal(err)
}
OAuth2 Integration
// Get OAuth2 authorization URL
state := "random-state-string"
authURL, err := authService.GetOAuth2AuthURL("google", state)
if err != nil {
    log.Fatal(err)
}

// Redirect user to authURL...

// Exchange authorization code for user info
code := "authorization-code-from-callback"
result, err := authService.ExchangeOAuth2Code("google", code, state)
if err != nil {
    log.Fatal(err)
}

log.Printf("OAuth2 Result: %+v", result)
Custom User and Session Stores

You can implement custom storage backends by implementing the UserStore and SessionStore interfaces:

type DatabaseUserStore struct {
    db *sql.DB
}

func (s *DatabaseUserStore) GetUser(ctx context.Context, userID string) (*auth.User, error) {
    // Implement database query
}

func (s *DatabaseUserStore) CreateUser(ctx context.Context, user *auth.User) error {
    // Implement database insert
}

// Implement other UserStore methods...

// Register custom stores
app.RegisterService("user_store", &DatabaseUserStore{db: db})
app.RegisterService("session_store", &RedisSessionStore{client: redisClient})

API Reference

AuthService Interface

The main authentication service interface provides the following methods:

JWT Operations
  • GenerateToken(userID string, claims map[string]interface{}) (*TokenPair, error)
  • ValidateToken(token string) (*Claims, error)
  • RefreshToken(refreshToken string) (*TokenPair, error)
Password Operations
  • HashPassword(password string) (string, error)
  • VerifyPassword(hashedPassword, password string) error
  • ValidatePasswordStrength(password string) error
Session Operations
  • CreateSession(userID string, metadata map[string]interface{}) (*Session, error)
  • GetSession(sessionID string) (*Session, error)
  • DeleteSession(sessionID string) error
  • RefreshSession(sessionID string) (*Session, error)
OAuth2 Operations
  • GetOAuth2AuthURL(provider, state string) (string, error)
  • ExchangeOAuth2Code(provider, code, state string) (*OAuth2Result, error)
Data Structures
User
type User struct {
    ID           string                 `json:"id"`
    Email        string                 `json:"email"`
    PasswordHash string                 `json:"-"`
    Roles        []string               `json:"roles"`
    Permissions  []string               `json:"permissions"`
    Active       bool                   `json:"active"`
    CreatedAt    time.Time              `json:"created_at"`
    UpdatedAt    time.Time              `json:"updated_at"`
    LastLoginAt  *time.Time             `json:"last_login_at,omitempty"`
    Metadata     map[string]interface{} `json:"metadata,omitempty"`
}
Session
type Session struct {
    ID        string                 `json:"id"`
    UserID    string                 `json:"user_id"`
    CreatedAt time.Time              `json:"created_at"`
    ExpiresAt time.Time              `json:"expires_at"`
    IPAddress string                 `json:"ip_address"`
    UserAgent string                 `json:"user_agent"`
    Active    bool                   `json:"active"`
    Metadata  map[string]interface{} `json:"metadata,omitempty"`
}
TokenPair
type TokenPair struct {
    AccessToken  string    `json:"access_token"`
    RefreshToken string    `json:"refresh_token"`
    TokenType    string    `json:"token_type"`
    ExpiresIn    int64     `json:"expires_in"`
    ExpiresAt    time.Time `json:"expires_at"`
}

Testing

The module includes comprehensive tests covering all functionality:

cd modules/auth
go test -v
Test Coverage
  • Configuration validation
  • JWT token generation and validation
  • Password hashing and verification
  • Session management
  • OAuth2 integration
  • Memory store implementations
  • Module lifecycle and dependency injection

Security Considerations

  1. JWT Secret: Use a strong, randomly generated secret for JWT signing
  2. Password Hashing: bcrypt cost should be at least 12 for production
  3. Session Security: Enable secure and httpOnly flags for session cookies
  4. OAuth2: Validate state parameters to prevent CSRF attacks
  5. Token Expiration: Set appropriate expiration times for access and refresh tokens

Examples

See the examples/ directory for complete usage examples including:

  • Basic authentication setup
  • OAuth2 integration
  • Custom middleware implementation
  • Database integration patterns

Dependencies

  • github.com/golang-jwt/jwt/v5 - JWT token handling
  • golang.org/x/crypto - Password hashing
  • golang.org/x/oauth2 - OAuth2 client implementation

License

This module is part of the Modular framework and is licensed under the same terms.

Documentation

Index

Constants

View Source
const (
	// ServiceName is the name used to register the auth service
	ServiceName = "auth"
)

Variables

View Source
var (
	ErrInvalidConfig      = errors.New("invalid auth configuration")
	ErrInvalidCredentials = errors.New("invalid credentials")
	ErrTokenExpired       = errors.New("token has expired")
	ErrTokenInvalid       = errors.New("token is invalid")
	ErrTokenMalformed     = errors.New("token is malformed")
	ErrUserNotFound       = errors.New("user not found")
	ErrUserAlreadyExists  = errors.New("user already exists")
	ErrPasswordTooWeak    = errors.New("password does not meet requirements")
	ErrSessionNotFound    = errors.New("session not found")
	ErrSessionExpired     = errors.New("session has expired")
	ErrOAuth2Failed       = errors.New("oauth2 authentication failed")
	ErrProviderNotFound   = errors.New("oauth2 provider not found")
)

Auth module specific errors

Functions

func NewModule

func NewModule() modular.Module

NewModule creates a new authentication module

Types

type AuthContext

type AuthContext struct {
	User        *User    `json:"user"`
	Session     *Session `json:"session"`
	Claims      *Claims  `json:"claims"`
	Permissions []string `json:"permissions"`
	Roles       []string `json:"roles"`
}

AuthContext represents authentication context in HTTP requests

type AuthService

type AuthService interface {
	// JWT operations
	GenerateToken(userID string, claims map[string]interface{}) (*TokenPair, error)
	ValidateToken(token string) (*Claims, error)
	RefreshToken(refreshToken string) (*TokenPair, error)

	// Password operations
	HashPassword(password string) (string, error)
	VerifyPassword(hashedPassword, password string) error
	ValidatePasswordStrength(password string) error

	// Session operations
	CreateSession(userID string, metadata map[string]interface{}) (*Session, error)
	GetSession(sessionID string) (*Session, error)
	DeleteSession(sessionID string) error
	RefreshSession(sessionID string) (*Session, error)

	// OAuth2 operations
	GetOAuth2AuthURL(provider, state string) (string, error)
	ExchangeOAuth2Code(provider, code, state string) (*OAuth2Result, error)
}

AuthService defines the main authentication service interface

type Claims

type Claims struct {
	UserID      string                 `json:"user_id"`
	Email       string                 `json:"email"`
	Roles       []string               `json:"roles"`
	Permissions []string               `json:"permissions"`
	IssuedAt    time.Time              `json:"iat"`
	ExpiresAt   time.Time              `json:"exp"`
	Issuer      string                 `json:"iss"`
	Subject     string                 `json:"sub"`
	Custom      map[string]interface{} `json:"custom,omitempty"`
}

Claims represents JWT token claims

type Config

type Config struct {
	JWT      JWTConfig      `yaml:"jwt"`
	Session  SessionConfig  `yaml:"session"`
	OAuth2   OAuth2Config   `yaml:"oauth2"`
	Password PasswordConfig `yaml:"password"`
}

Config represents the authentication module configuration

func (*Config) Validate

func (c *Config) Validate() error

Validate validates the authentication configuration

type JWTConfig

type JWTConfig struct {
	Secret            string        `yaml:"secret" required:"true"`
	Expiration        time.Duration `yaml:"expiration" default:"24h"`
	RefreshExpiration time.Duration `yaml:"refresh_expiration" default:"168h"` // 7 days
	Issuer            string        `yaml:"issuer" default:"modular-auth"`
	Algorithm         string        `yaml:"algorithm" default:"HS256"`
}

JWTConfig contains JWT-related configuration

type MemorySessionStore

type MemorySessionStore struct {
	// contains filtered or unexported fields
}

MemorySessionStore implements SessionStore interface using in-memory storage

func NewMemorySessionStore

func NewMemorySessionStore() *MemorySessionStore

NewMemorySessionStore creates a new in-memory session store

func (*MemorySessionStore) Cleanup

func (s *MemorySessionStore) Cleanup(ctx context.Context) error

Cleanup removes expired sessions

func (*MemorySessionStore) Delete

func (s *MemorySessionStore) Delete(ctx context.Context, sessionID string) error

Delete removes a session

func (*MemorySessionStore) Get

func (s *MemorySessionStore) Get(ctx context.Context, sessionID string) (*Session, error)

Get retrieves a session by ID

func (*MemorySessionStore) Store

func (s *MemorySessionStore) Store(ctx context.Context, session *Session) error

Store stores a session

type MemoryUserStore

type MemoryUserStore struct {
	// contains filtered or unexported fields
}

MemoryUserStore implements UserStore interface using in-memory storage

func NewMemoryUserStore

func NewMemoryUserStore() *MemoryUserStore

NewMemoryUserStore creates a new in-memory user store

func (*MemoryUserStore) CreateUser

func (s *MemoryUserStore) CreateUser(ctx context.Context, user *User) error

CreateUser creates a new user

func (*MemoryUserStore) DeleteUser

func (s *MemoryUserStore) DeleteUser(ctx context.Context, userID string) error

DeleteUser deletes a user

func (*MemoryUserStore) GetUser

func (s *MemoryUserStore) GetUser(ctx context.Context, userID string) (*User, error)

GetUser retrieves a user by ID

func (*MemoryUserStore) GetUserByEmail

func (s *MemoryUserStore) GetUserByEmail(ctx context.Context, email string) (*User, error)

GetUserByEmail retrieves a user by email

func (*MemoryUserStore) UpdateUser

func (s *MemoryUserStore) UpdateUser(ctx context.Context, user *User) error

UpdateUser updates an existing user

type Middleware

type Middleware interface {
	RequireAuth(next http.Handler) http.Handler
	OptionalAuth(next http.Handler) http.Handler
	RequireRole(role string) func(http.Handler) http.Handler
	RequirePermission(permission string) func(http.Handler) http.Handler
}

Middleware defines authentication middleware interface

type Module

type Module struct {
	// contains filtered or unexported fields
}

Module implements the modular.Module interface for authentication

func (*Module) Constructor

func (m *Module) Constructor() modular.ModuleConstructor

Constructor provides dependency injection for the module

func (*Module) Dependencies

func (m *Module) Dependencies() []string

Dependencies returns the module dependencies

func (*Module) Init

func (m *Module) Init(app modular.Application) error

Init initializes the authentication module

func (*Module) Name

func (m *Module) Name() string

Name returns the module name

func (*Module) ProvidesServices

func (m *Module) ProvidesServices() []modular.ServiceProvider

ProvidesServices returns the services provided by this module

func (*Module) RegisterConfig

func (m *Module) RegisterConfig(app modular.Application) error

RegisterConfig registers the module's configuration

func (*Module) RequiresServices

func (m *Module) RequiresServices() []modular.ServiceDependency

RequiresServices returns the services required by this module

func (*Module) Start

func (m *Module) Start(ctx context.Context) error

Start starts the authentication module

func (*Module) Stop

func (m *Module) Stop(ctx context.Context) error

Stop stops the authentication module

type OAuth2Config

type OAuth2Config struct {
	Providers map[string]OAuth2Provider `yaml:"providers"`
}

OAuth2Config contains OAuth2/OIDC configuration

type OAuth2Provider

type OAuth2Provider struct {
	ClientID     string   `yaml:"client_id" required:"true"`
	ClientSecret string   `yaml:"client_secret" required:"true"`
	RedirectURL  string   `yaml:"redirect_url" required:"true"`
	Scopes       []string `yaml:"scopes"`
	AuthURL      string   `yaml:"auth_url"`
	TokenURL     string   `yaml:"token_url"`
	UserInfoURL  string   `yaml:"user_info_url"`
}

OAuth2Provider represents an OAuth2 provider configuration

type OAuth2Result

type OAuth2Result struct {
	Provider     string                 `json:"provider"`
	UserInfo     map[string]interface{} `json:"user_info"`
	AccessToken  string                 `json:"access_token"`
	RefreshToken string                 `json:"refresh_token"`
	ExpiresAt    time.Time              `json:"expires_at"`
}

OAuth2Result represents the result of OAuth2 authentication

type PasswordConfig

type PasswordConfig struct {
	Algorithm      string `yaml:"algorithm" default:"bcrypt"` // bcrypt, argon2
	MinLength      int    `yaml:"min_length" default:"8"`
	RequireUpper   bool   `yaml:"require_upper" default:"true"`
	RequireLower   bool   `yaml:"require_lower" default:"true"`
	RequireDigit   bool   `yaml:"require_digit" default:"true"`
	RequireSpecial bool   `yaml:"require_special" default:"false"`
	BcryptCost     int    `yaml:"bcrypt_cost" default:"12"`
}

PasswordConfig contains password-related configuration

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service implements the AuthService interface

func NewService

func NewService(config *Config, userStore UserStore, sessionStore SessionStore) *Service

NewService creates a new authentication service

func (*Service) CreateSession

func (s *Service) CreateSession(userID string, metadata map[string]interface{}) (*Session, error)

CreateSession creates a new user session

func (*Service) DeleteSession

func (s *Service) DeleteSession(sessionID string) error

DeleteSession removes a session

func (*Service) ExchangeOAuth2Code

func (s *Service) ExchangeOAuth2Code(provider, code, state string) (*OAuth2Result, error)

ExchangeOAuth2Code exchanges an OAuth2 authorization code for user info

func (*Service) GenerateToken

func (s *Service) GenerateToken(userID string, customClaims map[string]interface{}) (*TokenPair, error)

GenerateToken creates a new JWT token pair

func (*Service) GetOAuth2AuthURL

func (s *Service) GetOAuth2AuthURL(provider, state string) (string, error)

GetOAuth2AuthURL returns the OAuth2 authorization URL for a provider

func (*Service) GetSession

func (s *Service) GetSession(sessionID string) (*Session, error)

GetSession retrieves a session by ID

func (*Service) HashPassword

func (s *Service) HashPassword(password string) (string, error)

HashPassword hashes a password using bcrypt

func (*Service) RefreshSession

func (s *Service) RefreshSession(sessionID string) (*Session, error)

RefreshSession extends a session's expiration time

func (*Service) RefreshToken

func (s *Service) RefreshToken(refreshTokenString string) (*TokenPair, error)

RefreshToken creates a new token pair using a refresh token

func (*Service) ValidatePasswordStrength

func (s *Service) ValidatePasswordStrength(password string) error

ValidatePasswordStrength validates password against configured requirements

func (*Service) ValidateToken

func (s *Service) ValidateToken(tokenString string) (*Claims, error)

ValidateToken validates a JWT token and returns the claims

func (*Service) VerifyPassword

func (s *Service) VerifyPassword(hashedPassword, password string) error

VerifyPassword verifies a password against its hash

type Session

type Session struct {
	ID        string                 `json:"id"`
	UserID    string                 `json:"user_id"`
	CreatedAt time.Time              `json:"created_at"`
	ExpiresAt time.Time              `json:"expires_at"`
	IPAddress string                 `json:"ip_address"`
	UserAgent string                 `json:"user_agent"`
	Active    bool                   `json:"active"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
}

Session represents a user session

type SessionConfig

type SessionConfig struct {
	Store      string        `yaml:"store" default:"memory"` // memory, redis, database
	CookieName string        `yaml:"cookie_name" default:"session_id"`
	MaxAge     time.Duration `yaml:"max_age" default:"24h"`
	Secure     bool          `yaml:"secure" default:"true"`
	HTTPOnly   bool          `yaml:"http_only" default:"true"`
	SameSite   string        `yaml:"same_site" default:"strict"` // strict, lax, none
	Domain     string        `yaml:"domain"`
	Path       string        `yaml:"path" default:"/"`
}

SessionConfig contains session-related configuration

type SessionStore

type SessionStore interface {
	Store(ctx context.Context, session *Session) error
	Get(ctx context.Context, sessionID string) (*Session, error)
	Delete(ctx context.Context, sessionID string) error
	Cleanup(ctx context.Context) error // Remove expired sessions
}

SessionStore defines the interface for session storage operations

type TokenPair

type TokenPair struct {
	AccessToken  string    `json:"access_token"`
	RefreshToken string    `json:"refresh_token"`
	TokenType    string    `json:"token_type"`
	ExpiresIn    int64     `json:"expires_in"`
	ExpiresAt    time.Time `json:"expires_at"`
}

TokenPair represents an access token and refresh token pair

type User

type User struct {
	ID           string                 `json:"id"`
	Email        string                 `json:"email"`
	PasswordHash string                 `json:"-"` // Never serialize password hash
	Roles        []string               `json:"roles"`
	Permissions  []string               `json:"permissions"`
	Active       bool                   `json:"active"`
	CreatedAt    time.Time              `json:"created_at"`
	UpdatedAt    time.Time              `json:"updated_at"`
	LastLoginAt  *time.Time             `json:"last_login_at,omitempty"`
	Metadata     map[string]interface{} `json:"metadata,omitempty"`
}

User represents a user in the authentication system

type UserStore

type UserStore interface {
	GetUser(ctx context.Context, userID string) (*User, error)
	GetUserByEmail(ctx context.Context, email string) (*User, error)
	CreateUser(ctx context.Context, user *User) error
	UpdateUser(ctx context.Context, user *User) error
	DeleteUser(ctx context.Context, userID string) error
}

UserStore defines the interface for user storage operations

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL