Deprecated: Function get_magic_quotes_gpc() is deprecated in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 99

Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 619

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1169

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176
E627 GitHub - TBNilles/gokeeper: Keycloak Wrapper package
Nothing Special   »   [go: up one dir, main page]

Skip to content

TBNilles/gokeeper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ” GoKeeper

GoKeeper is a comprehensive authentication and authorization wrapper for Go applications that integrates with Keycloak. It provides both a standalone service and a library that can be imported into existing projects, along with a JavaScript client for seamless frontend integration.

✨ Features

  • Keycloak Integration: Full wrapper around the go-keycloak library
  • Secure Cookie Management: Automatic chunking for large credential data
  • JavaScript Client: Clean, modern JavaScript class with read-only properties
  • Resource-Based Authorization: Granular access control for different resources
  • Standalone or Library: Use as a service or import into existing projects
  • Auto-Authentication: Automatic session validation and renewal
  • Mock Service: Built-in mock for development and testing
  • CORS Support: Cross-origin request handling
  • Role-Based Access: Fine-grained role checking capabilities

πŸš€ Quick Start

1. Clone and Setup

# Clone the project to your GolandProjects directory
cp -r gokeeper (https://github.com/TBNilles/gokeeper)

cd gokeeper
go mod tidy

2. Run as Standalone Service

# Run with default configuration (uses mock Keycloak)
go run main.go

# Run with custom configuration
KEYCLOAK_URL=http://localhost:8080 \
KEYCLOAK_REALM=myrealm \
KEYCLOAK_CLIENT_ID=myapp \
KEYCLOAK_CLIENT_SECRET=secret \
go run main.go

3. View the Demo

Open your browser to http://localhost:8081 to see the interactive demo.

πŸ“š API Endpoints

Authentication Endpoints

  • POST /api/auth/authenticate - Login with username/password
  • GET /api/auth/validate - Validate current session
  • POST /api/auth/resource-authenticate - Check resource access
  • POST /api/auth/logout - Logout user

Example Endpoints

  • GET /api/protected/profile - Get current user (requires auth)
  • GET /api/admin/users - Admin only endpoint
  • GET /api/public/info - Public endpoint

🎯 JavaScript Client Usage

The JavaScript client provides a clean, modern interface for authentication:

// Initialize GoKeeper client
const auth = new GoKeeper();

// Authenticate user
const success = await auth.authenticate('username', 'password');

// Access user properties (read-only)
if (auth.isAuthenticated) {
    console.log(auth.user.first_name);
    console.log(auth.user.last_name);
    console.log(auth.user.roles); // Array of roles
}

// Check resource access
const canAccess = await auth.resourceAuthenticate('admin', 'read');

// Check roles
const isAdmin = auth.hasRole('admin');
const hasAnyRole = auth.hasAnyRole(['admin', 'user']);

// Event listeners
auth.on('login', (user) => console.log('User logged in:', user));
auth.on('logout', () => console.log('User logged out'));
auth.on('session-expired', () => console.log('Session expired'));

πŸ”§ Configuration

Configure GoKeeper using environment variables:

# Keycloak Configuration
KEYCLOAK_URL=http://localhost:8080
KEYCLOAK_REALM=master
KEYCLOAK_CLIENT_ID=gokeeper
KEYCLOAK_CLIENT_SECRET=your-client-secret

# Server Configuration
SERVER_PORT=8081
SERVER_HOST=localhost

# Cookie Configuration
COOKIE_DOMAIN=localhost
COOKIE_SECURE=false
COOKIE_MAX_AGE=3600
COOKIE_CHUNK_SIZE=4000

# Security
JWT_SECRET=your-secret-key-change-in-production

# Development
DEBUG=true

πŸ“¦ Import as Library

You can import GoKeeper into your existing Go project:

package main

import (
    "gokeeper/auth"
    "gokeeper/config"
    "gokeeper/web"
    
    "github.com/gin-gonic/gin"
)

func main() {
    // Load configuration
    cfg := config.New()
    
    // Create auth service
    authService := auth.NewKeycloakService(
        cfg.KeycloakURL,
        cfg.KeycloakRealm,
        cfg.KeycloakClientID,
        cfg.KeycloakSecret,
        cfg.JWTSecret,
    )
    
    // Create cookie manager
    cookieManager := auth.NewCookieManager(
        cfg.CookieDomain,
        cfg.CookieSecure,
        cfg.CookieMaxAge,
        cfg.CookieChunkSize,
    )
    
    // Create handler
    handler := web.NewHandler(authService, cookieManager, cfg)
    
    // Setup routes
    r := gin.Default()
    handler.SetupRoutes(r)
    
    // Add your own routes
    protected := r.Group("/my-api")
    protected.Use(handler.AuthRequired())
    {
        protected.GET("/data", func(c *gin.Context) {
            user, _ := c.Get("user")
            // Your protected endpoint logic
        })
    }
    
    r.Run(":8080")
}

πŸ”’ Security Features

Cookie Chunking

GoKeeper automatically handles large authentication data by splitting it into multiple cookies when needed:

  • Maximum 4KB per cookie (configurable)
  • Automatic reconstruction of chunked data
  • Secure cookie attributes (HttpOnly, SameSite)
  • Automatic cleanup of expired chunks

Resource-Based Authorization

Define granular access controls:

// Check if user can read admin resources
authorized, err := authService.ResourceAuthenticate(user, "admin", "read")

// Check if user can write to user resources
authorized, err := authService.ResourceAuthenticate(user, "user", "write")

Role-Based Access Control

// JavaScript client
auth.hasRole('admin')
auth.hasAnyRole(['admin', 'moderator'])

// Go middleware
router.Use(handler.RequireRole("admin", "moderator"))

πŸ§ͺ Development & Testing

Mock Keycloak Service

For development and testing, GoKeeper includes a mock Keycloak service:

// Use mock service
authService := auth.NewMockKeycloakService()

// Test users available:
// Username: admin, Password: any (roles: admin, user)
// Username: user, Password: any (roles: user)

Testing the JavaScript Client

The example page includes comprehensive testing tools:

  1. Login/logout functionality
  2. Resource access testing
  3. Role checking
  4. Session management
  5. API demonstrations

πŸ“ Project Structure

gokeeper/
β”œβ”€β”€ config/
β”‚   └── config.go          # Configuration management
β”œβ”€β”€ auth/
β”‚   β”œβ”€β”€ auth.go            # Core authentication interfaces
β”‚   β”œβ”€β”€ cookies.go         # Cookie chunking and management
β”‚   └── keycloak.go        # Keycloak service implementation
β”œβ”€β”€ web/
β”‚   └── handlers.go        # HTTP handlers and middleware
β”œβ”€β”€ static/
β”‚   β”œβ”€β”€ gokeeper.js        # JavaScript client library
β”‚   └── example.html       # Demo/example page
β”œβ”€β”€ examples/
β”‚   └── integration/       # Integration examples
β”œβ”€β”€ main.go                # Standalone service entry point
β”œβ”€β”€ go.mod                 # Go module definition
└── README.md             # This file

πŸ”„ Integration Examples

With Existing Gin Application

// Add GoKeeper to existing app
func addAuth(r *gin.Engine) {
    cfg := config.New()
    authService := auth.NewKeycloakService(/* config */)
    cookieManager := auth.NewCookieManager(/* config */)
    handler := web.NewHandler(authService, cookieManager, cfg)
    
    // Add auth routes
    handler.SetupRoutes(r)
    
    // Protect existing routes
    api := r.Group("/api")
    api.Use(handler.AuthRequired())
    // ... your existing routes
}

Frontend Integration

<!DOCTYPE html>
<html>
<head>
    <script src="/static/gokeeper.js"></script>
</head>
<body>
    <script>
        const auth = new GoKeeper();
        
        // Auto-validate session on page load
        auth.autoAuthenticate().then(isAuthenticated => {
            if (!isAuthenticated) {
                // Show login form
            } else {
                // Show authenticated content
                document.getElementById('username').textContent = auth.user.first_name;
            }
        });
    </script>
</body>
</html>

πŸ› οΈ Advanced Usage

Custom Resource Rules

Extend the resource authentication logic:

// In your KeycloakService implementation
func (ks *KeycloakService) checkResourceAccess(user *User, resource string, action string) bool {
    // Custom business logic here
    switch resource {
    case "financial-data":
        return user.HasAnyRole([]string{"finance", "admin"})
    case "hr-records":
        return user.HasRole("hr") || user.HasRole("admin")
    default:
        return false
    }
}

Custom Middleware

Create custom authentication middleware:

func CustomAuthMiddleware(authService auth.AuthService) gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("Authorization")
        if token == "" {
            c.JSON(401, gin.H{"error": "No token provided"})
            c.Abort()
            return
        }
        
        user, err := authService.Validate(token)
        if err != nil {
            c.JSON(401, gin.H{"error": "Invalid token"})
            c.Abort()
            return
        }
        
        c.Set("user", user)
        c.Next()
    }
}

πŸ› Troubleshooting

Common Issues

  1. Cookie size limits: If you're getting cookie errors, reduce COOKIE_CHUNK_SIZE
  2. CORS issues: Enable debug mode or configure proper origins
  3. Keycloak connection: Verify KEYCLOAK_URL and network connectivity
  4. Session expiry: Check token expiration and refresh logic

Debug Mode

Enable debug mode for detailed logging:

DEBUG=true go run main.go

πŸ“„ License

This project is licensed under the MIT License. See the LICENSE file for details.

🀝 Contributing

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

πŸ“ž Support

If you have questions or need help:

  1. Check the example implementation in static/example.html
  2. Review the API documentation above
  3. Enable debug mode for detailed logging
  4. Create an issue on the project repository

GoKeeper - Secure, Simple, Scalable Authentication for Go & JavaScript πŸ”

About

Keycloak Wrapper package

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published
0