Deta Space Authentication: Choosing Between Space Auth and Custom OIDC
A decision guide for Deta Space apps: compare built-in Space Auth against custom OIDC/JWT stacks, understand sandbox constraints, and validate both paths with the Space CLI.
16 Aug 2025, 21:59 UTC

You are building an app on Deta Space and must decide how users will authenticate. This choice is structural, not cosmetic. Space Auth provides a managed OIDC identity tied to the Space OS, but it functions only inside the Space environment. A custom stack built on an external identity provider offers portability and richer features, yet you own the middleware, secrets, and user store. The correct answer depends on whether your users already hold Space accounts and whether you might run the same codebase outside Space.
Constraints That Shape the Decision
Deta Space apps run in isolated sandboxes with ephemeral filesystems. There is no persistent local disk for session files, so any custom session store must use Deta Base, Deta Drive, or an external database. Space Auth is injected only when the app executes inside Space; it is not a general-purpose OIDC server you can query from arbitrary services. If you choose custom auth, you must manage JWKS caching, token validation, CORS for callbacks, and secure cookie handling within that same sandbox. The behavior described here assumes Space OS v0.12+ and CLI versions available in 2024–2025; because Deta Space tooling is evolving, verify current Spacefile schema and CLI flags before deploying to production.
Supported Options at a Glance
| Factor | Space Auth | Custom Auth |
|---|---|---|
| Setup | Zero-config via Spacefile | Manual IdP + JWKS middleware |
| Identity | Space username | Email/social/enterprise |
| Tokens | OIDC ID token from Space | IdP JWT (RS256/ES256) |
| Sessions | Space OS SSO | App-managed cookies/refresh |
| Multi-tenancy | 1 Space user = 1 tenant | Explicit org modeling |
| Revocation | Space-level logout | App/IdP blocklist or short TTL |
| Local dev | space dev tunnel | Offline mock IdP |
| Cost | Free | IdP pricing or self-host |
Trade-offs: Ecosystem Lock-in vs Operational Control
Space Auth eliminates nearly all authentication code. You set auth: true in the Spacefile, and Space injects an Authorization: Bearer token into incoming requests. The token carries a space:username claim. There is no built-in role or permission system, so authorization logic lives entirely in your application. The cost is coupling: every user must have a Space account, and moving the app off Space later means replacing the auth layer.
Custom auth decouples your app from the Space ecosystem. You can accept email/password, social login, or enterprise SAML/OIDC through an external IdP. Tokens typically carry sub and email claims, which map cleanly to multi-tenant organization models. The operational burden is real: you must rotate secrets, cache JWKS keys, validate aud, iss, and exp, and register redirect URIs against the app's public URL, which changes per user install (https://<app>-<username>.deta.space).
Concrete Validation: Two Branches
Branch A: Space Auth
Create a Spacefile with auth: true and push the app. After deployment, inspect the injected token using the Space CLI. Run space auth token --decode in your terminal; this requires an authenticated Space CLI session. Confirm the decoded payload includes a space:username claim. Then call a protected route with the token:
curl -H "Authorization: Bearer $(space auth token)" \
https://<app>-<username>.deta.space/api/protected
Expect HTTP 200. If the route returns 401, verify that auth: true is present in the Spacefile and that the app was redeployed after the change. Because CLI syntax evolves, check the exact flag behavior against your installed Space CLI version.
Branch B: Custom JWT Validation
Store your identity provider's JWKS URI and issuer in Space secrets. Run these commands from your project directory with the Space CLI:
space secrets set JWKS_URI=https://your-idp.example.com/.well-known/jwks.json
space secrets set ISSUER=https://your-idp.example.com/
Space injects these as environment variables at runtime. Add middleware that fetches the JWKS on first request, caches it in memory, and validates RS256 signatures along with aud, iss, and exp. Map the sub claim to a user record in Deta Base. During local development, space dev creates a tunnel, but you still need a reachable IdP or a local mock. An illustrative middleware pattern looks like this:
// Illustrative only; adapt to your framework
async function verifyToken(req, res, next) {
const header = req.headers.authorization;
if (!header?.startsWith('Bearer ')) return res.sendStatus(401);
const token = header.slice(7);
// 1. Fetch JWKS from process.env.JWKS_URI and cache
// 2. Verify RS256 signature, aud, iss, exp
// 3. Look up or create user by sub claim in Deta Base
next();
}
After deploying, call the same protected route with a token from your IdP and expect HTTP 200. Check your application logs to confirm the JWKS is fetched only on the first request and cached thereafter. Because Space has no persistent local storage, keep the cache in memory and accept that it resets on cold starts.
Hybrid Middleware Pattern
If you need to support both Space-native installs and external deployments, use a hybrid middleware. Attempt Space Auth first by looking for a space:username claim. If the token is absent or the claim is missing, fall back to custom JWT validation using the same JWKS middleware. This keeps one codebase but requires careful testing of both paths.
Limitations and Practical Verification
- Space Auth tokens are only valid within the Space environment; external services cannot verify them without Space's introspection endpoint or public JWKS.
- No persistent local storage means custom session stores must live in Deta Base, Drive, or an external database.
- The Space CLI and APIs are evolving;
Spacefileschema and auth injection behavior may change in minor releases. Verify current documentation before relying on specific flags. - Custom auth redirect URIs must be registered with the IdP using the per-install public URL, which complicates multi-tenant onboarding.
- Space Auth and Deta Base have per-app rate limits; high-traffic auth flows may hit throttling.
- Space Auth has no built-in roles or permissions; all authorization logic is application code.
To validate your implementation, run space auth token --decode after space push to inspect actual claims. Deploy with auth: true and curl a protected route to confirm header injection. For custom auth, set secrets, deploy, and verify JWKS caching by checking logs for a single fetch on cold start. Test revocation by revoking app access in the Space UI; subsequent requests with the old token should return 401. Validate multi-tenancy by installing the app under two Space accounts and confirming space:username differs and Deta Base data is isolated. Finally, measure cold-start overhead with time curl -w "%{time_total}" ... for both paths to understand latency impact.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.