oneauth

package module
v0.0.22 Latest Latest
Warning

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

Go to latest
Published: Jan 13, 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.
  • API authentication: JWT access tokens, refresh tokens, and API keys for programmatic access
  • Separation of concerns: Users, identities, and authentication channels as distinct concepts
  • Flexible storage: Database-agnostic store interfaces with file-based, GORM, and GAE/Datastore implementations
  • Email workflows: Built-in email verification and password reset flows
  • Security focused: bcrypt password hashing, JWT tokens, secure token generation, single-use tokens
  • Scopes & permissions: Fine-grained access control with scope validation
  • 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

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/fs"
)

// Initialize stores
storagePath := "/path/to/storage"
userStore := fs.NewFSUserStore(storagePath)
identityStore := fs.NewFSIdentityStore(storagePath)
channelStore := fs.NewFSChannelStore(storagePath)
tokenStore := fs.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.

API Authentication

OneAuth provides a complete API authentication system for mobile apps, SPAs, CLI tools, and service-to-service communication.

Token Architecture
  • Access Tokens: Short-lived JWTs (15 min default) for stateless API authentication
  • Refresh Tokens: Long-lived opaque tokens (7 days) for obtaining new access tokens
  • API Keys: Long-lived keys for CI/CD, scripts, and automation
API Login
import (
    "github.com/panyam/oneauth"
    "github.com/panyam/oneauth/stores/fs"
)

// Setup stores
storagePath := "/path/to/storage"
refreshTokenStore := fs.NewFSRefreshTokenStore(storagePath)
apiKeyStore := fs.NewFSAPIKeyStore(storagePath)

// Configure API authentication
apiAuth := &oneauth.APIAuth{
    ValidateCredentials: validateCreds,
    RefreshTokenStore:   refreshTokenStore,
    APIKeyStore:         apiKeyStore,
    JWTSecretKey:        "your-secret-key",
    JWTIssuer:           "yourapp.com",
    GetUserScopes: func(userID string) ([]string, error) {
        return []string{"read", "write", "profile"}, nil
    },
}

// Mount API routes
mux.Handle("/api/login", http.HandlerFunc(apiAuth.HandleLogin))
mux.Handle("/api/logout", http.HandlerFunc(apiAuth.HandleLogout))
mux.Handle("/api/keys", http.HandlerFunc(apiAuth.HandleAPIKeys))
API Middleware

Protect your API endpoints with JWT validation:

middleware := &oneauth.APIMiddleware{
    JWTSecretKey: "your-secret-key",
    JWTIssuer:    "yourapp.com",
    APIKeyStore:  apiKeyStore,
}

// Require authentication
mux.Handle("/api/protected", middleware.ValidateToken(protectedHandler))

// Require specific scopes
mux.Handle("/api/write", middleware.RequireScopes("write")(writeHandler))

// Optional authentication
mux.Handle("/api/public", middleware.Optional(publicHandler))
API Requests
# Login with password
curl -X POST http://localhost:8080/api/login \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"password","username":"user@example.com","password":"secret"}'

# Response: {"access_token":"eyJ...", "refresh_token":"abc123...", "token_type":"Bearer"}

# Use access token
curl http://localhost:8080/api/protected \
  -H "Authorization: Bearer eyJ..."

# Refresh tokens
curl -X POST http://localhost:8080/api/login \
  -d '{"grant_type":"refresh_token","refresh_token":"abc123..."}'

# Create API key
curl -X POST http://localhost:8080/api/keys \
  -H "Authorization: Bearer eyJ..." \
  -d '{"name":"CI Key","scopes":["read"]}'

Documentation

Store Interfaces

OneAuth defines six 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
}
RefreshTokenStore

Manages refresh tokens for API authentication.

type RefreshTokenStore interface {
    CreateRefreshToken(userID, clientID string, deviceInfo map[string]any, scopes []string, expiresIn time.Duration) (*RefreshToken, error)
    GetRefreshToken(token string) (*RefreshToken, error)
    RotateRefreshToken(oldToken string, expiresIn time.Duration) (*RefreshToken, error)
    RevokeRefreshToken(token string) error
    RevokeUserTokens(userID string) error
    RevokeTokenFamily(family string) error
}
APIKeyStore

Manages API keys for long-lived programmatic access.

type APIKeyStore interface {
    CreateAPIKey(userID, name string, scopes []string, expiresAt *time.Time) (fullKey string, apiKey *APIKey, err error)
    GetAPIKeyByID(keyID string) (*APIKey, error)
    ValidateAPIKey(fullKey string) (*APIKey, error)
    RevokeAPIKey(keyID string) error
    ListUserAPIKeys(userID string) ([]*APIKey, error)
}

Store Implementations

OneAuth provides three store implementations:

File-Based Stores

For development and small applications (< 1000 users):

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

storagePath := "/path/to/storage"
userStore := fs.NewFSUserStore(storagePath)
identityStore := fs.NewFSIdentityStore(storagePath)
channelStore := fs.NewFSChannelStore(storagePath)
tokenStore := fs.NewFSTokenStore(storagePath)
refreshTokenStore := fs.NewFSRefreshTokenStore(storagePath)
apiKeyStore := fs.NewFSAPIKeyStore(storagePath)
GORM Stores

For SQL databases (PostgreSQL, MySQL, SQLite):

import (
    "github.com/panyam/oneauth/stores/gorm"
    gormdb "gorm.io/gorm"
)

db, _ := gormdb.Open(postgres.Open(dsn), &gormdb.Config{})

userStore := gorm.NewGORMUserStore(db)
identityStore := gorm.NewGORMIdentityStore(db)
channelStore := gorm.NewGORMChannelStore(db)
tokenStore := gorm.NewGORMTokenStore(db)
refreshTokenStore := gorm.NewGORMRefreshTokenStore(db)
apiKeyStore := gorm.NewGORMAPIKeyStore(db)

// Auto-migrate tables
gorm.AutoMigrate(db)
GAE/Datastore Stores

For Google App Engine and Cloud Datastore:

import (
    "github.com/panyam/oneauth/stores/gae"
    "cloud.google.com/go/datastore"
)

client, _ := datastore.NewClient(ctx, projectID)
namespace := "myapp"

userStore := gae.NewUserStore(client, namespace)
identityStore := gae.NewIdentityStore(client, namespace)
channelStore := gae.NewChannelStore(client, namespace)
tokenStore := gae.NewTokenStore(client, namespace)
refreshTokenStore := gae.NewRefreshTokenStore(client, namespace)
apiKeyStore := gae.NewAPIKeyStore(client, namespace)

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 := fs.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 for usage examples:

  • local_test.go, auth_flows_test.go: Browser-based authentication flows
  • api_auth_test.go: API authentication with JWT, refresh tokens, and API keys
  • grpc/context_test.go, grpc/interceptor_test.go: gRPC integration patterns

Limitations & Extensibility

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

Store Options
  • File-based stores: Suitable for development and <1000 users
  • GORM stores: For production SQL databases
  • GAE stores: For Google Cloud deployments
  • Custom stores: Implement interfaces for other databases
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)
  • github.com/golang-jwt/jwt/v5 for JWT tokens (required for API auth)
  • golang.org/x/oauth2 for OAuth providers (optional)
  • gorm.io/gorm for GORM stores (optional)
  • cloud.google.com/go/datastore for GAE stores (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 (
	ScopeRead    = "read"    // Read access to user data
	ScopeWrite   = "write"   // Write access to user data
	ScopeProfile = "profile" // Access to user profile information
	ScopeOffline = "offline" // Enable refresh tokens (long-lived sessions)
	ScopeAdmin   = "admin"   // Administrative access
)

Built-in scope constants

View Source
const (
	TokenExpiryEmailVerification = 24 * time.Hour     // 24 hours
	TokenExpiryPasswordReset     = 1 * time.Hour      // 1 hour
	TokenExpiryAccessToken       = 15 * time.Minute   // 15 minutes
	TokenExpiryRefreshToken      = 7 * 24 * time.Hour // 7 days
)

Default token expiry durations

View Source
const DefaultUserParamName = "loggedInUserId"

DefaultUserParamName is the default context key for user ID

Variables

View Source
var (
	ErrTokenNotFound  = fmt.Errorf("token not found")
	ErrTokenExpired   = fmt.Errorf("token expired")
	ErrTokenRevoked   = fmt.Errorf("token revoked")
	ErrTokenReused    = fmt.Errorf("token reuse detected")
	ErrInvalidGrant   = fmt.Errorf("invalid grant")
	ErrInvalidScope   = fmt.Errorf("invalid scope")
	ErrAPIKeyNotFound = fmt.Errorf("api key not found")
)

Common errors for token operations

Functions

func AllBuiltinScopes added in v0.0.20

func AllBuiltinScopes() []string

AllBuiltinScopes returns all built-in scope values

func ContainsAllScopes added in v0.0.20

func ContainsAllScopes(granted, required []string) bool

ContainsAllScopes checks if all required scopes are present in the granted scopes

func ContainsScope added in v0.0.20

func ContainsScope(scopes []string, scope string) bool

ContainsScope checks if a scope is present in the list

func DetectUsernameType added in v0.0.13

func DetectUsernameType(username string) string

DetectUsernameType attempts to detect what type of username was provided

func GenerateAPIKeyID added in v0.0.20

func GenerateAPIKeyID() (string, error)

GenerateAPIKeyID generates a new API key ID with prefix

func GenerateAPIKeySecret added in v0.0.20

func GenerateAPIKeySecret() (string, error)

GenerateAPIKeySecret generates the secret portion of an API key

func GenerateSecureToken added in v0.0.13

func GenerateSecureToken() (string, error)

GenerateSecureToken generates a cryptographically secure random token

func GetAuthTypeFromAPIContext added in v0.0.20

func GetAuthTypeFromAPIContext(ctx context.Context) string

GetAuthTypeFromAPIContext retrieves the auth type ("jwt" or "api_key") from context

func GetScopesFromAPIContext added in v0.0.20

func GetScopesFromAPIContext(ctx context.Context) []string

GetScopesFromAPIContext retrieves the granted scopes from the API middleware context

func GetUserIDFromAPIContext added in v0.0.20

func GetUserIDFromAPIContext(ctx context.Context) string

GetUserIDFromAPIContext retrieves the user ID from the API middleware context

func GetUserIDFromContext added in v0.0.20

func GetUserIDFromContext(ctx context.Context) string

GetUserIDFromContext retrieves the user ID from the request context Uses the default key "loggedInUserId"

func IdentityKey added in v0.0.13

func IdentityKey(identityType, identityValue string) string

IdentityKey creates a consistent identity key from type and value

func IntersectScopes added in v0.0.20

func IntersectScopes(requested, allowed []string) []string

IntersectScopes returns the intersection of requested and allowed scopes The result contains only scopes that appear in both slices

func JoinScopes added in v0.0.20

func JoinScopes(scopes []string) string

JoinScopes joins a slice of scopes into a space-separated string

func ParseScopes added in v0.0.20

func ParseScopes(scopeString string) []string

ParseScopes parses a space-separated scope string into a slice

func ScopesEqual added in v0.0.20

func ScopesEqual(a, b []string) bool

ScopesEqual checks if two scope slices contain the same scopes (order-independent)

func SetUserIDInContext added in v0.0.20

func SetUserIDInContext(ctx context.Context, userID string) context.Context

SetUserIDInContext sets the user ID in the request context

func ValidateRequestedScopes added in v0.0.20

func ValidateRequestedScopes(requested, allowed []string) (valid, invalid []string)

ValidateRequestedScopes validates that all requested scopes are from the allowed set Returns the valid scopes and any invalid scopes found

Types

type APIAuth added in v0.0.20

type APIAuth struct {
	// Stores
	RefreshTokenStore RefreshTokenStore
	APIKeyStore       APIKeyStore

	// JWT configuration
	JWTSecretKey  string // Secret key for signing JWTs
	JWTIssuer     string // Issuer claim (e.g., "myapp")
	JWTAudience   string // Audience claim (e.g., "api")
	JWTSigningAlg string // Signing algorithm (defaults to HS256)

	// Token configuration
	AccessTokenExpiry  time.Duration // Defaults to 15 minutes
	RefreshTokenExpiry time.Duration // Defaults to 7 days

	// Callbacks
	ValidateCredentials CredentialsValidator                              // Validates username/password
	GetUserScopes       GetUserScopesFunc                                 // Returns allowed scopes for a user
	OnLoginSuccess      func(userID string, r *http.Request)              // Optional: for logging/analytics
	OnLoginFailure      func(username string, r *http.Request, err error) // Optional: for logging/analytics

	// Rate limiting (optional)
	RateLimiter RateLimiter
}

APIAuth handles API token-based authentication

func (*APIAuth) HandleAPIKeys added in v0.0.20

func (a *APIAuth) HandleAPIKeys(w http.ResponseWriter, r *http.Request)

HandleAPIKeys handles API key management (GET=list, POST=create) Requires authentication (userID must be in request context)

func (*APIAuth) HandleListSessions added in v0.0.20

func (a *APIAuth) HandleListSessions(w http.ResponseWriter, r *http.Request)

HandleListSessions handles GET /api/sessions - lists active sessions for the user Requires authentication (userID must be in request context)

func (*APIAuth) HandleLogout added in v0.0.20

func (a *APIAuth) HandleLogout(w http.ResponseWriter, r *http.Request)

HandleLogout handles POST /api/logout - revokes a refresh token

func (*APIAuth) HandleLogoutAll added in v0.0.20

func (a *APIAuth) HandleLogoutAll(w http.ResponseWriter, r *http.Request)

HandleLogoutAll handles POST /api/logout-all - revokes all refresh tokens for the user Requires authentication (userID must be in request context)

func (*APIAuth) HandleRevokeAPIKey added in v0.0.20

func (a *APIAuth) HandleRevokeAPIKey(w http.ResponseWriter, r *http.Request)

HandleRevokeAPIKey handles DELETE /api/keys/:id - revokes an API key Requires authentication (userID must be in request context)

func (*APIAuth) ServeHTTP added in v0.0.20

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

ServeHTTP handles the /api/login endpoint

func (*APIAuth) ValidateAccessToken added in v0.0.20

func (a *APIAuth) ValidateAccessToken(tokenString string) (userID string, scopes []string, err error)

ValidateAccessToken validates a JWT access token and returns the claims

type APIKey added in v0.0.20

type APIKey struct {
	KeyID      string     `json:"key_id"`   // Public identifier (e.g., "oa_abc123...")
	KeyHash    string     `json:"key_hash"` // bcrypt hash of the secret portion
	UserID     string     `json:"user_id"`  // Owner of this key
	Name       string     `json:"name"`     // User-defined label
	Scopes     []string   `json:"scopes"`   // Allowed scopes
	CreatedAt  time.Time  `json:"created_at"`
	ExpiresAt  *time.Time `json:"expires_at,omitempty"` // Optional expiry
	LastUsedAt time.Time  `json:"last_used_at"`
	RevokedAt  *time.Time `json:"revoked_at,omitempty"`
	Revoked    bool       `json:"revoked"`
}

APIKey represents a long-lived API key for programmatic access

func (*APIKey) IsExpired added in v0.0.20

func (k *APIKey) IsExpired() bool

IsExpired checks if an API key has expired

func (*APIKey) IsValid added in v0.0.20

func (k *APIKey) IsValid() bool

IsValid checks if an API key is valid (not expired and not revoked)

type APIKeyStore added in v0.0.20

type APIKeyStore interface {
	// CreateAPIKey creates a new API key and returns the full key (only shown once)
	// The key format is: keyID + "_" + secret
	CreateAPIKey(userID, name string, scopes []string, expiresAt *time.Time) (fullKey string, apiKey *APIKey, err error)

	// GetAPIKeyByID retrieves an API key by its public ID
	GetAPIKeyByID(keyID string) (*APIKey, error)

	// ValidateAPIKey validates a full API key and returns the key metadata if valid
	// The fullKey format is: keyID + "_" + secret
	ValidateAPIKey(fullKey string) (*APIKey, error)

	// RevokeAPIKey marks an API key as revoked
	RevokeAPIKey(keyID string) error

	// ListUserAPIKeys returns all API keys for a user (without secrets)
	ListUserAPIKeys(userID string) ([]*APIKey, error)

	// UpdateAPIKeyLastUsed updates the last used timestamp
	UpdateAPIKeyLastUsed(keyID string) error
}

APIKeyStore manages API keys for programmatic access

type APIMiddleware added in v0.0.20

type APIMiddleware struct {
	// JWT validation (uses same config as APIAuth)
	JWTSecretKey  string
	JWTIssuer     string
	JWTAudience   string
	JWTSigningAlg string

	// API key validation (optional)
	APIKeyStore APIKeyStore

	// Token header configuration
	AuthHeader string // Defaults to "Authorization"

	// Error handling
	OnAuthError func(w http.ResponseWriter, r *http.Request, err error)
}

APIMiddleware provides middleware for validating API tokens

func (*APIMiddleware) Optional added in v0.0.20

func (m *APIMiddleware) Optional(next http.Handler) http.Handler

Optional middleware allows requests without auth but sets user info if present

func (*APIMiddleware) RequireScopes added in v0.0.20

func (m *APIMiddleware) RequireScopes(requiredScopes ...string) func(http.Handler) http.Handler

RequireScopes middleware ensures the authenticated user has all required scopes

func (*APIMiddleware) ValidateToken added in v0.0.20

func (m *APIMiddleware) ValidateToken(next http.Handler) http.Handler

ValidateToken middleware validates Bearer tokens (JWT or API key) and sets user info in context

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 GetUserScopesFunc added in v0.0.20

type GetUserScopesFunc func(userID string) ([]string, error)

GetUserScopesFunc is a callback that returns allowed scopes for a user. Applications implement this to determine what scopes a user is allowed to have. This can be based on user roles, profile data, groups, etc.

func DefaultGetUserScopes added in v0.0.20

func DefaultGetUserScopes() GetUserScopesFunc

DefaultGetUserScopes returns a default implementation that grants basic scopes to all users

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 RateLimiter added in v0.0.20

type RateLimiter interface {
	Allow(key string) bool
}

RateLimiter interface for rate limiting login attempts

type RefreshToken added in v0.0.20

type RefreshToken struct {
	Token      string         `json:"token"`       // 64-char hex token value
	TokenHash  string         `json:"token_hash"`  // SHA256 hash for storage (optional)
	UserID     string         `json:"user_id"`     // Associated user
	ClientID   string         `json:"client_id"`   // Optional client/app identifier
	DeviceInfo map[string]any `json:"device_info"` // User agent, IP, etc.
	Family     string         `json:"family"`      // Token family for rotation tracking
	Generation int            `json:"generation"`  // Increments on rotation
	Scopes     []string       `json:"scopes"`      // Granted scopes
	CreatedAt  time.Time      `json:"created_at"`
	ExpiresAt  time.Time      `json:"expires_at"`
	LastUsedAt time.Time      `json:"last_used_at"`
	RevokedAt  *time.Time     `json:"revoked_at,omitempty"`
	Revoked    bool           `json:"revoked"`
}

RefreshToken represents a long-lived refresh token for API access

func (*RefreshToken) IsExpired added in v0.0.20

func (t *RefreshToken) IsExpired() bool

IsExpired checks if a refresh token has expired

func (*RefreshToken) IsValid added in v0.0.20

func (t *RefreshToken) IsValid() bool

IsValid checks if a refresh token is valid (not expired and not revoked)

type RefreshTokenStore added in v0.0.20

type RefreshTokenStore interface {
	// CreateRefreshToken creates a new refresh token for a user
	CreateRefreshToken(userID, clientID string, deviceInfo map[string]any, scopes []string) (*RefreshToken, error)

	// GetRefreshToken retrieves a refresh token by its value
	GetRefreshToken(token string) (*RefreshToken, error)

	// RotateRefreshToken invalidates old token and creates new one in same family
	// Returns ErrTokenReused if the old token was already revoked (theft detection)
	RotateRefreshToken(oldToken string) (*RefreshToken, error)

	// RevokeRefreshToken marks a token as revoked
	RevokeRefreshToken(token string) error

	// RevokeUserTokens revokes all refresh tokens for a user
	RevokeUserTokens(userID string) error

	// RevokeTokenFamily revokes all tokens in a family (theft detection)
	RevokeTokenFamily(family string) error

	// GetUserTokens lists all active (non-revoked, non-expired) refresh tokens for a user
	GetUserTokens(userID string) ([]*RefreshToken, error)

	// CleanupExpiredTokens removes expired tokens (for maintenance)
	CleanupExpiredTokens() error
}

RefreshTokenStore manages refresh tokens for API access

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 TokenError added in v0.0.20

type TokenError struct {
	Error            string `json:"error"`
	ErrorDescription string `json:"error_description,omitempty"`
}

TokenError represents an OAuth 2.0 compliant error response

type TokenPair added in v0.0.20

type TokenPair struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"` // "Bearer"
	ExpiresIn    int64  `json:"expires_in"` // Seconds until access token expires
	RefreshToken string `json:"refresh_token,omitempty"`
	Scope        string `json:"scope,omitempty"`
}

TokenPair represents the response from a successful authentication

type TokenRequest added in v0.0.20

type TokenRequest struct {
	GrantType    string `json:"grant_type"`              // "password", "refresh_token"
	Username     string `json:"username,omitempty"`      // For password grant
	Password     string `json:"password,omitempty"`      // For password grant
	RefreshToken string `json:"refresh_token,omitempty"` // For refresh_token grant
	Scope        string `json:"scope,omitempty"`         // Requested scopes
	ClientID     string `json:"client_id,omitempty"`     // Optional client identifier
}

TokenRequest represents a request to the token endpoint

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"
	TokenTypeRefresh           TokenType = "refresh"
)

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
Package client provides client-side authentication utilities for oneauth.
Package client provides client-side authentication utilities for oneauth.
stores/fs
Package fs provides a file system-based credential store for oneauth client.
Package fs provides a file system-based credential store for oneauth client.
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.
stores
fs
gae
Package gae provides Google Cloud Datastore implementations of oneauth store interfaces.
Package gae provides Google Cloud Datastore implementations of oneauth store interfaces.
gorm
Package gorm provides GORM-based implementations of oneauth store interfaces.
Package gorm provides GORM-based implementations of oneauth store interfaces.

Jump to

Keyboard shortcuts

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