The Go gopher was designed by Renée French, licensed under CC BY 4.0.
Go-based API server that delegates authentication and authorization entirely to external IdPs.
cmn-core provides a multi-tier REST API backed by PostgreSQL and Redis. All user management, authentication, and authorization are fully delegated to external IdPs — Keycloak (port 8080) and Casdoor (port 9000). The application itself performs no internal user CRUD.
CLI clients authenticate by posting credentials to the server (POST /v1/public/login); the server then obtains a JWT from the configured IdP and returns it to the client. Clients never contact the IdP directly.
- Go 1.25+
- Docker & Docker Compose
cp etc/app.yaml.example etc/app.yaml
make dev-upServices started by make dev-up:
| Service | URL | Credentials |
|---|---|---|
| PostgreSQL | localhost:5432 | user/password |
| Redis | localhost:6379 | — |
| Keycloak (admin) | http://localhost:8080/admin | admin / admin |
| Keycloak (cmn realm users) | http://localhost:8080/realms/cmn/account | user01-50 / Password123! |
| Casdoor (admin) | http://localhost:9000 | admin / 123 |
| Casdoor (cmn org users) | http://localhost:9000/login/cmn | user01-50 / Password123! |
| Casdoor (cmn admin user) | http://localhost:9000/login/cmn | admin@cmn.local / Admin123! |
| pgAdmin | http://localhost:3001 | admin@cmn.local / admin |
| Roundcube | http://localhost:3005 | — |
make build
./.bin/cmn-serverServer starts on http://localhost:8000.
Authentication is handled by external IdPs via OIDC / SAML 2.0. The server validates tokens issued by Keycloak or Casdoor.
Client → [Keycloak / Casdoor] → JWT Token → cmn-core Server → PostgreSQL / Redis
| Tier | Path prefix | Auth |
|---|---|---|
| Public | /v1/public/ |
None (login endpoint) |
| Share | /v1/share/ |
JWT required |
| Internal | /v1/internal/ |
JWT required |
| Private | /v1/private/ |
JWT + admin role required |
OIDC callback: GET /v1/share/auth/oidc/callback
cmd/ # Entrypoints (server, client/admin, client/app, client/anonymous)
pkg/
auth/ # OIDC / SAML provider interface and implementations
config/ # Configuration loading (YAML + AWS Secrets Manager)
entity/ # Models, request/response structs
server/ # Gin router, controllers, repositories
client/ # CLI client implementations
etc/
app.yaml.example # Configuration template
keycloak/ # Keycloak realm import (cmn-realm.json)
casdoor/ # Casdoor config (app.conf) and seed data (init_data.json)
scripts/
data/postgres/ # PostgreSQL init SQL
test/
unit/ # Unit tests
e2e/ # End-to-end tests
cp etc/app.yaml.example etc/app.yamlKey settings in etc/app.yaml:
Application:
Server:
port: 8000
admin:
emails:
- "admin@cmn.local"
jwt_secret: "CHANGE_THIS_JWT_SECRET_IN_PRODUCTION"
log_level: "info"
redis:
jwt_cache: true
cache_ttl: 1800
idp:
provider: "casdoor" # or "keycloak"
casdoor:
base_url: "http://localhost:9000"
client_id: "cmn-core-client-id"
client_secret: "cmn-core-client-secret"
organization: "cmn"
auth:
oidc:
issuer_url: "http://localhost:9000" # JWT iss claim value
provider_url: "http://localhost:9000" # OIDC discovery URL (set to internal URL in Docker)
client_id: "cmn-core-client-id"
PostgreSQL:
host: "localhost"
user: "user"
pass: "password"
port: "5432"
db: "cmn_core"
sslmode: "disable"
Redis:
host: "localhost"
port: 6379
user: "default"
pass: ""
db: 0# Run unit tests
make test
# Run with coverage
go test -v -cover ./...
# E2E tests (requires dev environment running)
go test -v -timeout 15m ./test/e2e/testcase/echo "DOCKER_PLATFORM=linux/arm64" > .env.localEphemeral Postfix/Dovecot + Roundcube environment for email testing:
./scripts/main.sh env recreate
open http://localhost:3005 # Roundcube — user: test1@cmn.local / pass: TestPassword123!Full documentation: https://ryo-arima.github.io/cmn-core/
# Build docs locally
make docs
# Serve docs locally
make docs-serveMIT — see LICENSE.