auth

package
v0.0.0-...-6a3e998 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2025 License: MIT Imports: 35 Imported by: 0

README

Auth Package

The auth package provides centralized authentication and authorization services for the DevOps MCP platform.

Implementation Status

✅ Fully Implemented
  • API Key Authentication: Complete with database storage, hashing, and caching
  • JWT Token Authentication: HS256 signing with standard claims support
  • Basic RBAC: Simple role-based access control (in-memory policies)
  • Middleware Support: Gin and standard HTTP middleware
  • Multi-Provider Support: Multiple auth methods in single request
  • Tenant Isolation: Built-in multi-tenancy support
  • Performance Caching: Redis/in-memory caching for auth checks
⚠️ Partially Implemented
  • OAuth Interface: Interface defined but no concrete providers (Google, GitHub, etc.)
  • GitHub App Auth: Exists in pkg/adapters/github/auth/ but not integrated here
❌ Not Implemented (Planned)
  • Casbin RBAC: Advanced policy-based access control
  • OAuth Providers: Concrete implementations for Google, GitHub, Microsoft
  • Session Management: No session tracking or refresh tokens
  • Token Revocation: JWT tokens cannot be revoked before expiration
  • Audit Logging: No dedicated auth event logging (uses general logging)
  • MFA/2FA: No multi-factor authentication support

Features

  • API Key Authentication: Support for static and dynamic API keys with secure hashing
  • JWT Token Authentication: JSON Web Token support with configurable expiration
  • Scope-based Authorization: Basic permission control via scopes
  • Middleware Support: Ready-to-use middleware for Gin and standard HTTP handlers
  • Caching: Built-in caching support for improved performance
  • Database Integration: PostgreSQL storage for API keys with pgx driver
  • Multi-tenancy: Built-in tenant isolation support
  • Rate Limiting: Basic rate limiting support (configurable)

Architecture

The auth package uses a provider-based architecture:

Manager (orchestrator)
├── APIKeyProvider (database-backed)
├── JWTProvider (stateless tokens)
├── OAuthProvider (interface only)
└── Authorizer (ProductionAuthorizer or TestProvider)

Usage

Basic Setup
import (
    "github.com/S-Corkum/devops-mcp/pkg/auth"
    "github.com/S-Corkum/devops-mcp/pkg/observability"
)

// Create auth manager with all providers
config := &auth.Config{
    // JWT Configuration
    JWTSecret:    os.Getenv("JWT_SECRET"), // Required
    JWTIssuer:    "devops-mcp",
    JWTExpiresIn: 15 * time.Minute,
    
    // API Key Configuration  
    EnableAPIKeys: true,
    APIKeyHeader:  "X-API-Key", // or Authorization: Bearer
    
    // Authorization
    AuthorizerType: "production", // or "test" for testing
    
    // Caching
    CacheEnabled: true,
    CacheTTL:    5 * time.Minute,
}

// Dependencies
logger := observability.NewLogger("auth")
tracer := observability.NewTracer("auth")

// Create manager
authManager, err := auth.NewManager(config, db, cache, logger, tracer)
if err != nil {
    log.Fatal(err)
}

// The manager automatically initializes:
// - APIKeyProvider with APIKeyService
// - JWTProvider with configuration
// - ProductionAuthorizer with basic RBAC
Using with Gin
// Create Gin router
router := gin.New()

// Apply auth middleware - supports multiple auth types
router.Use(auth.GinMiddleware(authManager))

// The middleware checks in order:
// 1. Authorization: Bearer <token> (JWT or API key)
// 2. X-API-Key: <key>
// 3. Custom headers configured in APIKeyHeader

// Protected routes
v1 := router.Group("/api/v1")
v1.Use(auth.GinMiddleware(authManager))

// Get user from context in handlers
v1.GET("/profile", func(c *gin.Context) {
    user, exists := c.Get("user")
    if !exists {
        c.JSON(401, gin.H{"error": "unauthorized"})
        return
    }
    
    authUser := user.(*auth.User)
    c.JSON(200, gin.H{
        "user_id": authUser.ID,
        "tenant_id": authUser.TenantID,
        "scopes": authUser.Scopes,
    })
})
Using with Standard HTTP
// Wrap standard HTTP handlers
mux := http.NewServeMux()

// Create middleware
authMiddleware := auth.StandardMiddleware(authManager)

// Protected endpoint
mux.Handle("/api/", authMiddleware(http.HandlerFunc(apiHandler)))

func apiHandler(w http.ResponseWriter, r *http.Request) {
    // Get user from context
    user := r.Context().Value(auth.UserContextKey).(*auth.User)
    
    // Use authenticated user info
    fmt.Fprintf(w, "Hello %s", user.ID)
}
API Key Management
// Get the API key service from manager
apiKeyService := authManager.GetAPIKeyService()

// Create a new API key
key := &auth.APIKey{
    ID:       uuid.New(),
    Name:     "Production API",
    TenantID: uuid.MustParse("tenant-123"),
    UserID:   uuid.MustParse("user-456"),
    Scopes:   []string{"read", "write"},
    ExpiresAt: time.Now().Add(365 * 24 * time.Hour), // 1 year
}

// Create returns the unhashed key - save this!
apiKey, plainKey, err := apiKeyService.CreateKey(ctx, key)
if err != nil {
    return err
}

// The plainKey is only returned once and should be given to the user
fmt.Printf("Your API key: %s\n", plainKey)

// Validate an API key (done automatically by middleware)
validKey, err := apiKeyService.ValidateKey(ctx, plainKey)

// List keys for a user
keys, err := apiKeyService.ListKeys(ctx, userID, tenantID)

// Revoke a key
err = apiKeyService.RevokeKey(ctx, keyID)
JWT Token Management
// JWT provider handles token generation/validation
// This is typically done after login or OAuth callback

// Create user claims
user := &auth.User{
    ID:       uuid.New().String(),
    TenantID: uuid.New().String(), 
    Email:    "user@example.com",
    Scopes:   []string{"contexts:read", "agents:write"},
}

// Generate token (done internally by auth flow)
token, err := authManager.GenerateToken(user)
if err != nil {
    return err
}

// Token should be returned to client
// Client includes it as: Authorization: Bearer <token>

// Validation happens automatically in middleware
// But you can manually validate:
claims, err := authManager.ValidateToken(token)
Authorization Checks
// In handlers, check permissions
func deleteResource(c *gin.Context) {
    user := c.MustGet("user").(*auth.User)
    resourceID := c.Param("id")
    
    // Check permission using the authorizer
    allowed, err := authManager.Authorize(c.Request.Context(), &auth.AuthRequest{
        Subject:  user.ID,
        Resource: "contexts",
        Action:   "delete",
        TenantID: user.TenantID,
    })
    
    if err != nil || !allowed {
        c.JSON(403, gin.H{"error": "forbidden"})
        return
    }
    
    // Proceed with deletion
}

// Or use middleware for consistent checks
adminOnly := auth.RequireScopes(authManager, "admin")
router.DELETE("/api/v1/users/:id", adminOnly, deleteUser)

Configuration

type Config struct {
    // JWT Settings
    JWTSecret    string        // Required: Min 32 bytes recommended
    JWTIssuer    string        // Default: "devops-mcp"
    JWTExpiresIn time.Duration // Default: 15 minutes
    
    // API Key Settings
    EnableAPIKeys bool   // Default: true
    APIKeyHeader  string // Default: "X-API-Key"
    
    // Authorization
    AuthorizerType string // "production" or "test"
    Policies       []Policy // Optional: custom policies
    
    // Cache Settings
    CacheEnabled bool          // Default: true
    CacheTTL     time.Duration // Default: 5 minutes
    
    // Security
    RateLimitPerMinute int // Default: 1000
    
    // Database (optional)
    DatabaseURL string // PostgreSQL connection string
}

Authorization Model

The current implementation uses a simple RBAC model:

// Basic policy structure (not Casbin)
type Policy struct {
    Subject  string // User ID or role
    Resource string // Resource type (e.g., "contexts")
    Action   string // Action (e.g., "read", "write", "delete")
}

// Default roles
const (
    RoleAdmin  = "admin"  // Full access
    RoleUser   = "user"   // Standard access
    RoleViewer = "viewer" // Read-only access
)

Database Schema

The auth package uses the following PostgreSQL schema:

-- API Keys table (with UUID primary key)
CREATE TABLE api_keys (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    key_hash VARCHAR(64) NOT NULL UNIQUE, -- SHA256 hash
    tenant_id UUID NOT NULL,
    user_id UUID NOT NULL,
    name VARCHAR(255) NOT NULL,
    scopes TEXT[] DEFAULT '{}',
    expires_at TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    last_used_at TIMESTAMP WITH TIME ZONE,
    revoked_at TIMESTAMP WITH TIME ZONE,
    active BOOLEAN NOT NULL DEFAULT true,
    
    INDEX idx_api_keys_tenant_user (tenant_id, user_id),
    INDEX idx_api_keys_active (active) WHERE active = true,
    INDEX idx_api_keys_expires (expires_at) WHERE expires_at IS NOT NULL
);

-- Future: OAuth tokens table (not implemented)
CREATE TABLE oauth_tokens (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    provider VARCHAR(50) NOT NULL,
    access_token_encrypted TEXT NOT NULL,
    refresh_token_encrypted TEXT,
    expires_at TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Future: Sessions table (not implemented)
CREATE TABLE user_sessions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    token_hash VARCHAR(64) NOT NULL UNIQUE,
    ip_address INET,
    user_agent TEXT,
    expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

Testing

The package includes comprehensive tests:

# Run all auth tests
go test ./pkg/auth/...

# Run with race detection
go test -race ./pkg/auth/...

# Run with coverage
go test -cover ./pkg/auth/...

For testing environments, use the TestProvider:

// Enable test mode
os.Setenv("MCP_TEST_MODE", "true")
os.Setenv("TEST_AUTH_ENABLED", "true")

// Create test provider
config := &auth.Config{
    AuthorizerType: "test",
}
authManager, _ := auth.NewManager(config, nil, nil, logger, tracer)

// Generate test tokens
testProvider := authManager.GetTestProvider()
token, _ := testProvider.GenerateTestToken(userID, tenantID, "admin", []string{"all"})

Current Limitations

No Session Management
  • JWT tokens cannot be revoked before expiration
  • No refresh token support
  • No session tracking or device management
  • Workaround: Use short JWT expiration times (15 minutes)
Basic Authorization Only
  • No Casbin integration (simple RBAC only)
  • No attribute-based access control (ABAC)
  • No dynamic policy updates
  • Workaround: Implement custom authorization logic in handlers
OAuth Not Implemented
  • Interface exists but no providers
  • No OAuth flow handling
  • No social login support
  • Workaround: Implement OAuth providers following the interface
Limited Audit Logging
  • Basic logging through observability package
  • No dedicated auth event tracking
  • No compliance-focused audit trail
  • Workaround: Implement custom audit logging in middleware

Security Best Practices

API Key Security
// DO: Generate cryptographically secure keys
key := make([]byte, 32)
rand.Read(key)
apiKey := base64.URLEncoding.EncodeToString(key)

// DON'T: Use predictable keys
apiKey := fmt.Sprintf("key_%d", userID) // INSECURE
JWT Security
// DO: Use strong secrets (min 256 bits)
jwtSecret := os.Getenv("JWT_SECRET") // Must be 32+ chars

// DO: Set short expiration times
config.JWTExpiresIn = 15 * time.Minute

// DON'T: Store sensitive data in JWT claims
claims["password"] = userPassword // NEVER DO THIS
Production Checklist
  • Set strong JWT secret (32+ bytes)
  • Configure API key rotation policy
  • Enable HTTPS only
  • Set up rate limiting
  • Configure proper CORS headers
  • Monitor authentication failures
  • Implement IP allowlisting for admin operations
  • Regular security audits
  • Keep dependencies updated

Troubleshooting

Common Issues
  1. "Invalid JWT secret"

    • Ensure JWT_SECRET environment variable is set
    • Secret must be at least 32 bytes
  2. "API key not found"

    • Check if key is properly hashed in database
    • Verify tenant_id matches
    • Ensure key hasn't expired
  3. "Unauthorized" errors

    • Check middleware is properly configured
    • Verify auth headers are being sent
    • Check token/key expiration
  4. Performance issues

    • Enable caching (Redis recommended)
    • Use connection pooling for database
    • Consider increasing cache TTL

Future Enhancements

Planned improvements for the auth package:

  1. Casbin Integration - Advanced policy-based access control
  2. OAuth Providers - Google, GitHub, Microsoft implementations
  3. Session Management - Refresh tokens and session tracking
  4. Audit Logging - Dedicated auth event logging
  5. MFA Support - Multi-factor authentication
  6. Token Revocation - Blacklist/whitelist for JWTs
  7. Rate Limiting - More sophisticated rate limiting per user/IP

Documentation

Overview

Package auth provides centralized authentication and authorization for the DevOps MCP platform

Index

Examples

Constants

View Source
const (
	// ContextKeyIPAddress is the context key for IP address
	ContextKeyIPAddress contextKey = "ip_address"
	// ContextKeyUserAgent is the context key for user agent
	ContextKeyUserAgent contextKey = "user_agent"
)
View Source
const (
	// PassthroughTokenKey is the key for storing passthrough token in context
	PassthroughTokenKey contextKey = "passthrough_token"
	// TokenProviderKey is the key for storing token provider in context
	TokenProviderKey contextKey = "token_provider"
	// GatewayIDKey is the key for storing gateway ID in context
	GatewayIDKey contextKey = "gateway_id"
)

Define additional context keys for passthrough functionality

View Source
const (
	// UserContextKey is the key for storing user in context
	UserContextKey contextKey = "auth_user"
)

Variables

View Source
var (
	ErrInvalidCredentials = errors.New("invalid credentials")
	ErrTokenExpired       = errors.New("token expired")
	ErrInvalidToken       = errors.New("invalid token")
	ErrUnauthorized       = errors.New("unauthorized")
	ErrNoAPIKey           = errors.New("no API key provided")
	ErrInvalidAPIKey      = errors.New("invalid API key")
	ErrInsufficientScope  = errors.New("insufficient scope")
)

Common errors

Functions

func CheckPassword

func CheckPassword(password, hash string) bool

CheckPassword compares a password with its hash

func CredentialExtractionMiddleware

func CredentialExtractionMiddleware(logger observability.Logger) gin.HandlerFunc

CredentialExtractionMiddleware extracts tool credentials from requests

func CredentialValidationMiddleware

func CredentialValidationMiddleware(requiredTools []string, logger observability.Logger) gin.HandlerFunc

CredentialValidationMiddleware validates that required credentials are present

func ExtractAllowedServices

func ExtractAllowedServices(metadata map[string]interface{}) []string

ExtractAllowedServices extracts allowed services from user metadata

func ExtractCredentialsFromBody

func ExtractCredentialsFromBody(c *gin.Context) (*models.ToolCredentials, bool)

ExtractCredentialsFromBody is a helper to extract credentials from a parsed body

func GenerateTestAPIKey

func GenerateTestAPIKey() string

GenerateTestAPIKey generates a secure test API key

func GetAgentID

func GetAgentID(ctx context.Context) string

GetAgentID gets the agent ID from context

func GetGatewayID

func GetGatewayID(ctx context.Context) (string, bool)

GetGatewayID retrieves the gateway ID from the context

func GetTenantFromContext

func GetTenantFromContext(c *gin.Context) (string, bool)

GetTenantFromContext extracts the tenant ID from the Gin context

func GetTenantID

func GetTenantID(ctx context.Context) uuid.UUID

GetTenantID gets the tenant ID from context

func GetTokenProvider

func GetTokenProvider(ctx context.Context) (string, bool)

GetTokenProvider retrieves the token provider from the context

func GetToolCredential

func GetToolCredential(ctx context.Context, tool string) (*models.TokenCredential, bool)

GetToolCredential retrieves a specific tool credential from context

func GetToolCredentials

func GetToolCredentials(ctx context.Context) (*models.ToolCredentials, bool)

GetToolCredentials retrieves tool credentials from context

func GetUserID

func GetUserID(ctx context.Context) string

GetUserID gets the user ID from context

func HTTPAuthMiddleware

func HTTPAuthMiddleware() func(http.Handler) http.Handler

HTTPAuthMiddleware creates HTTP middleware that adds IP to context

func HasToolCredential

func HasToolCredential(ctx context.Context, tool string) bool

HasToolCredential checks if a specific tool credential exists in context

func HashPassword

func HashPassword(password string) (string, error)

HashPassword hashes a password using bcrypt

func RateLimitMiddleware

func RateLimitMiddleware(rateLimiter *RateLimiter, logger observability.Logger) func(http.Handler) http.Handler

RateLimitMiddleware creates HTTP middleware for rate limiting

func SetupTestAuth

SetupTestAuth creates a complete test authentication system

func SetupTestAuthWithConfig

func SetupTestAuthWithConfig(t *testing.T, config *AuthSystemConfig) (*AuthMiddleware, *TestCache)

SetupTestAuthWithConfig allows custom configuration

func ValidateAuthConfiguration

func ValidateAuthConfiguration(logger observability.Logger) error

ValidateAuthConfiguration validates that auth configuration is consistent across services

func ValidateProviderAllowed

func ValidateProviderAllowed(provider string, allowedServices []string) bool

ValidateProviderAllowed checks if a provider is in the allowed services list

func WithAgentID

func WithAgentID(ctx context.Context, agentID string) context.Context

WithAgentID adds agent ID to context

func WithGatewayID

func WithGatewayID(ctx context.Context, gatewayID string) context.Context

WithGatewayID adds the gateway ID to the context

func WithPassthroughToken

func WithPassthroughToken(ctx context.Context, token PassthroughToken) context.Context

WithPassthroughToken adds a passthrough token to the context

func WithTenantID

func WithTenantID(ctx context.Context, tenantID uuid.UUID) context.Context

WithTenantID adds tenant ID to context

func WithTokenProvider

func WithTokenProvider(ctx context.Context, provider string) context.Context

WithTokenProvider adds the token provider to the context

func WithToolCredentials

func WithToolCredentials(ctx context.Context, creds *models.ToolCredentials) context.Context

WithToolCredentials adds tool credentials to context

func WithUserID

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

WithUserID adds user ID to context

Types

type APIKey

type APIKey struct {
	Key       string     `db:"key"`
	KeyHash   string     `db:"key_hash"`
	KeyPrefix string     `db:"key_prefix"`
	TenantID  string     `db:"tenant_id"`
	UserID    string     `db:"user_id"`
	Name      string     `db:"name"`
	KeyType   KeyType    `db:"key_type"` // NEW
	Scopes    []string   `db:"scopes"`
	ExpiresAt *time.Time `db:"expires_at"`
	CreatedAt time.Time  `db:"created_at"`
	LastUsed  *time.Time `db:"last_used"`
	Active    bool       `db:"is_active"`

	// Gateway-specific fields
	ParentKeyID     *string  `db:"parent_key_id"`    // NEW
	AllowedServices []string `db:"allowed_services"` // NEW

	// Rate limiting
	RateLimitRequests      int `db:"rate_limit_requests"`
	RateLimitWindowSeconds int `db:"rate_limit_window_seconds"`
}

APIKey represents an API key

type APIKeyConfig

type APIKeyConfig struct {
	// Development keys (only loaded in dev/test environments)
	DevelopmentKeys map[string]APIKeySettings `yaml:"development_keys"`

	// Production key sources
	ProductionKeySource string `yaml:"production_key_source"` // "env", "vault", "aws-secrets"
}

APIKeyConfig represents API key configuration

func LoadAuthConfigFromFile

func LoadAuthConfigFromFile(filename string) (*APIKeyConfig, error)

LoadAuthConfigFromFile loads auth configuration from a YAML file

type APIKeySettings

type APIKeySettings struct {
	Role      string   `yaml:"role"`
	Scopes    []string `yaml:"scopes"`
	TenantID  string   `yaml:"tenant_id"`
	ExpiresIn string   `yaml:"expires_in"` // Duration string like "30d"
}

APIKeySettings represents settings for an API key

type AuditEvent

type AuditEvent struct {
	Timestamp time.Time              `json:"timestamp"`
	EventType string                 `json:"event_type"`
	UserID    string                 `json:"user_id,omitempty"`
	TenantID  string                 `json:"tenant_id,omitempty"`
	AuthType  string                 `json:"auth_type"`
	Success   bool                   `json:"success"`
	IPAddress string                 `json:"ip_address,omitempty"`
	UserAgent string                 `json:"user_agent,omitempty"`
	Error     string                 `json:"error,omitempty"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
}

AuditEvent represents an authentication audit event

type AuditLogger

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

AuditLogger handles authentication audit logging

func NewAuditLogger

func NewAuditLogger(logger observability.Logger) *AuditLogger

NewAuditLogger creates a new audit logger

func (*AuditLogger) LogAPIKeyCreated

func (al *AuditLogger) LogAPIKeyCreated(ctx context.Context, userID, tenantID, keyName string)

LogAPIKeyCreated logs API key creation

func (*AuditLogger) LogAPIKeyRevoked

func (al *AuditLogger) LogAPIKeyRevoked(ctx context.Context, userID, tenantID, keyID string)

LogAPIKeyRevoked logs API key revocation

func (*AuditLogger) LogAuthAttempt

func (al *AuditLogger) LogAuthAttempt(ctx context.Context, event AuditEvent)

LogAuthAttempt logs an authentication attempt

func (*AuditLogger) LogAuthorizationDenial

func (al *AuditLogger) LogAuthorizationDenial(ctx context.Context, subject, resource, action, reason string)

LogAuthorizationDenial logs authorization denials

func (*AuditLogger) LogAuthorizationSuccess

func (al *AuditLogger) LogAuthorizationSuccess(ctx context.Context, subject, resource, action string)

LogAuthorizationSuccess logs successful authorization

func (*AuditLogger) LogPolicyChange

func (al *AuditLogger) LogPolicyChange(ctx context.Context, action string, policy interface{}, reason string)

LogPolicyChange logs policy changes

func (*AuditLogger) LogRateLimitExceeded

func (al *AuditLogger) LogRateLimitExceeded(ctx context.Context, identifier, ipAddress string)

LogRateLimitExceeded logs rate limit exceeded events

func (*AuditLogger) LogRoleAssignment

func (al *AuditLogger) LogRoleAssignment(ctx context.Context, action, user, role string)

LogRoleAssignment logs role assignment changes

type AuthConfig

type AuthConfig struct {
	ModelPath     string
	PolicyPath    string
	DBDriver      string
	DBSource      string
	Cache         cache.Cache
	Logger        observability.Logger
	Metrics       observability.MetricsClient
	Tracer        observability.StartSpanFunc
	AuditLogger   *AuditLogger
	CacheEnabled  bool
	CacheDuration time.Duration
}

AuthConfig holds configuration for the production authorizer

type AuthMiddleware

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

AuthMiddleware wraps the auth service with production features

func NewAuthMiddleware

func NewAuthMiddleware(service *Service, rateLimiter *RateLimiter, metrics *MetricsCollector, audit *AuditLogger) *AuthMiddleware

NewAuthMiddleware creates middleware with rate limiting and metrics

func SetupAuthentication

func SetupAuthentication(db *sqlx.DB, cache cache.Cache, logger observability.Logger, metrics observability.MetricsClient) (*AuthMiddleware, error)

SetupAuthentication sets up the enhanced authentication service

func SetupAuthenticationWithConfig

func SetupAuthenticationWithConfig(
	config *AuthSystemConfig,
	db *sqlx.DB,
	cache cache.Cache,
	logger observability.Logger,
	metrics observability.MetricsClient,
) (*AuthMiddleware, error)

SetupAuthenticationWithConfig provides full control over auth system initialization

func SetupEnhancedAuthentication

func SetupEnhancedAuthentication(
	db *sqlx.DB,
	cache cache.Cache,
	logger observability.Logger,
	metrics observability.MetricsClient,
) (*AuthMiddleware, error)

SetupEnhancedAuthentication maintains backward compatibility for enhanced auth

func (*AuthMiddleware) GinMiddleware

func (m *AuthMiddleware) GinMiddleware() gin.HandlerFunc

GinMiddleware returns a Gin middleware that uses the enhanced auth service

func (*AuthMiddleware) ValidateAPIKeyWithMetrics

func (m *AuthMiddleware) ValidateAPIKeyWithMetrics(ctx context.Context, apiKey string) (*User, error)

ValidateAPIKeyWithMetrics validates an API key with rate limiting and metrics

func (*AuthMiddleware) ValidateJWTWithMetrics

func (m *AuthMiddleware) ValidateJWTWithMetrics(ctx context.Context, tokenString string) (*User, error)

ValidateJWTWithMetrics validates a JWT with rate limiting and metrics

type AuthMode

type AuthMode string

AuthMode represents the authentication mode

const (
	AuthModeProduction AuthMode = "production"
	AuthModeTest       AuthMode = "test"
)

type AuthRequest

type AuthRequest struct {
	Subject  string                 `json:"subject"`
	Resource string                 `json:"resource"`
	Action   string                 `json:"action"`
	Tenant   string                 `json:"tenant"`
	Context  map[string]interface{} `json:"context,omitempty"`
}

AuthRequest represents an authorization request

type AuthSystemConfig

type AuthSystemConfig struct {
	Service     *ServiceConfig
	RateLimiter *RateLimiterConfig
	APIKeys     map[string]APIKeySettings
}

AuthSystemConfig holds complete auth system configuration

func TestAuthConfig

func TestAuthConfig() *AuthSystemConfig

TestAuthConfig creates a complete test configuration

type Authorizer

type Authorizer interface {
	Authorize(ctx context.Context, permission Permission) Decision
	CheckPermission(ctx context.Context, resource, action string) bool
}

Authorizer provides authorization functionality

func NewAuthorizer

func NewAuthorizer(config FactoryConfig) (Authorizer, error)

NewAuthorizer creates the appropriate authorizer based on configuration

type BaseOAuthProvider

type BaseOAuthProvider struct {
	ClientID     string
	ClientSecret string
	AuthURL      string
	TokenURL     string
	UserInfoURL  string
}

BaseOAuthProvider provides common OAuth functionality

func (*BaseOAuthProvider) GetAuthorizationURL

func (p *BaseOAuthProvider) GetAuthorizationURL(state, redirectURI string) string

GetAuthorizationURL returns the authorization URL

func (*BaseOAuthProvider) GetAuthorizationURLWithPKCE

func (p *BaseOAuthProvider) GetAuthorizationURLWithPKCE(state, redirectURI, codeChallenge string) string

GetAuthorizationURLWithPKCE returns the authorization URL with PKCE

func (*BaseOAuthProvider) ValidateState

func (p *BaseOAuthProvider) ValidateState(providedState, expectedState string) bool

ValidateState validates the state parameter

type Claims

type Claims struct {
	jwt.RegisteredClaims
	UserID   string   `json:"user_id"`
	TenantID string   `json:"tenant_id"`
	Scopes   []string `json:"scopes,omitempty"`
	Email    string   `json:"email,omitempty"`
}

Claims represents JWT claims

type CreateAPIKeyRequest

type CreateAPIKeyRequest struct {
	Name      string     `json:"name" binding:"required"`
	TenantID  string     `json:"tenant_id" binding:"required"`
	UserID    string     `json:"user_id"`
	KeyType   KeyType    `json:"key_type" binding:"required"`
	Scopes    []string   `json:"scopes"`
	ExpiresAt *time.Time `json:"expires_at"`

	// Gateway-specific
	AllowedServices []string `json:"allowed_services,omitempty"`
	ParentKeyID     *string  `json:"parent_key_id,omitempty"`

	// Rate limiting
	RateLimit *int `json:"rate_limit,omitempty"`
}

CreateAPIKeyRequest represents a request to create a new API key

type CredentialContext

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

CredentialContext wraps common credential operations

func NewCredentialContext

func NewCredentialContext(ctx context.Context) *CredentialContext

NewCredentialContext creates a new credential context wrapper

func (*CredentialContext) Context

func (cc *CredentialContext) Context() context.Context

Context returns the underlying context

func (*CredentialContext) GetCredential

func (cc *CredentialContext) GetCredential(tool string) (*models.TokenCredential, bool)

GetCredential retrieves a specific tool credential

func (*CredentialContext) GetCredentials

func (cc *CredentialContext) GetCredentials() (*models.ToolCredentials, bool)

GetCredentials retrieves all credentials

func (*CredentialContext) HasCredential

func (cc *CredentialContext) HasCredential(tool string) bool

HasCredential checks if a specific tool credential exists

func (*CredentialContext) WithCredentials

func (cc *CredentialContext) WithCredentials(creds *models.ToolCredentials) *CredentialContext

WithCredentials adds credentials to the context

type Decision

type Decision struct {
	Allowed bool   `json:"allowed"`
	Reason  string `json:"reason,omitempty"`
}

Decision represents an authorization decision

type FactoryConfig

type FactoryConfig struct {
	Mode             AuthMode
	ProductionConfig *AuthConfig
	Logger           observability.Logger
	Tracer           observability.StartSpanFunc
}

FactoryConfig contains configuration for the auth factory

type KeyConfig

type KeyConfig struct {
	Key      string
	Role     string
	Scopes   []string
	TenantID string
	UserID   string
}

KeyConfig is used for backward compatibility with existing code

type KeyType

type KeyType string

KeyType represents the type of API key

const (
	KeyTypeUser    KeyType = "user"    // Regular user access
	KeyTypeAdmin   KeyType = "admin"   // Full system access
	KeyTypeAgent   KeyType = "agent"   // AI agents
	KeyTypeGateway KeyType = "gateway" // Local MCP instances
)

func (KeyType) GetRateLimit

func (kt KeyType) GetRateLimit() int

GetRateLimit returns the default rate limit for a key type

func (KeyType) GetScopes

func (kt KeyType) GetScopes() []string

GetScopes returns the default scopes for a key type

func (*KeyType) Scan

func (kt *KeyType) Scan(value interface{}) error

Scan implements sql.Scanner for database operations

func (KeyType) String

func (kt KeyType) String() string

String implements fmt.Stringer

func (KeyType) Valid

func (kt KeyType) Valid() bool

Valid returns true if the key type is valid

func (KeyType) Value

func (kt KeyType) Value() (driver.Value, error)

Value implements driver.Valuer for database operations

type MetricsCollector

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

MetricsCollector collects authentication metrics

func NewMetricsCollector

func NewMetricsCollector(metrics observability.MetricsClient) *MetricsCollector

NewMetricsCollector creates a new metrics collector

func (*MetricsCollector) RecordAuthAttempt

func (mc *MetricsCollector) RecordAuthAttempt(ctx context.Context, authType string, success bool, duration time.Duration)

RecordAuthAttempt records an authentication attempt

func (*MetricsCollector) RecordRateLimitExceeded

func (mc *MetricsCollector) RecordRateLimitExceeded(ctx context.Context, identifier string)

RecordRateLimitExceeded records rate limit exceeded events

func (*MetricsCollector) UpdateActiveSessions

func (mc *MetricsCollector) UpdateActiveSessions(count float64)

UpdateActiveSessions updates the active sessions gauge

type OAuthProvider

type OAuthProvider interface {
	// GetAuthorizationURL returns the authorization URL
	GetAuthorizationURL(state, redirectURI string) string

	// GetAuthorizationURLWithPKCE returns the authorization URL with PKCE
	GetAuthorizationURLWithPKCE(state, redirectURI, codeChallenge string) string

	// ExchangeCode exchanges an authorization code for tokens
	ExchangeCode(ctx context.Context, code, redirectURI string) (*OAuthToken, error)

	// ExchangeCodeWithPKCE exchanges an authorization code with PKCE
	ExchangeCodeWithPKCE(ctx context.Context, code, redirectURI, codeVerifier string) (*OAuthToken, error)

	// RefreshToken refreshes an access token
	RefreshToken(ctx context.Context, refreshToken string) (*OAuthToken, error)

	// ValidateToken validates an access token and returns user info
	ValidateToken(ctx context.Context, accessToken string) (*OAuthUserInfo, error)

	// ValidateState validates the state parameter
	ValidateState(providedState, expectedState string) bool
}

OAuthProvider defines the interface for OAuth providers

type OAuthToken

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

OAuthToken represents an OAuth token

type OAuthUserInfo

type OAuthUserInfo struct {
	ID    string `json:"id"`
	Email string `json:"email"`
	Name  string `json:"name"`
}

OAuthUserInfo represents user information from OAuth provider

type PassthroughToken

type PassthroughToken struct {
	Provider string   // github, gitlab, bitbucket
	Token    string   // The actual token
	Scopes   []string // Token scopes if known
}

PassthroughToken represents a token to be passed to external services

func GetPassthroughToken

func GetPassthroughToken(ctx context.Context) (*PassthroughToken, bool)

GetPassthroughToken retrieves a passthrough token from the context

func GetPassthroughTokenFromGin

func GetPassthroughTokenFromGin(c interface{}) (*PassthroughToken, bool)

GetPassthroughTokenFromGin retrieves a passthrough token from Gin context This is an alternative to GetPassthroughToken for use in Gin handlers

type Permission

type Permission struct {
	Resource   string                 `json:"resource"`
	Action     string                 `json:"action"`
	Conditions map[string]interface{} `json:"conditions,omitempty"`
}

Permission represents a permission request

type Policy

type Policy struct {
	Subject  string `json:"subject"`
	Resource string `json:"resource"`
	Action   string `json:"action"`
	Effect   string `json:"effect,omitempty"`
	Tenant   string `json:"tenant,omitempty"`
}

Policy represents an authorization policy

type ProductionAuthorizer

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

ProductionAuthorizer implements production-grade authorization

func NewProductionAuthorizer

func NewProductionAuthorizer(config AuthConfig) (*ProductionAuthorizer, error)

NewProductionAuthorizer creates a production authorizer

func (*ProductionAuthorizer) AddPolicy

func (a *ProductionAuthorizer) AddPolicy(ctx context.Context, policy Policy) error

AddPolicy adds a new authorization policy

func (*ProductionAuthorizer) AddRole

func (a *ProductionAuthorizer) AddRole(ctx context.Context, user, role string) error

AddRole assigns a role to a user

func (*ProductionAuthorizer) Authorize

func (a *ProductionAuthorizer) Authorize(ctx context.Context, permission Permission) Decision

Authorize implements the Authorizer interface

func (*ProductionAuthorizer) AuthorizeRequest

func (a *ProductionAuthorizer) AuthorizeRequest(ctx context.Context, req *AuthRequest) error

AuthorizeRequest checks if a subject can perform an action on a resource

func (*ProductionAuthorizer) CheckPermission

func (a *ProductionAuthorizer) CheckPermission(ctx context.Context, resource, action string) bool

CheckPermission implements the Authorizer interface

func (*ProductionAuthorizer) GetRolesForUser

func (a *ProductionAuthorizer) GetRolesForUser(ctx context.Context, user string) ([]string, error)

GetRolesForUser returns all roles assigned to a user

func (*ProductionAuthorizer) GetUsersForRole

func (a *ProductionAuthorizer) GetUsersForRole(ctx context.Context, role string) ([]string, error)

GetUsersForRole returns all users assigned to a role

func (*ProductionAuthorizer) RemovePolicy

func (a *ProductionAuthorizer) RemovePolicy(ctx context.Context, policy Policy) error

RemovePolicy removes an authorization policy

func (*ProductionAuthorizer) RemoveRole

func (a *ProductionAuthorizer) RemoveRole(ctx context.Context, user, role string) error

RemoveRole removes a role from a user

type RateLimiter

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

RateLimiter provides rate limiting for authentication endpoints

func NewRateLimiter

func NewRateLimiter(cache cache.Cache, logger observability.Logger, config *RateLimiterConfig) *RateLimiter

NewRateLimiter creates a new rate limiter

func (*RateLimiter) CheckLimit

func (rl *RateLimiter) CheckLimit(ctx context.Context, identifier string) error

CheckLimit checks if the identifier has exceeded rate limits

func (*RateLimiter) GetLockoutPeriod

func (rl *RateLimiter) GetLockoutPeriod() time.Duration

GetLockoutPeriod returns the configured lockout period

func (*RateLimiter) RecordAttempt

func (rl *RateLimiter) RecordAttempt(ctx context.Context, identifier string, success bool)

RecordAttempt records an authentication attempt

type RateLimiterConfig

type RateLimiterConfig struct {
	Enabled       bool          // Whether rate limiting is enabled
	MaxAttempts   int           // Max attempts per window
	WindowSize    time.Duration // Time window for attempts
	LockoutPeriod time.Duration // Lockout duration after max attempts
}

RateLimiterConfig holds rate limiter configuration

func DefaultRateLimiterConfig

func DefaultRateLimiterConfig() *RateLimiterConfig

DefaultRateLimiterConfig returns sensible defaults

func TestRateLimiterConfig

func TestRateLimiterConfig() *RateLimiterConfig

TestRateLimiterConfig returns test-friendly defaults

type Service

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

Service provides authentication services

func NewService

func NewService(config *ServiceConfig, db *sqlx.DB, cache cache.Cache, logger observability.Logger) *Service

NewService creates a new auth service

func (*Service) AddAPIKey

func (s *Service) AddAPIKey(key string, settings APIKeySettings) error

AddAPIKey adds an API key to the service at runtime (thread-safe)

func (*Service) AuthorizeScopes

func (s *Service) AuthorizeScopes(user *User, requiredScopes []string) error

AuthorizeScopes checks if a user has the required scopes

func (*Service) CreateAPIKey

func (s *Service) CreateAPIKey(ctx context.Context, tenantID, userID, name string, scopes []string, expiresAt *time.Time) (*APIKey, error)

CreateAPIKey creates a new API key

Example
package main

import (
	"context"
	"fmt"

	"github.com/S-Corkum/devops-mcp/pkg/auth"
	"github.com/S-Corkum/devops-mcp/pkg/observability"
)

func main() {
	// Create auth service
	config := auth.DefaultConfig()
	logger := observability.NewLogger("example")
	authService := auth.NewService(config, nil, nil, logger)

	// Create an API key
	ctx := context.Background()
	apiKey, err := authService.CreateAPIKey(
		ctx,
		"tenant-123",
		"user-456",
		"My API Key",
		[]string{"read", "write"},
		nil, // No expiration
	)

	if err == nil {
		fmt.Printf("Created API key: %s\n", apiKey.Name)
	}
}
Output:

Created API key: My API Key

func (*Service) CreateAPIKeyWithType

func (s *Service) CreateAPIKeyWithType(ctx context.Context, req CreateAPIKeyRequest) (*APIKey, error)

CreateAPIKeyWithType creates a new API key with the specified type

func (*Service) GenerateJWT

func (s *Service) GenerateJWT(ctx context.Context, user *User) (string, error)

GenerateJWT generates a new JWT token for a user

Example
package main

import (
	"context"
	"fmt"

	"github.com/S-Corkum/devops-mcp/pkg/auth"
	"github.com/S-Corkum/devops-mcp/pkg/observability"
)

func main() {
	// Create auth service
	config := auth.DefaultConfig()
	config.JWTSecret = "example-secret"
	logger := observability.NewLogger("example")
	authService := auth.NewService(config, nil, nil, logger)

	// Generate a JWT token
	ctx := context.Background()
	user := &auth.User{
		ID:       "user-123",
		TenantID: "tenant-456",
		Email:    "user@example.com",
		Scopes:   []string{"read"},
	}

	_, err := authService.GenerateJWT(ctx, user)
	if err == nil {
		fmt.Println("Generated JWT token")
	}
}
Output:

Generated JWT token

func (*Service) GetConfig

func (s *Service) GetConfig() *ServiceConfig

GetConfig returns the service configuration

func (*Service) GinMiddleware

func (s *Service) GinMiddleware(authTypes ...Type) gin.HandlerFunc

GinMiddleware creates a Gin middleware for authentication

Example
package main

import (
	"fmt"
	"net/http/httptest"

	"github.com/S-Corkum/devops-mcp/pkg/auth"
	"github.com/S-Corkum/devops-mcp/pkg/observability"
	"github.com/gin-gonic/gin"
)

func main() {
	// Create auth service
	config := auth.DefaultConfig()
	config.JWTSecret = "example-secret"
	logger := observability.NewLogger("example")
	authService := auth.NewService(config, nil, nil, logger)

	// Initialize some API keys
	authService.InitializeDefaultAPIKeys(map[string]string{
		"test-key": "read",
	})

	// Create Gin router with auth
	gin.SetMode(gin.ReleaseMode)
	router := gin.New()

	// Apply auth middleware
	router.Use(authService.GinMiddleware(auth.TypeAPIKey))

	// Add a protected endpoint
	router.GET("/api/data", func(c *gin.Context) {
		user, _ := auth.GetUserFromContext(c)
		c.JSON(200, gin.H{
			"message": fmt.Sprintf("Hello user %s", user.ID),
		})
	})

	// Test the endpoint with valid API key
	req := httptest.NewRequest("GET", "/api/data", nil)
	req.Header.Set("Authorization", "Bearer test-key")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	fmt.Println("Response:", w.Code)
}
Output:

Response: 200

func (*Service) GinMiddlewareWithPassthrough

func (s *Service) GinMiddlewareWithPassthrough(authTypes ...Type) gin.HandlerFunc

GinMiddlewareWithPassthrough creates a Gin middleware for authentication with token passthrough support

func (*Service) InitializeAPIKeysWithConfig

func (s *Service) InitializeAPIKeysWithConfig(keysConfig map[string]interface{})

InitializeAPIKeysWithConfig initializes API keys with full configuration including tenant IDs

func (*Service) InitializeDefaultAPIKeys

func (s *Service) InitializeDefaultAPIKeys(keys map[string]string)

InitializeDefaultAPIKeys initializes default API keys from configuration

func (*Service) LoadAPIKeys

func (s *Service) LoadAPIKeys(config *APIKeyConfig) error

LoadAPIKeys loads API keys based on environment

func (*Service) LoadAuthConfigBasedOnEnvironment

func (s *Service) LoadAuthConfigBasedOnEnvironment() error

LoadAuthConfigBasedOnEnvironment loads the appropriate auth config file

func (*Service) RequireScopes

func (s *Service) RequireScopes(scopes ...string) gin.HandlerFunc

RequireScopes creates a middleware that checks for required scopes

func (*Service) RevokeAPIKey

func (s *Service) RevokeAPIKey(ctx context.Context, apiKey string) error

RevokeAPIKey revokes an API key

func (*Service) StandardMiddleware

func (s *Service) StandardMiddleware(authTypes ...Type) func(http.Handler) http.Handler

StandardMiddleware returns standard HTTP middleware for authentication

Example
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/S-Corkum/devops-mcp/pkg/auth"
	"github.com/S-Corkum/devops-mcp/pkg/observability"
)

func main() {
	// Create auth service
	config := auth.DefaultConfig()
	logger := observability.NewLogger("example")
	authService := auth.NewService(config, nil, nil, logger)

	// Initialize some API keys
	authService.InitializeDefaultAPIKeys(map[string]string{
		"test-key": "read",
	})

	// Create standard HTTP handler
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		user, ok := auth.GetUserFromRequest(r)
		if ok {
			if _, err := fmt.Fprintf(w, "Hello user %s", user.ID); err != nil {
				// Log error if needed - in example code, we'll just ignore
				_ = err
			}
		}
	})

	// Wrap with auth middleware
	protectedHandler := authService.StandardMiddleware(auth.TypeAPIKey)(handler)

	// Test the handler
	req := httptest.NewRequest("GET", "/api/data", nil)
	req.Header.Set("Authorization", "test-key")
	w := httptest.NewRecorder()
	protectedHandler.ServeHTTP(w, req)

	fmt.Println("Response:", w.Code)
}
Output:

Response: 200

func (*Service) StandardMiddlewareWithPassthrough

func (s *Service) StandardMiddlewareWithPassthrough(authTypes ...Type) func(http.Handler) http.Handler

StandardMiddlewareWithPassthrough returns standard HTTP middleware for authentication with passthrough support

func (*Service) ValidateAPIKey

func (s *Service) ValidateAPIKey(ctx context.Context, apiKey string) (*User, error)

ValidateAPIKey validates an API key and returns the associated user

func (*Service) ValidateJWT

func (s *Service) ValidateJWT(ctx context.Context, tokenString string) (*User, error)

ValidateJWT validates a JWT token and returns the associated user

type ServiceConfig

type ServiceConfig struct {
	JWTSecret         string
	JWTExpiration     time.Duration
	APIKeyHeader      string
	EnableAPIKeys     bool
	EnableJWT         bool
	CacheEnabled      bool
	CacheTTL          time.Duration
	MaxFailedAttempts int
	LockoutDuration   time.Duration
}

ServiceConfig represents auth configuration

func DefaultConfig

func DefaultConfig() *ServiceConfig

DefaultConfig returns the default configuration

type TestCache

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

TestCache implements cache.Cache interface for testing

func NewTestCache

func NewTestCache() *TestCache

NewTestCache creates a new test cache instance

func (*TestCache) Close

func (c *TestCache) Close() error

Close is a no-op for test cache

func (*TestCache) Delete

func (c *TestCache) Delete(ctx context.Context, key string) error

Delete removes a key from cache

func (*TestCache) Exists

func (c *TestCache) Exists(ctx context.Context, key string) (bool, error)

Exists checks if key exists

func (*TestCache) Flush

func (c *TestCache) Flush(ctx context.Context) error

Flush clears all cache data

func (*TestCache) Get

func (c *TestCache) Get(ctx context.Context, key string, value interface{}) error

Get retrieves a value from cache, returns error if not found

func (*TestCache) Set

func (c *TestCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error

Set stores a value in cache

type TestProvider

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

TestProvider implements the Authorizer interface for test environments It provides JWT-based authentication with rate limiting and audit logging

func NewTestProvider

func NewTestProvider(logger observability.Logger, tracer observability.StartSpanFunc) (*TestProvider, error)

NewTestProvider creates a new test authentication provider

func (*TestProvider) Authorize

func (tp *TestProvider) Authorize(ctx context.Context, permission Permission) Decision

Authorize implements the Authorizer interface

func (*TestProvider) CheckPermission

func (tp *TestProvider) CheckPermission(ctx context.Context, resource, action string) bool

CheckPermission implements the Authorizer interface

func (*TestProvider) CleanupExpiredTokens

func (tp *TestProvider) CleanupExpiredTokens()

CleanupExpiredTokens removes expired tokens from tracking

func (*TestProvider) Close

func (tp *TestProvider) Close() error

Close closes the test provider

func (*TestProvider) GenerateTestToken

func (tp *TestProvider) GenerateTestToken(userID, tenantID uuid.UUID, role string, scopes []string) (string, error)

GenerateTestToken generates a JWT token for testing

func (*TestProvider) GetUserRole

func (tp *TestProvider) GetUserRole(ctx context.Context, userID, tenantID uuid.UUID) (string, error)

GetUserRole returns the role for a user (test helper)

func (*TestProvider) ListUserPermissions

func (tp *TestProvider) ListUserPermissions(ctx context.Context, userID, tenantID uuid.UUID) ([]string, error)

ListUserPermissions returns permissions for a user (test helper)

func (*TestProvider) RevokeToken

func (tp *TestProvider) RevokeToken(tokenID string) error

RevokeToken revokes a test token

func (*TestProvider) ValidateTestToken

func (tp *TestProvider) ValidateTestToken(tokenString string) (*Claims, error)

ValidateTestToken validates a test JWT token

type Type

type Type string

Type represents the type of authentication

const (
	TypeAPIKey Type = "api_key"
	TypeJWT    Type = "jwt"
	TypeNone   Type = "none"
)

type User

type User struct {
	ID       string                 `json:"id"`
	TenantID string                 `json:"tenant_id"`
	Email    string                 `json:"email,omitempty"`
	Scopes   []string               `json:"scopes,omitempty"`
	AuthType Type                   `json:"auth_type"`
	Metadata map[string]interface{} `json:"metadata,omitempty"`
}

User represents an authenticated user

func GetUserFromContext

func GetUserFromContext(c *gin.Context) (*User, bool)

GetUserFromContext extracts the authenticated user from the Gin context

func GetUserFromRequest

func GetUserFromRequest(r *http.Request) (*User, bool)

GetUserFromRequest extracts the authenticated user from the request context

Jump to

Keyboard shortcuts

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