Keycloak is an open-source identity provider — SSO, OAuth2, OIDC, SAML, social login, and user management. Replace Auth0 and Okta with a self-hosted solution.
Why Keycloak?
- SSO: Single sign-on across all your apps
- Social login: Google, GitHub, Facebook, Apple
- OIDC/OAuth2/SAML: Industry standards
- User management: Admin console for users and roles
- MFA: TOTP, WebAuthn, SMS
- Self-hosted: Full control over identity data
- Free: No per-user pricing
Docker Setup
docker run -p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak start-dev
Admin console at http://localhost:8080
API: Get Access Token
curl -X POST http://localhost:8080/realms/master/protocol/openid-connect/token \
-d 'grant_type=password' \
-d 'client_id=admin-cli' \
-d 'username=admin' \
-d 'password=admin'
API: Create User
curl -X POST http://localhost:8080/admin/realms/myrealm/users \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"username": "alice",
"email": "alice@example.com",
"enabled": true,
"credentials": [{
"type": "password",
"value": "secure-password",
"temporary": false
}]
}'
API: List Users
curl http://localhost:8080/admin/realms/myrealm/users \
-H 'Authorization: Bearer ACCESS_TOKEN'
API: Create Client (Application)
curl -X POST http://localhost:8080/admin/realms/myrealm/clients \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"clientId": "my-web-app",
"rootUrl": "http://localhost:3000",
"redirectUris": ["http://localhost:3000/*"],
"webOrigins": ["http://localhost:3000"],
"publicClient": true
}'
Integrate with React
import Keycloak from 'keycloak-js';
const keycloak = new Keycloak({
url: 'http://localhost:8080',
realm: 'myrealm',
clientId: 'my-web-app',
});
await keycloak.init({ onLoad: 'login-required' });
console.log('User:', keycloak.tokenParsed.preferred_username);
console.log('Email:', keycloak.tokenParsed.email);
console.log('Roles:', keycloak.tokenParsed.realm_access.roles);
// Use token for API calls
fetch('/api/data', {
headers: { Authorization: `Bearer ${keycloak.token}` },
});
Integrate with Express
import express from 'express';
import jwt from 'jsonwebtoken';
import jwksClient from 'jwks-rsa';
const client = jwksClient({
jwksUri: 'http://localhost:8080/realms/myrealm/protocol/openid-connect/certs',
});
function authenticate(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'No token' });
jwt.verify(token, getKey, { algorithms: ['RS256'] }, (err, decoded) => {
if (err) return res.status(401).json({ error: 'Invalid token' });
req.user = decoded;
next();
});
}
app.get('/api/protected', authenticate, (req, res) => {
res.json({ user: req.user.preferred_username });
});
Real-World Use Case
A company with 5 internal apps used separate auth for each — 5 login pages, 5 user databases. After deploying Keycloak, employees log in once and access all apps. Replacing Auth0 ($500/mo for 1000 MAUs) with self-hosted Keycloak saved $6,000/year.
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)