How CasaOS Implements Multi-User Authentication and Authorization
CasaOS implements multi-user authentication and authorization using JSON Web Tokens (JWT) signed with a configurable secret, where Echo middleware validates tokens on every request and injects a user_id header for downstream ownership checks.
CasaOS is a multi-tenant home-server platform designed to support multiple users through a token-based security model. The authentication system relies on JWTs to maintain stateless sessions across API requests, with authorization enforced at the middleware and service layers. This architecture separates user contexts by embedding user identifiers and role flags directly into signed tokens stored in internal/conf/config.go.
JWT-Based Authentication Flow
Login and Token Issuance
When a user authenticates via the built-in /login endpoint or an enabled OAuth provider such as GitHub, the server generates a JWT containing the user's primary key (ID) and any relevant role flags. The token is signed using the JwtSecret defined in internal/conf/config.go and returned to the client for subsequent requests.
Token Validation Middleware
All protected API routes in route/v2.go are wrapped by Echo's JWT middleware configured with echo_middleware.JWTWithConfig. The middleware validates incoming tokens using the public key retrieved from external.GetPublicKey(config.CommonInfo.RuntimePath), which is shared across CasaOS-Common services.
e.Use(echo_middleware.JWTWithConfig(echo_middleware.JWTConfig{
ParseTokenFunc: func(token string, c echo.Context) (interface{}, error) {
valid, claims, err := jwt.Validate(token,
func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })
if err != nil || !valid {
return nil, echo.ErrUnauthorized
}
c.Request().Header.Set("user_id", strconv.Itoa(claims.ID))
return claims, nil
},
TokenLookupFuncs: []echo_middleware.ValuesExtractor{
func(ctx echo.Context) ([]string, error) {
if hdr := ctx.Request().Header.Get(echo.HeaderAuthorization); len(hdr) > 0 {
return []string{hdr}, nil
}
return []string{ctx.QueryParam("token")}, nil
},
},
}))
Request Authorization and Ownership Checks
User ID Injection and Header Parsing
After successful validation, the middleware extracts claims.ID from the JWT and injects it into the request header as user_id. Downstream handlers retrieve this value to identify the requesting user and enforce access controls.
Resource-Level Authorization
Authorization logic varies by service but consistently checks the user_id against resource ownership:
- File Operations: In
route/v2.go, theInitFileandInitDirhandlers validate the token before serving content, ensuring only the token owner can access their files. - Share Management: The
service/shares.gofile verifies that theuser_idfrom the request matches the share owner before allowing modifications or deletion. - System Services: Similar checks appear in
service/notify.goandservice/storage.goto prevent cross-user data access.
userIDStr := c.Request().Header.Get("user_id")
uid, _ := strconv.Atoi(userIDStr)
// verify ownership
if !service.IsOwner(uid, fileID) {
return echo.ErrForbidden
}
Configuration and Security Settings
JWT Secrets and Expiration
The security parameters are centralized in internal/conf/config.go. The JwtSecret field defines the signing key used for all tokens, while TokenExpiresIn controls the lifetime of authenticated sessions.
OAuth Provider Integration
Optional third-party authentication is controlled via GithubLoginEnabled in internal/conf/const.go. When enabled, the OAuth flow completes through the external provider, after which CasaOS issues a standard JWT for session management, maintaining consistency with local authentication.
Summary
- CasaOS uses stateless JWT authentication to support multi-user home-server environments without server-side session storage.
- Echo middleware in
route/v2.gohandles validation, extracting user IDs from tokens and injecting them asuser_idheaders for downstream processing. - Authorization occurs at the service layer, where functions in
service/shares.goand other files verify resource ownership against the injected user ID. - Security is configurable through
internal/conf/config.go, allowing administrators to set customJwtSecretvalues and token expiration times. - OAuth integration via GitHub is supported through settings in
internal/conf/const.go, issuing standard JWTs post-authentication.
Frequently Asked Questions
How does CasaOS validate JWT tokens on every request?
CasaOS configures Echo's JWT middleware in route/v2.go with a custom ParseTokenFunc that calls jwt.Validate using the public key from external.GetPublicKey. This validates the token signature and claims before allowing the request to proceed to handlers.
Where is the JWT secret configured in CasaOS?
The JWT signing secret is defined as JwtSecret in internal/conf/config.go, alongside TokenExpiresIn which controls how long tokens remain valid. These values are loaded at startup and used throughout the authentication lifecycle.
Can CasaOS integrate with external identity providers?
Yes, CasaOS supports OAuth authentication through providers like GitHub when GithubLoginEnabled is set to true in internal/conf/const.go. After external validation, CasaOS issues its own JWT containing the user ID, maintaining the same authorization flow as local logins.
How does CasaOS prevent users from accessing other users' files?
Authorization handlers extract the user_id from the request header injected by middleware and compare it against resource ownership records. For example, service/shares.go verifies the user ID matches the share owner before allowing modifications, returning echo.ErrForbidden for unauthorized attempts.
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 →