pasetojar

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Nov 5, 2025 License: MIT Imports: 5 Imported by: 0

README

pasetojar

Go Reference Go Report Card

Minimal and idiomatic Go package for handling encrypted cookie sessions using PASETO (v4.local).

Features

  • 🔒 Secure: Uses PASETO v4.local for authenticated encryption
  • 🎯 Simple: Clean API with just three methods: Set, Get, and Clear
  • 📦 Minimal dependencies: Only depends on aidanwoods.dev/go-paseto

Installation

go get github.com/ppdx999/pasetojar

Quick Start

package main

import (
    "errors"
    "net/http"
    "time"

    paseto "aidanwoods.dev/go-paseto"
    "github.com/ppdx999/pasetojar"
)

type Session struct {
    UserID int64  `json:"user_id"`
    Role   string `json:"role"`
}

func main() {
    // Generate a symmetric key (store this securely!)
    key := paseto.NewV4SymmetricKey()

    // Configure cookie parameters
    params := pasetojar.CookieParams{
        Path:     "/",
        Domain:   "",
        MaxAge:   24 * time.Hour,
        Secure:   true,
        HttpOnly: true,
        SameSite: http.SameSiteStrictMode,
    }

    // Create a jar instance
    jar, err := pasetojar.New("session", key, params)
    if err != nil {
        panic(err)
    }

    // Set a cookie
    http.HandleFunc("/set-cookie", func(w http.ResponseWriter, r *http.Request) {
        session := Session{UserID: 42, Role: "admin"}
        if err := jar.Set(w, session); err != nil {
            http.Error(w, "Failed to set cookie", http.StatusInternalServerError)
            return
        }
        w.Write([]byte("Cookie set!"))
    })

    // Get a cookie
    http.HandleFunc("/get-cookie", func(w http.ResponseWriter, r *http.Request) {
        var session Session
        err := jar.Get(r, &session)
        if errors.Is(err, pasetojar.ErrCookieNotFound) {
            http.Error(w, "Not logged in", http.StatusUnauthorized)
            return
        } else if errors.Is(err, pasetojar.ErrInvalidToken) {
            http.Error(w, "Invalid or expired session", http.StatusUnauthorized)
            return
        } else if err != nil {
            http.Error(w, "Internal error", http.StatusInternalServerError)
            return
        }
        w.Write([]byte("Retrieved session for user ID: " + string(session.UserID)))
    })

    // Clear a cookie
    http.HandleFunc("/clear-cookie", func(w http.ResponseWriter, r *http.Request) {
        jar.Clear(w)
        w.Write([]byte("Cookie cleared!"))
    })

    http.ListenAndServe(":8080", nil)
}

API Reference

Creating a Jar
jar, err := pasetojar.New(name string, key paseto.V4SymmetricKey, params CookieParams) (*Jar, error)

Creates a new Jar instance. Returns ErrInvalidMaxAge if params.MaxAge <= 0.

Note: Session cookies (MaxAge=0) are not supported. All cookies must have a positive MaxAge.

err := jar.Set(w http.ResponseWriter, v any) error

Encrypts and stores a value in a cookie. The value must be JSON-serializable.

err := jar.Get(r *http.Request, out any) error

Retrieves and decrypts a cookie value. Returns:

  • ErrCookieNotFound if the cookie doesn't exist
  • ErrInvalidToken if the token is invalid, expired, or tampered with
jar.Clear(w http.ResponseWriter)

Deletes the cookie by setting it to expire immediately.

Getters
jar.Name() string                     // Returns the cookie name
jar.Key() paseto.V4SymmetricKey       // Returns the encryption key
jar.Params() CookieParams             // Returns the cookie parameters

Security Best Practices

  1. Generate and store keys securely:

    // Generate once and store in environment variable or secrets manager
    key := paseto.NewV4SymmetricKey()
    
  2. Use secure cookie settings in production:

    params := pasetojar.CookieParams{
        Path:     "/",
        MaxAge:   24 * time.Hour,
        Secure:   true,  // Require HTTPS
        HttpOnly: true,  // Prevent JavaScript access
        SameSite: http.SameSiteStrictMode,  // CSRF protection
    }
    
  3. Handle errors appropriately:

    if errors.Is(err, pasetojar.ErrCookieNotFound) {
        // User is not logged in
    } else if errors.Is(err, pasetojar.ErrInvalidToken) {
        // Session expired or tampered with - require re-authentication
    }
    

Why PASETO?

PASETO (Platform-Agnostic Security Tokens) provides:

  • Simplicity: No algorithm negotiation, one secure default
  • Security: Authenticated encryption prevents tampering
  • Modern cryptography: Uses proven, modern algorithms
  • No footguns: Designed to prevent common JWT mistakes

Comparison with JWT

Feature PASETO JWT
Algorithm selection One secure default Multiple algorithms (risky)
Encryption Built-in Optional (JWE is complex)
Tampering protection Always authenticated Depends on algorithm
Complexity Low High

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

Acknowledgments

Documentation

Overview

Package pasetojar provides a thin wrapper for secure cookie management using PASETO v4.local tokens.

This package offers a simple interface for storing encrypted data in HTTP cookies, leveraging the security of PASETO (Platform-Agnostic Security Tokens) for encryption and automatic expiration validation.

Basic usage:

key := paseto.NewV4SymmetricKey()
params := pasetojar.CookieParams{
	Path:     "/",
	MaxAge:   24 * time.Hour,
	Secure:   true,
	HttpOnly: true,
	SameSite: http.SameSiteStrictMode,
}
jar, err := pasetojar.New("session", key, params)
if err != nil {
	// Handle error (e.g., invalid MaxAge)
}

// Set a cookie
session := map[string]interface{}{"user_id": 42, "role": "admin"}
jar.Set(w, session)

// Get a cookie
var data map[string]interface{}
if err := jar.Get(r, &data); err != nil {
	if errors.Is(err, pasetojar.ErrCookieNotFound) {
		// Handle missing cookie
	}
}

// Clear a cookie
jar.Clear(w)

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrCookieNotFound is returned when the requested cookie is not present in the request.
	ErrCookieNotFound = errors.New("cookie not found")
	// ErrInvalidToken is returned when the token is invalid, expired, or tampered with.
	ErrInvalidToken = errors.New("invalid or expired token")
	// ErrInvalidMaxAge is returned when MaxAge is not greater than 0.
	ErrInvalidMaxAge = errors.New("MaxAge must be greater than 0")
)

Functions

This section is empty.

Types

type CookieParams

type CookieParams struct {
	// Path specifies the cookie path. Use "/" for the entire domain.
	Path string
	// Domain specifies the cookie domain. Empty string means current domain only.
	Domain string
	// MaxAge specifies cookie lifetime. Must be greater than 0.
	MaxAge time.Duration
	// Secure requires HTTPS. Should be true in production.
	Secure bool
	// HttpOnly prevents JavaScript access. Should be true for sensitive cookies.
	HttpOnly bool
	// SameSite controls cross-site request behavior.
	SameSite http.SameSite
}

CookieParams contains HTTP cookie configuration parameters.

Note: MaxAge must be greater than 0. Session cookies are not supported as encrypted session cookies have limited practical use cases.

For security best practices, it's recommended to set:

  • Secure: true (require HTTPS)
  • HttpOnly: true (prevent JavaScript access)
  • SameSite: http.SameSiteStrictMode or http.SameSiteLaxMode

type Jar

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

Jar handles encrypted cookie storage using PASETO v4.local tokens. It provides methods to securely set, get, and clear cookies with automatic encryption, decryption, and expiration validation.

All data stored in cookies is encrypted using PASETO v4.local, which provides authenticated encryption. The encrypted tokens include timestamps and are automatically validated for expiration when retrieved.

func New

func New(name string, key paseto.V4SymmetricKey, params CookieParams) (*Jar, error)

New creates a new Jar instance for managing encrypted cookies.

Returns ErrInvalidMaxAge if params.MaxAge is not greater than 0.

Parameters:

  • name: The cookie name that will be used in HTTP headers
  • key: A PASETO v4 symmetric key for encryption/decryption (generate with paseto.NewV4SymmetricKey())
  • params: Cookie configuration parameters (path, domain, security settings, etc.)

Example:

key := paseto.NewV4SymmetricKey()
params := pasetojar.CookieParams{
	Path:     "/",
	MaxAge:   24 * time.Hour,
	Secure:   true,
	HttpOnly: true,
	SameSite: http.SameSiteStrictMode,
}
jar, err := pasetojar.New("session", key, params)
if err != nil {
	// Handle error
}

func (*Jar) Clear

func (j *Jar) Clear(w http.ResponseWriter)

Clear removes the cookie by setting it to expire immediately.

This method sets the cookie's MaxAge to -1 and Expires to a past date, instructing the browser to delete the cookie. All other cookie parameters (Path, Domain, Secure, HttpOnly, SameSite) are preserved to ensure the cookie is properly matched and deleted.

Parameters:

  • w: The HTTP response writer where the cookie deletion will be set

Example:

// Log out user by clearing session cookie
jar.Clear(w)

func (*Jar) Get

func (j *Jar) Get(r *http.Request, out any) error

Get retrieves and decrypts the cookie value from the HTTP request.

The encrypted token is automatically validated for:

  • Cryptographic authenticity (prevents tampering)
  • Expiration time (if MaxAge was set)

Parameters:

  • r: The HTTP request containing the cookie
  • out: Pointer to a variable where the decrypted data will be stored

Returns:

  • ErrCookieNotFound: If the cookie is not present in the request
  • ErrInvalidToken: If the token is invalid, expired, or tampered with
  • Other errors: For unexpected failures

Example:

var session Session
err := jar.Get(r, &session)
if errors.Is(err, pasetojar.ErrCookieNotFound) {
	// User is not logged in
} else if errors.Is(err, pasetojar.ErrInvalidToken) {
	// Token expired or tampered with - require re-authentication
} else if err != nil {
	// Handle other errors
}

func (*Jar) Key

func (j *Jar) Key() paseto.V4SymmetricKey

Key returns the PASETO v4 symmetric key used for encryption and decryption.

func (*Jar) Name

func (j *Jar) Name() string

Name returns the cookie name used by this Jar.

func (*Jar) Params

func (j *Jar) Params() CookieParams

Params returns a copy of the cookie parameters used by this Jar.

func (*Jar) Set

func (j *Jar) Set(w http.ResponseWriter, v any) error

Set encrypts the given value and stores it as a cookie in the HTTP response.

The value is encrypted using PASETO v4.local and includes:

  • Issued-at timestamp
  • Expiration time (based on MaxAge)
  • The provided data in the "data" claim

The cookie will expire after the duration specified in MaxAge.

Parameters:

  • w: The HTTP response writer where the cookie will be set
  • v: The value to encrypt and store (must be serializable to JSON)

Returns:

  • error: Returns an error if encryption or serialization fails

Example:

session := Session{UserID: 42, Role: "admin"}
if err := jar.Set(w, session); err != nil {
	// Handle error
}

Jump to

Keyboard shortcuts

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