Moonlight security model
Who this is for
You are securing DeskFlow and want to understand where auth runs — at the switch, in middleware, or inside an action.
What you will learn
- Why Moonlight action payloads use POST JSON bodies
- How switch-level authentication protects groups of actions
- The difference between HTTP 401 and envelope
returnCode
Before you start
- Moonlight overview — POST dispatch model
- DeskFlow tutorial Step 1 — DeskFlow on port 8000
How it works
Credentials and business fields travel in the POST JSON body. Authentication runs at the switch before your action method executes — like checking Alex’s badge at the Northwind office door, not at every desk.
POST bodies and access logs
Moonlight sends credentials and business fields in the request body, not query strings:
{
"service": "member",
"action": "login",
"email": "alex@northwind.studio",
"password": "your-secret"
}Query strings often appear in proxy and CDN access logs. POST bodies typically do not — still use HTTPS in production and never log raw passwords in application code.
Health checks like GET /api/v1/ping remain ordinary GET requests.
Switch-level authentication
Pionia v3 evaluates authentication before dispatching to your action — at the switch layer. DeskFlow can require JWT for all task.create calls while leaving task.list public, configured on MainSwitch.
See Authentication & authorization for JWT setup with member.login.
Action-level rules
Inside an action you still enforce authorization — e.g. only project leads may delete tasks. Authentication proves who Alex is; authorization decides what Alex may do.
Real HTTP status codes
| Situation | HTTP status | Envelope |
|---|---|---|
| Success | 200 | returnCode: 0 |
| Validation error | 422 | returnCode non-zero |
| Not authenticated | 401 | error message in envelope |
| Forbidden | 403 | error message in envelope |
Do not assume HTTP 200 for every error — clients must read both status and JSON.
Common mistakes
- Putting passwords in query strings — use POST JSON for
member.login; never?password=in URLs. - Checking auth only inside actions — configure switch-level rules so unauthenticated requests fail before business logic runs.
- Logging raw request bodies in production — redact passwords; use
[logging] HIDE_IN_LOGSinsettings.ini. - Ignoring HTTP status because
returnCodeexists — mobile clients must handle 401, 403, and 422 explicitly.
What’s next
Authentication
Implement member.login with JWT.
Security utilities
Password reset tokens for Alex.
Middleware
Request IDs for support tickets.