From e95f47874a86581051762f975b1507cda9091877 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sat, 14 Jun 2025 01:56:00 +0200 Subject: [PATCH] Add authentication system with Authelia integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add /auth/user API endpoint to extract and return Authelia headers - Create account.html test page for authentication verification - Update documentation in CLAUDE.md with authentication setup details - Add account page to main feature list in index.html 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- CLAUDE.md | 24 ++++++++++++++++ account.html | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 4 +++ main.go | 38 ++++++++++++++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 account.html diff --git a/CLAUDE.md b/CLAUDE.md index a1d2948..d90c43e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -18,6 +18,30 @@ There is a reverse proxy rewrite rule in place. To call any API endpoint from th - API endpoint URLs should be: `playground.shiny.space/api/yourendpointhere` - Example: `/randomnumber` endpoint becomes `/api/randomnumber` +## Authentication +The setup uses Caddy with Authelia for authentication: +- Caddy acts as reverse proxy and checks with Authelia before allowing access to protected pages +- When authenticated, Authelia adds headers to requests that reach the Go API +- The Go API can read these headers to get user information + +### Authentication Headers from Authelia +The following headers are available in authenticated requests: +- `Remote-User`: Username of the authenticated user +- `Remote-Name`: Display name of the user +- `Remote-Email`: Email address of the user +- `Remote-Groups`: User's group memberships + +### Authentication API Endpoint +- `/api/auth/user` (GET) - Returns user information and all headers for debugging +- Protected pages can use JavaScript to fetch this endpoint to get current user info +- Returns JSON with username, name, email, groups, and complete headers object + +### Authentication Test Page +- `account.html` - Test page that requires authentication to access +- Displays user information by calling `/api/auth/user` +- Shows both structured user info and raw headers for debugging +- Configure Caddy to require authentication for this page to test the setup + ## Development To rebuild the Go API after making changes: - Run `go build -o api` in the project directory diff --git a/account.html b/account.html new file mode 100644 index 0000000..4698695 --- /dev/null +++ b/account.html @@ -0,0 +1,77 @@ + + + + + + Account Information + + + +

Account Information

+

Your authenticated user information:

+ +
+

User Details

+
Loading user information...
+
+ +
+

All Headers (Debug)

+
Loading headers...
+
+ + + + + + \ No newline at end of file diff --git a/index.html b/index.html index 503933b..a3462b6 100644 --- a/index.html +++ b/index.html @@ -27,6 +27,10 @@ Items Management
Full CRUD demo with SQLite database - create, view, and delete items with persistent storage.
+
  • + Account Information +
    Authentication test page - displays user info and headers from Authelia (requires authentication).
    +
  • diff --git a/main.go b/main.go index 2c1af6f..dbc5b3f 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,14 @@ type Item struct { Name string `json:"name"` } +type UserInfo struct { + Username string `json:"username"` + Name string `json:"name"` + Email string `json:"email"` + Groups string `json:"groups"` + Headers map[string]string `json:"headers"` +} + var db *sql.DB func initDB() { @@ -81,6 +89,9 @@ func main() { // Items API endpoints http.HandleFunc("/items", handleItems) http.HandleFunc("/items/", handleItemDelete) + + // Auth endpoints + http.HandleFunc("/auth/user", handleAuthUser) log.Println("API running on :3847") http.ListenAndServe("127.0.0.1:3847", nil) @@ -224,3 +235,30 @@ func handleItemDelete(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(map[string]string{"message": "Item deleted successfully"}) } + +func handleAuthUser(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + + if r.Method != "GET" { + w.WriteHeader(http.StatusMethodNotAllowed) + json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"}) + return + } + + // Collect all headers for debugging + headers := make(map[string]string) + for name, values := range r.Header { + headers[name] = strings.Join(values, ", ") + } + + // Extract common Authelia headers + userInfo := UserInfo{ + Username: r.Header.Get("Remote-User"), + Name: r.Header.Get("Remote-Name"), + Email: r.Header.Get("Remote-Email"), + Groups: r.Header.Get("Remote-Groups"), + Headers: headers, + } + + json.NewEncoder(w).Encode(userInfo) +}