Managing authentication across multiple tenants can be a nightmare—different domains, identity providers, and security models all add complexity. In this guide, you’ll learn how to build a production-ready multi-tenant SSO system using Keycloak, React, and Go, enabling your users to log in with Google, GitHub, or Microsoft accounts, while keeping each tenant securely isolated.
Stack Overview
Layer | Tech | Purpose |
---|---|---|
Identity | Keycloak | Central identity provider (OAuth2, JWT, social login, multi-tenancy) |
Frontend | React | User and admin interfaces |
Backend | Go | Stateless API with JWT validation and business logic |
Data | PostgreSQL | Stores tenants, users, and metadata |
DevOps | Docker Compose | Container orchestration for local setup |
Architecture: A Layered Security Model
The solution follows a cleanly separated, layered architecture:
- Identity Providers Layer: Social login via Google, Microsoft, and GitHub
-
Frontend Layer:
- React user interface (
http://localhost:3000
) - Admin dashboard (
http://localhost:3001
)
- React user interface (
-
Authentication Layer:
- Keycloak (
http://localhost:8080
) handles all identity and access flows
- Keycloak (
-
Backend Layer:
- Go API (
http://localhost:8081
) that verifies JWTs and executes tenant-aware logic
- Go API (
-
Data Layer:
- PostgreSQL database for user, tenant, and relationship data
Why This Stack?
Keycloak
- Open-source IAM platform with OAuth2, OpenID Connect, social login, and multi-tenancy.
- Saves you from writing brittle auth code.
- Highly customizable with realms, clients, and mappers.
React
- Modern, component-driven framework.
- Perfect separation of user frontend and admin interface.
- Great developer experience and large ecosystem.
Go
- Lightweight and performant.
- Excellent standard library for JWT handling and HTTP.
- Strong concurrency model for scalable APIs.
Authentication Flow
Here’s how the secure OAuth2-based login works:
- User starts login from the React frontend.
- Keycloak redirects to the selected identity provider.
- User authenticates, and the OAuth callback returns to Keycloak.
- Keycloak issues a JWT with user and tenant context.
- Frontend includes the JWT in API requests.
- Go backend validates the token and extracts tenant info.
- Tenant-isolated operations run based on JWT claims.
This setup ensures centralized auth with stateless APIs and strong tenant isolation.
Multi-Tenancy: Key Considerations
Concern | Solution |
---|---|
Tenant Isolation | Users and data are scoped to their own organization. |
Flexible Auth | Each tenant chooses which social login providers to enable. |
Self-Service Admin | Admin panel allows tenant admins to manage users without overlap. |
Scalable Infrastructure | Each component is containerized and independently scalable. |
Security Best Practices
- JWT Validation: Go backend checks tokens against Keycloak’s JWKS endpoint.
- CORS Configuration: Proper headers configured in both Keycloak and backend.
-
Environment Variables: All sensitive values are managed via
.env
files. - Isolated Networks: Docker containers communicate over private networks.
Getting Started
Clone and boot the system using Docker Compose:
# Clone and navigate to the repo
git clone https://github.com/zrougamed/multitenant-sso
cd multitenant-sso
# Start all services
docker-compose up -d
Access services at:
- Keycloak: http://localhost:8080
- User frontend: http://localhost:3000
- Admin panel: http://localhost:3001
- Go API: http://localhost:8081
Configuring OAuth Providers
- Go to Google Cloud Console
- Create OAuth credentials
- Set redirect URI:
http://localhost:8080/realms/{realm}/broker/google/endpoint
GitHub
- Go to GitHub Developer Settings
- Set callback URI:
http://localhost:8080/realms/{realm}/broker/github/endpoint
Microsoft
- Register an app via Azure App Registrations
- Set redirect URI:
http://localhost:8080/realms/{realm}/broker/azure/endpoint
Common Challenges and Solutions
Problem | Solution |
---|---|
Port Conflicts | Modify docker-compose.yml or Keycloak config. |
CORS Errors | Ensure correct CORS settings in backend and Keycloak. |
JWT Validation Fails | Double-check audience (aud ), issuer (iss ), and realm configuration. |
Extending the System
- Add more identity providers: Twitter, Facebook, etc.
- Add Role-Based Access Control (RBAC) via Keycloak groups and roles.
- Implement API rate limiting in Go middleware.
- Add monitoring with Prometheus, Grafana, or ELK.
Production Considerations
- High Availability: Cluster Keycloak and PostgreSQL with redundancy.
- SSL/TLS: Use reverse proxy like NGINX or Traefik for HTTPS.
- Backups: Regular backups for Keycloak and PostgreSQL.
- Monitoring: Alerting on auth failures, performance, and token expiry issues.
Conclusion
Building a secure, scalable, multi-tenant SSO system doesn’t have to be painful. By using Keycloak for identity management, React for the frontend, and Go for the API, you get a powerful and maintainable architecture that scales with your needs.
The system supports:
- Multi-tenant user isolation
- Social logins via OAuth
- Stateless APIs with secure JWTs
- Admin management for each tenant
Source Code
👉 GitHub Repository – multitenant-sso
Questions or feedback?
Open an issue on GitHub or connect with me on LinkedIn
Top comments (0)