# Authentication and Authorization Mechanisms in WeKnora: A Complete Technical Guide

> Explore WeKnora's robust authentication and authorization mechanisms. Learn how JWT, API keys, OIDC, and RBAC ensure secure, fine-grained access control for your applications.

- Repository: [Tencent/WeKnora](https://github.com/tencent/WeKnora)
- Tags: how-to-guide
- Published: 2026-09-13

---

**WeKnora secures its APIs with a layered architecture that combines JWT token validation, API-key gating, OIDC verification, and role-based access control to enforce fine-grained, tenant-scoped permissions.**

Tencent/WeKnora implements a comprehensive security framework designed for multi-tenant AI operations. The platform authenticates every incoming request through multiple verification layers before authorizing actions based on hierarchical roles and strict tenant isolation. Understanding these authentication and authorization mechanisms in WeKnora is essential for securing custom integrations, managing cross-tenant access, and ensuring proper resource isolation.

## Core Authentication Methods

WeKnora supports four distinct authentication pathways, each serving specific use cases from standard user sessions to privileged sandbox operations.

### JWT Access Token Validation

The primary authentication mechanism uses **HS256-signed JWT tokens** validated in [`internal/middleware/auth.go`](https://github.com/Tencent/WeKnora/blob/main/internal/middleware/auth.go) (lines 150-156). When a request arrives with an `Authorization: Bearer <token>` header, the middleware invokes `userService.ValidateToken` defined in [`internal/application/service/user.go`](https://github.com/Tencent/WeKnora/blob/main/internal/application/service/user.go) (lines 1216-1221).

The validation logic enforces strict claim requirements:

- The `aud` claim must equal `weknora`
- The token must contain a valid `user_id` claim
- The signature is verified against the server-side `JWT_SECRET`
- An optional `tenant_id` claim specifies the target tenant (used as *jwtTenantID*)

If the `tenant_id` claim is absent, the system falls back to the user's stored default tenant.

### API-Key Gating for Service-to-Service Communication

For internal microservice communication, WeKnora implements an **API-key gate** in [`internal/middleware/api_key_gate.go`](https://github.com/Tencent/WeKnora/blob/main/internal/middleware/api_key_gate.go). Services must provide a valid `X-API-Key` header, which the middleware maps to a specific tenant and role. As shown in the test suite (lines 274-278), JWT tokens can pass through this gate when properly configured, enabling flexible authentication chains for service-to-service calls.

### OpenID Connect (OIDC) ID Token Verification

External identity providers integrate through **OIDC ID token verification** handled in [`internal/application/service/user_oidc_verify.go`](https://github.com/Tencent/WeKnora/blob/main/internal/application/service/user_oidc_verify.go). This flow validates RSA signatures against the external IdP's public keys, enforcing:
- Audience claim equals `weknora-client`
- Issuer matches the configured IdP
- Token expiration checks

### Sandbox Terminal Tickets

Privileged sandbox operations use a specialized mechanism defined in [`internal/application/service/sandbox_terminal_ticket.go`](https://github.com/Tencent/WeKnora/blob/main/internal/application/service/sandbox_terminal_ticket.go). These **sandbox terminal tickets** intentionally bypass standard JWT validation (as noted in [`auth.go`](https://github.com/Tencent/WeKnora/blob/main/auth.go) lines 32-33) to enable high-privilege terminal sessions. This isolation ensures that sandbox authentication remains distinct from standard user flows.

## Authorization Architecture

Once authenticated, WeKnora applies tenant-aware authorization through a structured principal model.

### The Principal Model

Authorization decisions rely on the `Principal` struct defined in [`internal/types/principal.go`](https://github.com/Tencent/WeKnora/blob/main/internal/types/principal.go). This structure attaches three critical fields to every request context:

- **UserID**: The authenticated user's identifier
- **TenantID**: The resolved target tenant
- **Role**: The user's assigned role within that tenant

### Role Hierarchy and Tenant Scoping

WeKnora implements a hierarchical **role-based access control (RBAC)** system with four distinct levels:

- **Owner**: Full administrative control including tenant deletion
- **Admin**: User management and resource configuration
- **Member**: Standard resource creation and modification
- **Guest**: Read-only access to specific resources

The middleware determines the effective tenant through `resolveTargetTenant` (line 207 in [`auth.go`](https://github.com/Tencent/WeKnora/blob/main/auth.go)), which evaluates the JWT tenant claim, `X-Tenant-ID` headers, and the `crossTenantSwitch` flag. Successful resolution logs the principal's role and tenant (lines 256-257) for audit purposes.

### WebSocket Authentication

Real-time connections receive specialized handling in [`internal/middleware/ws_auth.go`](https://github.com/Tencent/WeKnora/blob/main/internal/middleware/ws_auth.go) (lines 36-46). When a WebSocket upgrade request lacks the `X-Tenant-ID` header, the middleware extracts the tenant from the JWT claims and injects it into the request context. This ensures consistent tenant scoping for persistent connections.

## Implementing Access Control in Handlers

Downstream handlers receive a fully populated `*types.User` object (or `Principal`) through the Gin context. The [`internal/handler/auth.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/auth.go) file demonstrates this pattern in its `ValidateToken` endpoint (lines 974-1010), which simply returns the authenticated user object after middleware processing.

To enforce role-based restrictions, handlers can implement middleware like the following:

```go
// Example: Validating a JWT in a handler
func (h *AuthHandler) ValidateToken(c *gin.Context) {
    token := c.GetHeader("Authorization") // "Bearer <jwt>"
    ctx := c.Request.Context()
    user, _, err := h.userService.ValidateToken(ctx, token)
    if err != nil {
        c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
        return
    }
    c.JSON(http.StatusOK, user) // Contains ID, TenantID, Role, etc.
}

```

```go
// Example: Role-based access control middleware
func RequireAdmin() gin.HandlerFunc {
    return func(c *gin.Context) {
        p, exists := c.Get("principal")
        if !exists {
            c.AbortWithStatusJSON(http.StatusUnauthorized, 
                gin.H{"error": "authentication required"})
            return
        }
        principal := p.(types.Principal)
        if principal.Role != types.RoleAdmin && principal.Role != types.RoleOwner {
            c.AbortWithStatusJSON(http.StatusForbidden,
                gin.H{"error": "admin privilege required"})
            return
        }
        c.Next()
    }
}

```

## Summary

- **Multi-layered authentication**: WeKnora supports JWT tokens, API keys, OIDC verification, and sandbox tickets to accommodate diverse client types.
- **Strict token validation**: JWTs must include the `weknora` audience, valid `user_id`, and signature verification against `JWT_SECRET` according to [`internal/application/service/user.go`](https://github.com/Tencent/WeKnora/blob/main/internal/application/service/user.go).
- **Tenant isolation**: The `Principal` struct in [`internal/types/principal.go`](https://github.com/Tencent/WeKnora/blob/main/internal/types/principal.go) binds every request to a specific user, tenant, and role combination.
- **Hierarchical permissions**: Roles follow a strict hierarchy (owner > admin > member > guest) enforced after tenant resolution via `resolveTargetTenant`.
- **WebSocket support**: The [`ws_auth.go`](https://github.com/Tencent/WeKnora/blob/main/ws_auth.go) middleware ensures WebSocket connections carry proper tenant context through header propagation.

## Frequently Asked Questions

### How does WeKnora validate incoming JWT tokens?

WeKnora validates JWTs in [`internal/middleware/auth.go`](https://github.com/Tencent/WeKnora/blob/main/internal/middleware/auth.go) by extracting the `Authorization` header and calling `userService.ValidateToken` from [`internal/application/service/user.go`](https://github.com/Tencent/WeKnora/blob/main/internal/application/service/user.go). The validation checks the HS256 signature against `JWT_SECRET`, verifies the audience claim equals `weknora`, and extracts the `user_id` and optional `tenant_id` claims before attaching the user to the request context.

### What roles are available in WeKnora's authorization system?

The platform defines four hierarchical roles in its RBAC system: **Owner** (full control), **Admin** (user and resource management), **Member** (standard operations), and **Guest** (read-only access). These are stored in the `Principal` struct alongside `UserID` and `TenantID` to enforce scoped permissions.

### Can a user access resources across multiple tenants in a single request?

Yes, but only when explicitly permitted. The `resolveTargetTenant` function in [`internal/middleware/auth.go`](https://github.com/Tencent/WeKnora/blob/main/internal/middleware/auth.go) checks for the `crossTenantSwitch` flag, which allows authenticated users to specify a different target tenant via the `X-Tenant-ID` header or JWT claims, provided their role permits such cross-tenant operations.

### How does WeKnora handle authentication for WebSocket connections?

WebSocket authentication uses [`internal/middleware/ws_auth.go`](https://github.com/Tencent/WeKnora/blob/main/internal/middleware/ws_auth.go) to validate JWTs during the upgrade handshake. If the `X-Tenant-ID` header is missing, the middleware copies the tenant identifier from the JWT claims into the request context (lines 36-46), ensuring that real-time connections maintain proper tenant scoping throughout the session.