# How CasaOS Implements Multi-User Authentication and Authorization

> Discover how CasaOS secures multi-user access with JWT authentication. Learn how Echo middleware validates tokens and uses user IDs for authorization, ensuring seamless and secure multi-user control.

- Repository: [IceWhale/CasaOS](https://github.com/IceWhaleTech/CasaOS)
- Tags: internals
- Published: 2026-06-27

---

**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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/internal/conf/config.go) and returned to the client for subsequent requests.

### Token Validation Middleware

All protected API routes in [`route/v2.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/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.

```go
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`](https://github.com/IceWhaleTech/CasaOS/blob/main/route/v2.go), the `InitFile` and `InitDir` handlers validate the token before serving content, ensuring only the token owner can access their files.
- **Share Management**: The [`service/shares.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/shares.go) file verifies that the `user_id` from the request matches the share owner before allowing modifications or deletion.
- **System Services**: Similar checks appear in [`service/notify.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/notify.go) and [`service/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/storage.go) to prevent cross-user data access.

```go
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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/route/v2.go) handles validation**, extracting user IDs from tokens and injecting them as `user_id` headers for downstream processing.
- **Authorization occurs at the service layer**, where functions in [`service/shares.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/shares.go) and other files verify resource ownership against the injected user ID.
- **Security is configurable** through [`internal/conf/config.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/internal/conf/config.go), allowing administrators to set custom `JwtSecret` values and token expiration times.
- **OAuth integration** via GitHub is supported through settings in [`internal/conf/const.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/shares.go) verifies the user ID matches the share owner before allowing modifications, returning `echo.ErrForbidden` for unauthorized attempts.