oneauth

package module
v0.0.17 Latest Latest
Warning

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

Go to latest
Published: Jan 11, 2026 License: Apache-2.0 Imports: 18 Imported by: 3

README

OneAuth

A Go authentication library providing unified local and OAuth-based authentication with support for multiple authentication methods per user account.

Features

  • Unified authentication: Password and OAuth through a single interface
  • Multi-provider support: One account accessible via password, Google, GitHub, etc.
  • Separation of concerns: Users, identities, and authentication channels as distinct concepts
  • Flexible storage: Database-agnostic store interfaces with file-based reference implementation
  • Email workflows: Built-in email verification and password reset flows
  • Security focused: bcrypt password hashing, secure token generation, single-use tokens
  • Testing friendly: No HTTP server required, uses httptest for isolated testing
  • gRPC support: Authentication context utilities and interceptors for gRPC services
  • Production ready: Flexible validation with sensible defaults, comprehensive error handling, and documentation (use database-backed stores for production scale)

Quick Start

Install the package:

go get github.com/panyam/oneauth

Set up stores and authentication:

import (
    "github.com/panyam/oneauth"
    "github.com/panyam/oneauth/stores"
)

// Initialize stores
storagePath := "/path/to/storage"
userStore := stores.NewFSUserStore(storagePath)
identityStore := stores.NewFSIdentityStore(storagePath)
channelStore := stores.NewFSChannelStore(storagePath)
tokenStore := stores.NewFSTokenStore(storagePath)

// Create authentication callbacks
createUser := oneauth.NewCreateUserFunc(userStore, identityStore, channelStore)
validateCreds := oneauth.NewCredentialsValidator(identityStore, channelStore, userStore)
verifyEmail := oneauth.NewVerifyEmailFunc(identityStore, tokenStore)
updatePassword := oneauth.NewUpdatePasswordFunc(identityStore, channelStore)

// Configure local authentication
localAuth := &oneauth.LocalAuth{
    CreateUser:          createUser,
    ValidateCredentials: validateCreds,
    EmailSender:         &oneauth.ConsoleEmailSender{},
    TokenStore:          tokenStore,
    BaseURL:             "https://yourapp.com",
    VerifyEmail:         verifyEmail,
    UpdatePassword:      updatePassword,
    HandleUser:          yourSessionHandler,
}

// Set up HTTP routes
mux := http.NewServeMux()
mux.Handle("/auth/login", localAuth)
mux.Handle("/auth/signup", http.HandlerFunc(localAuth.HandleSignup))
mux.Handle("/auth/verify-email", http.HandlerFunc(localAuth.HandleVerifyEmail))
mux.Handle("/auth/forgot-password", http.HandlerFunc(localAuth.HandleForgotPassword))
mux.Handle("/auth/reset-password", http.HandlerFunc(localAuth.HandleResetPassword))

Architecture

OneAuth separates authentication into three layers:

User: A unique account containing profile information.

Identity: An email address or phone number with verification status. Identities can be used across multiple authentication channels.

Channel: An authentication mechanism (password, Google, GitHub) storing provider-specific credentials.

This design allows users to sign in with multiple methods while maintaining a single account.

Core Concepts

Multiple Authentication Methods

A user can authenticate via different methods using the same email:

User: john@example.com
├── Channel: local (password authentication)
├── Channel: google (OAuth)
└── Channel: github (OAuth)

All three channels access the same account and data.

Global Identity Verification

Verifying an email through any channel verifies it for all channels:

  • Sign up with password → email unverified
  • Log in with Google → email automatically verified for both password and Google login
Provider-Specific Data

Each channel stores its own credentials and profile:

  • Local channel: bcrypt password hash, username
  • Google channel: OAuth tokens, Google profile data
  • GitHub channel: OAuth tokens, GitHub profile data

gRPC Authentication

OneAuth provides gRPC authentication utilities in the grpc subpackage for passing user identity between HTTP gateways and gRPC services.

Context Utilities
import oagrpc "github.com/panyam/oneauth/grpc"

// In your gRPC gateway, inject user ID into metadata
md := metadata.Pairs(oagrpc.DefaultMetadataKeyUserID, userID)
ctx = metadata.NewOutgoingContext(ctx, md)

// In your gRPC service, extract user ID from context
userID := oagrpc.UserIDFromContext(ctx)
if userID == "" {
    return nil, status.Error(codes.Unauthenticated, "not authenticated")
}
Auth Interceptors
import oagrpc "github.com/panyam/oneauth/grpc"

// Require authentication for all methods
server := grpc.NewServer(
    grpc.UnaryInterceptor(oagrpc.UnaryAuthInterceptor(nil)),
    grpc.StreamInterceptor(oagrpc.StreamAuthInterceptor(nil)),
)

// Allow some methods to be public
config := oagrpc.NewPublicMethodsConfig(
    "/pkg.Service/PublicMethod",
    "/pkg.Service/AnotherPublicMethod",
)
server := grpc.NewServer(
    grpc.UnaryInterceptor(oagrpc.UnaryAuthInterceptor(config)),
)

// Optional auth (allow unauthenticated requests)
server := grpc.NewServer(
    grpc.UnaryInterceptor(oagrpc.UnaryAuthInterceptor(oagrpc.OptionalAuthConfig())),
)

See the Developer Guide for complete gRPC integration documentation.

Documentation

Store Interfaces

OneAuth defines four store interfaces for data persistence:

UserStore

Manages user accounts with profile data.

type UserStore interface {
    CreateUser(userId string, isActive bool, profile map[string]any) (User, error)
    GetUserById(userId string) (User, error)
    SaveUser(user User) error
}
IdentityStore

Manages contact information and verification status.

type IdentityStore interface {
    GetIdentity(identityType, identityValue string, createIfMissing bool) (*Identity, bool, error)
    SaveIdentity(identity *Identity) error
    SetUserForIdentity(identityType, identityValue string, newUserId string) error
    MarkIdentityVerified(identityType, identityValue string) error
    GetUserIdentities(userId string) ([]*Identity, error)
}
ChannelStore

Manages authentication methods and credentials.

type ChannelStore interface {
    GetChannel(provider, identityKey string, createIfMissing bool) (*Channel, bool, error)
    SaveChannel(channel *Channel) error
    GetChannelsByIdentity(identityKey string) ([]*Channel, error)
}
TokenStore

Manages verification and password reset tokens.

type TokenStore interface {
    CreateToken(userID, email string, tokenType TokenType, expiryDuration time.Duration) (*AuthToken, error)
    GetToken(token string) (*AuthToken, error)
    DeleteToken(token string) error
    DeleteUserTokens(userID string, tokenType TokenType) error
}

File-Based Stores

The stores package provides file-based implementations suitable for development and small applications:

import "github.com/panyam/oneauth/stores"

userStore := stores.NewFSUserStore("/path/to/storage")
identityStore := stores.NewFSIdentityStore("/path/to/storage")
channelStore := stores.NewFSChannelStore("/path/to/storage")
tokenStore := stores.NewFSTokenStore("/path/to/storage")

For production use with larger user bases, implement the store interfaces backed by your database.

Authentication Flows

User Registration
POST /auth/signup
Content-Type: application/x-www-form-urlencoded

username=johndoe&email=john@example.com&password=secret123

Response:

{
  "success": true,
  "user": {
    "username": "johndoe",
    "email": "john@example.com"
  }
}
User Login
POST /auth/login
Content-Type: application/x-www-form-urlencoded

email=john@example.com&password=secret123

Response:

{
  "success": true,
  "user": {
    "username": "johndoe"
  }
}
Email Verification
GET /auth/verify-email?token=abc123...

Response:

{
  "success": true,
  "message": "Email verified successfully"
}
Password Reset Request
POST /auth/forgot-password
Content-Type: application/x-www-form-urlencoded

email=john@example.com

Response:

{
  "success": true,
  "message": "If that email exists, a reset link has been sent"
}
Password Reset
POST /auth/reset-password
Content-Type: application/x-www-form-urlencoded

token=xyz789...&password=newsecret456

Response:

{
  "success": true,
  "message": "Password reset successfully",
  "email": "john@example.com"
}

Validation

Default Rules
  • Username: 3-20 characters, alphanumeric with underscore and hyphen
  • Email: Valid email format
  • Phone: Minimum 10 digits
  • Password: Minimum 8 characters
  • At least one of email or phone required
Custom Validation
localAuth.ValidateSignup = func(creds *oneauth.Credentials) error {
    if len(creds.Password) < 12 {
        return fmt.Errorf("password must be at least 12 characters")
    }
    // Add custom validation logic
    return nil
}

Email Integration

Development

Use the console email sender for development:

localAuth.EmailSender = &oneauth.ConsoleEmailSender{}

Emails are printed to stdout instead of being sent.

Production

Implement the SendEmail interface for your email service:

type SendEmail interface {
    SendVerificationEmail(to string, verificationLink string) error
    SendPasswordResetEmail(to string, resetLink string) error
}

Example with SMTP:

type SMTPSender struct {
    host, username, password string
    port int
}

func (s *SMTPSender) SendVerificationEmail(to, link string) error {
    // SMTP implementation
}

func (s *SMTPSender) SendPasswordResetEmail(to, link string) error {
    // SMTP implementation
}

Session Management

The HandleUser callback is invoked after successful authentication:

HandleUser: func(authtype, provider string, token *oauth2.Token,
                userInfo map[string]any, w http.ResponseWriter, r *http.Request) {
    // token is nil for local auth, populated for OAuth

    sessionID := generateSessionID()
    sessionStore.Save(sessionID, userInfo)

    http.SetCookie(w, &http.Cookie{
        Name:     "session_id",
        Value:    sessionID,
        HttpOnly: true,
        Secure:   true,
    })

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]any{
        "success": true,
        "user":    userInfo,
    })
}

Testing

Test handlers without a running server:

func TestLogin(t *testing.T) {
    tmpDir, _ := os.MkdirTemp("", "test-*")
    defer os.RemoveAll(tmpDir)

    // Set up stores and auth
    userStore := stores.NewFSUserStore(tmpDir)
    // ... configure localAuth

    // Create request
    form := url.Values{}
    form.Set("email", "test@example.com")
    form.Set("password", "password123")

    req := httptest.NewRequest(http.MethodPost, "/auth/login",
                                strings.NewReader(form.Encode()))
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

    rr := httptest.NewRecorder()
    localAuth.ServeHTTP(rr, req)

    if rr.Code != http.StatusOK {
        t.Errorf("Expected 200, got %d", rr.Code)
    }
}

Security

Password Storage

Passwords are hashed using bcrypt with default cost. Plain-text passwords are never stored.

Token Security
  • Verification tokens: 32 bytes, hex-encoded (64 characters)
  • Expiry: 24 hours for email verification, 1 hour for password reset
  • Single-use tokens automatically deleted after consumption
  • Expired tokens rejected and cleaned up automatically
Best Practices
  1. Use HTTPS in production
  2. Implement rate limiting at the HTTP handler level
  3. Add CSRF protection in application middleware
  4. Implement session timeouts
  5. Log authentication events
  6. Store secrets in environment variables or secret managers

Examples

Complete example applications are planned for a future release. See the test files (local_test.go, auth_flows_test.go) for usage examples in the meantime.

Limitations & Extensibility

OneAuth is designed to be flexible and extensible. Some features are intentionally left to the application layer:

File-Based Stores
  • Development & small apps: Suitable for <1000 users
  • Production: Implement database-backed stores for larger scale
Application Responsibilities

The following are intentionally not provided by OneAuth and should be implemented at the application level:

  • Rate limiting: Protect authentication endpoints from brute force attacks
  • CSRF protection: Add CSRF tokens to forms and validate them in your middleware
  • Session management: Use established session libraries (scs, gorilla/sessions, etc.)
  • Account lockout: Implement after repeated failed login attempts
  • Email service: Provide production email sender (ConsoleEmailSender is for development only)

See the Developer Guide for implementation patterns and best practices.

Requirements

  • Go 1.21 or later
  • golang.org/x/crypto/bcrypt for password hashing (required)
  • golang.org/x/oauth2 for OAuth providers (optional)

License

See LICENSE file for terms and conditions.

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines.

Support

  • Documentation: DEVELOPER_GUIDE.md and USER_GUIDE.md
  • Issues: GitHub Issues
  • Discussions: GitHub Discussions

Documentation

Overview

Package oneauth provides a unified authentication framework for Go applications.

OneAuth separates authentication concerns into three layers: users, identities, and channels. This design enables multiple authentication methods per user while maintaining a single account.

Architecture

User: A unique account in your system. Users are identified by a user ID and contain profile information.

Identity: A contact method (email address or phone number) that belongs to a user. Identities have verification status and can be shared across multiple authentication channels.

Channel: An authentication mechanism (local password, Google OAuth, GitHub OAuth) connected to an identity. Channels store provider-specific credentials and profile data.

Basic Usage

Set up stores for users, identities, channels, and tokens:

import (
    "github.com/panyam/oneauth"
    "github.com/panyam/oneauth/stores"
)

storagePath := "/path/to/storage"
userStore := stores.NewFSUserStore(storagePath)
identityStore := stores.NewFSIdentityStore(storagePath)
channelStore := stores.NewFSChannelStore(storagePath)
tokenStore := stores.NewFSTokenStore(storagePath)

Create authentication callbacks:

createUser := oneauth.NewCreateUserFunc(userStore, identityStore, channelStore)
validateCreds := oneauth.NewCredentialsValidator(identityStore, channelStore, userStore)
verifyEmail := oneauth.NewVerifyEmailFunc(identityStore, tokenStore)
updatePassword := oneauth.NewUpdatePasswordFunc(identityStore, channelStore)

Configure local authentication:

localAuth := &oneauth.LocalAuth{
    CreateUser:          createUser,
    ValidateCredentials: validateCreds,
    EmailSender:         &oneauth.ConsoleEmailSender{},
    TokenStore:          tokenStore,
    BaseURL:             "https://yourapp.com",
    VerifyEmail:         verifyEmail,
    UpdatePassword:      updatePassword,
    HandleUser: func(authtype, provider string, token *oauth2.Token,
                    userInfo map[string]any, w http.ResponseWriter, r *http.Request) {
        // Create session and respond
    },
}

Set up HTTP handlers:

mux := http.NewServeMux()
mux.Handle("/auth/login", localAuth)
mux.Handle("/auth/signup", http.HandlerFunc(localAuth.HandleSignup))
mux.Handle("/auth/verify-email", http.HandlerFunc(localAuth.HandleVerifyEmail))
mux.Handle("/auth/forgot-password", http.HandlerFunc(localAuth.HandleForgotPassword))
mux.Handle("/auth/reset-password", http.HandlerFunc(localAuth.HandleResetPassword))

Store Implementations

OneAuth provides file-based store implementations in the stores package, suitable for development and small applications. For production use with larger user bases, implement the store interfaces backed by your database.

Security

Passwords are hashed using bcrypt with default cost. Verification and password reset tokens are cryptographically secure 32-byte values, hex-encoded to 64 characters. Tokens expire automatically (24 hours for verification, 1 hour for password reset) and are deleted after single use.

Testing

Authentication handlers can be tested without a running HTTP server using httptest.NewRequest and httptest.ResponseRecorder. Tests use temporary storage directories for complete isolation.

Index

Constants

View Source
const (
	TokenExpiryEmailVerification = 24 * time.Hour // 24 hours
	TokenExpiryPasswordReset     = 1 * time.Hour  // 1 hour
)

Default token expiry durations

Variables

This section is empty.

Functions

func DetectUsernameType added in v0.0.13

func DetectUsernameType(username string) string

DetectUsernameType attempts to detect what type of username was provided

func GenerateSecureToken added in v0.0.13

func GenerateSecureToken() (string, error)

GenerateSecureToken generates a cryptographically secure random token

func IdentityKey added in v0.0.13

func IdentityKey(identityType, identityValue string) string

IdentityKey creates a consistent identity key from type and value

Types

type AuthToken added in v0.0.13

type AuthToken struct {
	Token     string    `json:"token"`
	Type      TokenType `json:"type"`
	UserID    string    `json:"user_id"`
	Email     string    `json:"email"`
	CreatedAt time.Time `json:"created_at"`
	ExpiresAt time.Time `json:"expires_at"`
}

AuthToken represents a verification or reset token

func (*AuthToken) IsExpired added in v0.0.13

func (t *AuthToken) IsExpired() bool

IsExpired checks if a token has expired

func (*AuthToken) IsValid added in v0.0.13

func (t *AuthToken) IsValid(expectedType TokenType) bool

IsValid checks if a token is valid (not expired and matches type)

type AuthUserStore added in v0.0.13

type AuthUserStore interface {
	UserStore
	IdentityStore
	ChannelStore

	// EnsureAuthUser orchestrates user creation/lookup across stores
	// This is the main entry point for OAuth and local authentication
	EnsureAuthUser(authtype string, provider string, token *oauth2.Token, userInfo map[string]any) (User, error)
}

AuthUserStore combines the store interfaces needed for authentication

type BasicUser

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

BasicUser is a simple implementation of the User interface

func (*BasicUser) Id

func (b *BasicUser) Id() string

func (*BasicUser) Profile added in v0.0.9

func (b *BasicUser) Profile() map[string]any

type Channel added in v0.0.13

type Channel struct {
	Provider    string         `json:"provider"`     // "local", "google", "github"
	IdentityKey string         `json:"identity_key"` // "email:john@example.com"
	Credentials map[string]any `json:"credentials"`  // password_hash, access_token, etc.
	Profile     map[string]any `json:"profile"`      // optional data from provider
	CreatedAt   time.Time      `json:"created_at"`
	UpdatedAt   time.Time      `json:"updated_at"`
}

Channel represents an authentication mechanism/provider

type ChannelStore added in v0.0.13

type ChannelStore interface {
	// GetChannel gets or optionally creates a channel
	GetChannel(provider string, identityKey string, createIfMissing bool) (channel *Channel, newCreated bool, err error)

	// SaveChannel creates or updates a channel (upsert)
	SaveChannel(channel *Channel) error

	// GetChannelsByIdentity returns all channels for an identity
	GetChannelsByIdentity(identityKey string) ([]*Channel, error)
}

ChannelStore manages authentication channels/providers

type ConsoleEmailSender added in v0.0.13

type ConsoleEmailSender struct{}

ConsoleEmailSender is a development implementation that logs emails to console

func (*ConsoleEmailSender) SendPasswordResetEmail added in v0.0.13

func (c *ConsoleEmailSender) SendPasswordResetEmail(to string, resetLink string) error

func (*ConsoleEmailSender) SendVerificationEmail added in v0.0.13

func (c *ConsoleEmailSender) SendVerificationEmail(to string, verificationLink string) error

type CreateUserFunc added in v0.0.13

type CreateUserFunc func(creds *Credentials) (User, error)

CreateUserFunc creates a new user with the given credentials

func NewCreateUserFunc added in v0.0.13

func NewCreateUserFunc(userStore UserStore, identityStore IdentityStore, channelStore ChannelStore) CreateUserFunc

NewCreateUserFunc creates a CreateUserFunc from stores

type Credentials added in v0.0.13

type Credentials struct {
	Username string  // Required for signup, can be username/email/phone for login
	Email    *string // Optional for signup
	Phone    *string // Optional for signup
	Password string  // Required
}

Credentials represents user credentials for signup or login

type CredentialsValidator added in v0.0.13

type CredentialsValidator func(username, password, usernameType string) (User, error)

CredentialsValidator validates credentials during login and returns the user

func NewCredentialsValidator added in v0.0.13

func NewCredentialsValidator(identityStore IdentityStore, channelStore ChannelStore, userStore UserStore) CredentialsValidator

NewCredentialsValidator creates a CredentialsValidator from stores

type HandleUserFunc added in v0.0.9

type HandleUserFunc func(authtype string, provider string, token *oauth2.Token, userInfo map[string]any, w http.ResponseWriter, r *http.Request)

type Identity added in v0.0.13

type Identity struct {
	Type      string    `json:"type"`     // "email", "phone"
	Value     string    `json:"value"`    // "john@example.com", "+1-555-1234"
	UserID    string    `json:"user_id"`  // which user owns this identity
	Verified  bool      `json:"verified"` // has any channel verified this identity?
	CreatedAt time.Time `json:"created_at"`
}

Identity represents a contact method (email, phone) that can be verified

type IdentityStore added in v0.0.13

type IdentityStore interface {
	// GetIdentity gets or optionally creates an identity
	GetIdentity(identityType, identityValue string, createIfMissing bool) (identity *Identity, newCreated bool, err error)

	// SaveIdentity creates or updates an identity (upsert)
	SaveIdentity(identity *Identity) error

	// SetUserForIdentity associates an identity with a user
	SetUserForIdentity(identityType, identityValue string, newUserId string) error

	// MarkIdentityVerified marks an identity as verified
	MarkIdentityVerified(identityType, identityValue string) error

	// GetUserIdentities returns all identities for a user
	GetUserIdentities(userId string) ([]*Identity, error)
}

IdentityStore manages contact identities (email, phone)

type LocalAuth added in v0.0.9

type LocalAuth struct {
	// Validates credentials during login
	ValidateCredentials CredentialsValidator

	// Validates credentials during signup
	ValidateSignup SignupValidator

	// Creates a new user (for signup)
	CreateUser CreateUserFunc

	// Optional email sender for verification emails
	EmailSender SendEmail

	// Optional token store for email verification and password reset
	TokenStore TokenStore

	// Base URL for generating verification/reset links
	BaseURL string

	// Whether email verification is required before login
	RequireEmailVerification bool

	// Provider name (defaults to "local")
	Provider string

	// Form field names
	UsernameField string
	PasswordField string
	EmailField    string
	PhoneField    string

	// Handler called after successful authentication
	HandleUser HandleUserFunc

	// Callback to verify email by token
	VerifyEmail VerifyEmailFunc

	// Callback to update password
	UpdatePassword UpdatePasswordFunc
}

Allows local username/password based authentication

func (*LocalAuth) HandleForgotPassword added in v0.0.13

func (a *LocalAuth) HandleForgotPassword(w http.ResponseWriter, r *http.Request)

HandleForgotPassword handles forgot password requests (POST)

func (*LocalAuth) HandleForgotPasswordForm added in v0.0.13

func (a *LocalAuth) HandleForgotPasswordForm(w http.ResponseWriter, r *http.Request)

HandleForgotPasswordForm shows the forgot password form (GET)

func (*LocalAuth) HandleResetPassword added in v0.0.13

func (a *LocalAuth) HandleResetPassword(w http.ResponseWriter, r *http.Request)

HandleResetPassword handles password reset submissions (POST)

func (*LocalAuth) HandleResetPasswordForm added in v0.0.13

func (a *LocalAuth) HandleResetPasswordForm(w http.ResponseWriter, r *http.Request)

HandleResetPasswordForm shows the reset password form (GET)

func (*LocalAuth) HandleSignup added in v0.0.13

func (a *LocalAuth) HandleSignup(w http.ResponseWriter, r *http.Request)

HandleSignup processes user registration

func (*LocalAuth) HandleVerifyEmail added in v0.0.13

func (a *LocalAuth) HandleVerifyEmail(w http.ResponseWriter, r *http.Request)

HandleVerifyEmail handles email verification via token

func (*LocalAuth) ServeHTTP added in v0.0.9

func (a *LocalAuth) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles login requests

type Middleware

type Middleware struct {
	AuthTokenHeaderName string
	AuthTokenCookieName string
	UserParamName       string
	CallbackURLParam    string
	SessionGetter       func(r *http.Request, param string) any
	GetRedirURL         func(r *http.Request) string
	DefaultRedirectURL  string
	VerifyToken         func(tokenString string) (loggedInUserId string, token any, err error)
}

func (*Middleware) EnsureReasonableDefaults

func (a *Middleware) EnsureReasonableDefaults()

*

  • Ensures that config values have reasonable defaults.

func (*Middleware) EnsureUser

func (a *Middleware) EnsureUser(next http.Handler) http.Handler

func (*Middleware) ExtractUser

func (a *Middleware) ExtractUser(next http.Handler) http.Handler

*

  • Fetches the user from the request and loads the UserId and User variables
  • available for other handlers. *
  • Note this does not perform any redirects if a valid user does not exist.
  • To also enforce a user exists, use the EnsureUser handler which both
  • calls ExgractUser and ensures that user is logged in.

func (*Middleware) GetLoggedInUserId

func (a *Middleware) GetLoggedInUserId(r *http.Request) string

Get the ID of the logged in user from the current request

type OneAuth

type OneAuth struct {
	Session    *scs.SessionManager
	Middleware Middleware

	// Optional name that can be used as a prefix for all required vars
	AppName string

	// Name of the session variable where the auth token is stored
	AuthTokenSessionVar string

	// Must be passed in
	UserStore AuthUserStore

	// All the domains where the auth token cookies will be set on a login success or logout
	CookieDomains []string

	// JWT related fields
	JwtIssuer    string
	JWTSecretKey string

	// How long is a session cookie valid for.  Defaults to 1 day
	SessionTimeoutInSeconds int
	// contains filtered or unexported fields
}

func New

func New(appName string) *OneAuth

func (*OneAuth) AddAuth added in v0.0.2

func (a *OneAuth) AddAuth(prefix string, handler http.Handler) *OneAuth

func (*OneAuth) EnsureDefaults

func (a *OneAuth) EnsureDefaults() *OneAuth

func (*OneAuth) Handler added in v0.0.2

func (a *OneAuth) Handler() http.Handler

func (*OneAuth) SaveUserAndRedirect

func (a *OneAuth) SaveUserAndRedirect(authtype, provider string, token *oauth2.Token, userInfo map[string]any, w http.ResponseWriter, r *http.Request)

*

  • Called by the oauth callback handler with auth token and user info after
  • a successful auth flow and redirect. *
  • Here is our opportunity to:
  • 1. Create a userId that is unique to our system based on userInfo
  • 2. Set the right session cookies from this.

type SendEmail added in v0.0.13

type SendEmail interface {
	SendVerificationEmail(to string, verificationLink string) error
	SendPasswordResetEmail(to string, resetLink string) error
}

SendEmail interface allows applications to provide their own email sending implementation

type SignupValidator added in v0.0.13

type SignupValidator func(creds *Credentials) error

SignupValidator validates credentials during signup

var DefaultSignupValidator SignupValidator = func(creds *Credentials) error {

	if len(creds.Username) < 3 || len(creds.Username) > 20 {
		return fmt.Errorf("username must be 3-20 characters")
	}
	usernameRegex := regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)
	if !usernameRegex.MatchString(creds.Username) {
		return fmt.Errorf("username can only contain letters, numbers, underscores, and hyphens")
	}

	if creds.Email == nil && creds.Phone == nil {
		return fmt.Errorf("email or phone required")
	}

	if creds.Email != nil && *creds.Email != "" {
		emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
		if !emailRegex.MatchString(*creds.Email) {
			return fmt.Errorf("invalid email format")
		}
	}

	if creds.Phone != nil && *creds.Phone != "" {
		cleaned := strings.ReplaceAll(*creds.Phone, "-", "")
		cleaned = strings.ReplaceAll(cleaned, " ", "")
		cleaned = strings.ReplaceAll(cleaned, "(", "")
		cleaned = strings.ReplaceAll(cleaned, ")", "")
		if len(cleaned) < 10 {
			return fmt.Errorf("invalid phone number")
		}
	}

	if len(creds.Password) < 8 {
		return fmt.Errorf("password must be at least 8 characters")
	}

	return nil
}

DefaultSignupValidator provides sensible default validation for signup

type TokenStore added in v0.0.13

type TokenStore interface {
	CreateToken(userID, email string, tokenType TokenType, expiryDuration time.Duration) (*AuthToken, error)
	GetToken(token string) (*AuthToken, error)
	DeleteToken(token string) error
	DeleteUserTokens(userID string, tokenType TokenType) error
}

TokenStore interface for managing auth tokens

type TokenType added in v0.0.13

type TokenType string

TokenType represents different types of auth tokens

const (
	TokenTypeEmailVerification TokenType = "email_verification"
	TokenTypePasswordReset     TokenType = "password_reset"
)

type UpdatePasswordFunc added in v0.0.13

type UpdatePasswordFunc func(email, newPassword string) error

func NewUpdatePasswordFunc added in v0.0.13

func NewUpdatePasswordFunc(identityStore IdentityStore, channelStore ChannelStore) UpdatePasswordFunc

NewUpdatePasswordFunc creates an UpdatePasswordFunc from stores

type User

type User interface {
	Id() string
	Profile() map[string]any
}

User represents a unified user account

type UserStore

type UserStore interface {
	// CreateUser creates a new user with the given ID and profile
	CreateUser(userId string, isActive bool, profile map[string]any) (User, error)

	// GetUserById retrieves a user by their ID
	GetUserById(userId string) (User, error)

	// SaveUser creates or updates a user (upsert)
	SaveUser(user User) error
}

UserStore manages unified user accounts

type VerifyEmailFunc added in v0.0.13

type VerifyEmailFunc func(token string) error

func NewVerifyEmailFunc added in v0.0.13

func NewVerifyEmailFunc(identityStore IdentityStore, tokenStore TokenStore) VerifyEmailFunc

NewVerifyEmailFunc creates a VerifyEmailFunc from stores

Directories

Path Synopsis
cmd
oneauth module
Package grpc provides authentication context utilities for passing user information between HTTP handlers and gRPC services via metadata.
Package grpc provides authentication context utilities for passing user information between HTTP handlers and gRPC services via metadata.
gae module
gorm module

Jump to

Keyboard shortcuts

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