How Kaneo Handles Authentication: A Complete Technical Guide

Kaneo uses Better Auth as its authentication foundation, combining JWT tokens, session cookies, API keys, and OAuth providers to secure both its API and React-based web interface.

Kaneo is an open-source project management platform built by usekaneo. Understanding how Kaneo handles authentication is essential for contributors, self-hosters, and security auditors. This article breaks down the complete authentication architecture based on the actual source code implementation.

Core Authentication Components

Kaneo's authentication stack relies on five primary mechanisms working together:

Component Purpose Implementation
JWT tokens Stateless session proof Signed with AUTH_SECRET (minimum 32 characters) from .env
Session cookies Persistent browser sessions HTTP-only, SameSite=Lax cookies managed by Better Auth
API keys Programmatic access Validated by authenticate-api-request.ts via Authorization: Bearer <key> header
OAuth providers SSO login GitHub, Google, Discord, and custom OIDC through environment variables
Turnstile (CAPTCHA) Bot protection Verified by verify-turnstile.ts on sign-up and sensitive actions

Authentication Request Flow

Understanding the sequence of authentication checks helps debug issues and extend the system:

  1. Request enters the API through apps/api/src/auth.ts where Better Auth middleware extracts the JWT cookie or Bearer token.

  2. Better Auth validates the token and injects context—c.get("user") and c.get("userId") become available to downstream handlers.

  3. API-key validation occurs in parallel for programmatic requests via authenticate-api-request.ts, which may enforce additional scopes.

  4. Authorization checks apply fine-grained permissions through utilities like authorize-asset-access.ts and require-workspace-permission.ts.

  5. Frontend synchronization happens through auth-client.ts, which supplies session tokens to TanStack Query hooks and handles automatic refresh.

Key Implementation Files

These source files define Kaneo's authentication behavior:

File Path Responsibility
apps/api/src/auth.ts Central Better Auth configuration and middleware registration
apps/api/src/utils/authenticate-api-request.ts API key validation logic
apps/api/src/utils/authorize-asset-access.ts Asset permission enforcement
apps/web/src/lib/auth-client.ts React client wrapper for Better Auth
apps/web/src/routes/auth.tsx UI routes for login, registration, and SSO
apps/api/src/utils/verify-turnstile.ts CAPTCHA verification utility

Code Examples: Authentication in Practice

Protecting an API Route

The Better Auth middleware automatically populates the Hono context with user information:

// apps/api/src/some-feature/controllers/example.ts
import { Hono } from "hono";

export const example = new Hono()
  .get(
    "/protected",
    async (c) => {
      const userId = c.get("userId");
      if (!userId) {
        return c.json({ error: "Unauthenticated" }, 401);
      }
      // Business logic executes only for authenticated users
      return c.json({ message: `Hello user ${userId}` });
    },
  );

Configuring the Frontend Auth Client

The shared client ensures consistent authentication behavior across the React application:

// apps/web/src/lib/auth-client.ts
import { createAuthClient } from "@better-auth/react";
import { VITE_API_URL } from "@/config";

export const authClient = createAuthClient({
  apiUrl: VITE_API_URL,
  // Automatic token refresh is handled internally
});

Protecting a React Component

Conditional rendering based on authentication state:

// apps/web/src/routes/dashboard.tsx
import { useAuth } from "@/lib/auth-client";

export default function Dashboard() {
  const { user, loading } = useAuth();

  if (loading) return <Spinner />;
  if (!user) return <Redirect to="/login" />;

  return <div>Welcome, {user.email}!</div>;
}

Security Mechanisms

Kaneo implements multiple defense layers to protect authentication data:

  • HTTP-only cookies prevent JavaScript access to session tokens, mitigating XSS attacks
  • SameSite=Lax cookie policy restricts cross-origin request contexts
  • JWT signatures guarantee token integrity without database lookups
  • Hashed API keys stored in the database support revocation at any time
  • Turnstile integration blocks automated account creation attempts
  • Role-based access control enforced through workspace membership checks

Environment Configuration

Authentication behavior is controlled through environment variables:


# Required: Minimum 32-character secret for JWT signing

AUTH_SECRET=your-super-secret-32-char-minimum-key

# OAuth provider credentials (optional)

GITHUB_CLIENT_ID=xxx
GITHUB_CLIENT_SECRET=xxx
GOOGLE_CLIENT_ID=xxx
GOOGLE_CLIENT_SECRET=xxx

# Turnstile for bot protection

TURNSTILE_SECRET_KEY=xxx

Summary

  • Better Auth provides the foundational authentication library for Kaneo's entire stack
  • Dual token system separates browser sessions (JWT cookies) from API access (Bearer keys)
  • Middleware-based validation in apps/api/src/auth.ts injects user context into all API routes
  • Fine-grained authorization utilities enforce workspace and asset-level permissions
  • React integration through auth-client.ts provides automatic session management
  • Security-hardened defaults include HTTP-only cookies, JWT signing, and CAPTCHA protection

Frequently Asked Questions

What authentication library does Kaneo use?

Kaneo uses Better Auth, a flexible TypeScript authentication library that supports multiple login methods including credentials, OAuth providers, and API keys. The integration is configured in apps/api/src/auth.ts and consumed by the React frontend through @better-auth/react.

How does Kaneo validate API requests from external services?

External services authenticate using API keys passed in the Authorization: Bearer <key> header. The apps/api/src/utils/authenticate-api-request.ts utility validates these keys against hashed database records and can enforce additional permission scopes beyond standard user sessions.

Where are authentication routes defined in the Kaneo codebase?

All user-facing authentication UI—login, registration, password reset, and OAuth callbacks—lives in apps/web/src/routes/auth.tsx. These routes use the shared auth-client.ts to communicate with the Better Auth backend, ensuring consistent behavior between server and client authentication state.

How does Kaneo prevent automated account creation?

Kaneo integrates Cloudflare Turnstile for invisible CAPTCHA protection. The apps/api/src/utils/verify-turnstile.ts utility validates Turnstile tokens on registration and other sensitive actions, blocking bots without degrading legitimate user experience.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →