Zitadel is an open-source identity platform with multi-tenancy built in. Perfect for SaaS — each customer gets their own organization with separate users, roles, and branding.
Why Zitadel?
- Multi-tenant by default: Each org has isolated users
- OIDC/OAuth2/SAML: Industry standards
- Passwordless: WebAuthn, passkeys
- Actions: Custom logic on auth events (like Auth0 Actions)
- Self-hosted or cloud: Both options
- gRPC + REST: Both API styles
- Free tier: 25K MAUs on cloud
Self-Host
docker run -p 8080:8080 \
ghcr.io/zitadel/zitadel:latest start-from-init \
--masterkey "MasterkeyNeedsToHave32Characters" \
--tlsMode disabled
Console at http://localhost:8080
API: Create Organization
curl -X POST http://localhost:8080/management/v1/orgs \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"name": "Acme Corp"}'
API: Create User
curl -X POST http://localhost:8080/management/v1/users/human/_import \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"userName": "alice@acme.com",
"profile": {"firstName": "Alice", "lastName": "Smith"},
"email": {"email": "alice@acme.com", "isEmailVerified": true},
"password": "SecureP@ssw0rd!"
}'
API: Create Project + App
# Create project
curl -X POST http://localhost:8080/management/v1/projects \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-d '{"name": "My SaaS"}'
# Create OIDC app
curl -X POST http://localhost:8080/management/v1/projects/PROJECT_ID/apps/oidc \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-d '{
"name": "Web App",
"redirectUris": ["http://localhost:3000/callback"],
"responseTypes": ["OIDC_RESPONSE_TYPE_CODE"],
"grantTypes": ["OIDC_GRANT_TYPE_AUTHORIZATION_CODE"],
"appType": "OIDC_APP_TYPE_WEB"
}'
React Integration
import { ZitadelAuth } from '@zitadel/react';
const config = {
authority: 'http://localhost:8080',
client_id: 'YOUR_CLIENT_ID',
redirect_uri: 'http://localhost:3000/callback',
scope: 'openid profile email',
};
function App() {
return (
<ZitadelAuth config={config}>
<ProtectedContent />
</ZitadelAuth>
);
}
Actions (Custom Logic)
// Run on pre-creation
function preCreation(ctx, api) {
// Auto-assign role based on email domain
if (ctx.user.email.endsWith('@acme.com')) {
api.setMetadata('role', 'employee');
}
}
Real-World Use Case
A B2B SaaS needed separate user pools per customer, with each customer managing their own users. Zitadel's multi-tenancy meant zero custom code — each customer is an organization with its own users, roles, and even login branding. What would take 2 months to build took 2 days.
Need to automate data collection? Check out my Apify actors for ready-made scrapers, or email spinov001@gmail.com for custom solutions.
Top comments (0)