Authentication and Authorization Mechanisms in WeKnora: A Complete Technical Guide
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 (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 (lines 1216-1221).
The validation logic enforces strict claim requirements:
- The
audclaim must equalweknora - The token must contain a valid
user_idclaim - The signature is verified against the server-side
JWT_SECRET - An optional
tenant_idclaim 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. 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. 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. These sandbox terminal tickets intentionally bypass standard JWT validation (as noted in 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. 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), 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 (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 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:
// 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.
}
// 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
weknoraaudience, validuser_id, and signature verification againstJWT_SECRETaccording tointernal/application/service/user.go. - Tenant isolation: The
Principalstruct ininternal/types/principal.gobinds 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.gomiddleware 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 by extracting the Authorization header and calling userService.ValidateToken from 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 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 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →