Skip to content

prasenjit-net/openid-golang

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

212 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

OpenID Connect Identity Server

CI Release Go Version License

A lightweight, production-ready OpenID Connect (OIDC) identity provider written in Go with an embedded React admin UI.
No external key-management tooling needed β€” RSA key pairs and X.509 certificates are generated in pure Go.


✨ Features

OpenID Connect / OAuth 2.0

Feature Status
Authorization Code Flow βœ…
Implicit Flow (id_token, token id_token) βœ…
PKCE (S256 + plain) βœ…
Refresh Token Grant βœ…
Token Revocation (/revoke) βœ…
Token Introspection (/introspect) βœ…
Dynamic Client Registration (RFC 7591/7592) βœ…
OpenID Connect Discovery (/.well-known/openid-configuration) βœ…
JWKS Endpoint (/.well-known/jwks.json) with x5c / x5t#S256 βœ…
Scopes: openid, profile, email, address, phone, offline_access βœ…
Nonce replay protection βœ…
auth_time claim βœ…

Signing Keys

Feature Status
RSA 2048-bit key generation (pure Go) βœ…
Self-signed X.509 certificate per key βœ…
KID derived from cert SHA-256 fingerprint (x5t#S256, RFC 7517) βœ…
Configurable certificate validity (default 90 days) βœ…
Key rotation β€” old keys kept until cert expires βœ…
Generate PKCS#10 CSR for CA submission βœ…
Import CA-signed certificate (replaces self-signed) βœ…
JWKS serves all valid keys with x5c + x5t#S256 βœ…

Storage

Backend Use case
JSON file Development, small deployments
MongoDB Production, high-traffic

Admin UI

  • Modern "Secure Slate" design with light / dark theme
  • Dashboard with live statistics
  • User management (CRUD, password reset)
  • OAuth client management + secret rotation
  • Token management β€” search, filter, revoke
  • Signing key management β€” rotate, generate CSR, import cert
  • Audit log viewer
  • Server settings
  • First-run setup wizard

πŸš€ Quick Start

Docker (recommended)

# JSON-file storage (no external dependencies)
docker-compose --profile json-storage up -d

# MongoDB storage
MONGO_USER=admin MONGO_PASSWORD=secret docker-compose --profile with-mongodb up -d

The server starts at http://localhost:8080.
On first launch, the setup wizard runs automatically at http://localhost:8080/setup.

Binary

# Download from GitHub Releases and make executable
chmod +x openid-server-*

# Interactive first-run wizard (creates config + admin user)
./openid-server-* --setup

# Start
./openid-server-*

Development

# Install Go + Node dependencies, build frontend, run server
make deps
make run

πŸ“ Project Structure

openid-golang/
β”œβ”€β”€ cmd/
β”‚   β”œβ”€β”€ root.go          # CLI entry point (cobra)
β”‚   └── serve.go         # Server startup, route registration
β”œβ”€β”€ pkg/
β”‚   β”œβ”€β”€ configstore/     # Configuration loading (TOML / env / MongoDB)
β”‚   β”œβ”€β”€ crypto/          # RSA keygen, cert gen, CSR, JWT, PKCE, bcrypt
β”‚   β”œβ”€β”€ handlers/
β”‚   β”‚   β”œβ”€β”€ admin.go     # Admin REST API (users, clients, keys, tokens, audit)
β”‚   β”‚   β”œβ”€β”€ authorize.go # /authorize endpoint
β”‚   β”‚   β”œβ”€β”€ bootstrap.go # Setup wizard handler
β”‚   β”‚   β”œβ”€β”€ discovery.go # /.well-known/* + JWKS
β”‚   β”‚   β”œβ”€β”€ handlers.go  # Shared handler wiring
β”‚   β”‚   β”œβ”€β”€ token.go     # /token, /revoke, /introspect
β”‚   β”‚   └── userinfo.go  # /userinfo
β”‚   β”œβ”€β”€ middleware/      # JWT auth middleware for OIDC endpoints
β”‚   β”œβ”€β”€ models/          # Data models (User, Client, Token, SigningKey, AuditLog…)
β”‚   β”œβ”€β”€ session/         # Server-side session store + cookie middleware
β”‚   └── storage/
β”‚       β”œβ”€β”€ storage.go   # Storage interface
β”‚       β”œβ”€β”€ json.go      # JSON file implementation
β”‚       └── mongodb.go   # MongoDB implementation
β”œβ”€β”€ frontend/            # React + TypeScript + Ant Design admin UI
β”‚   └── src/
β”‚       β”œβ”€β”€ pages/       # Dashboard, Users, Clients, Tokens, KeyManagement, AuditLog…
β”‚       └── hooks/       # useApi.ts β€” all React Query hooks
β”œβ”€β”€ public/              # Embedded HTML templates (login, consent, setup wizard)
β”œβ”€β”€ embed.go             # go:embed declarations
β”œβ”€β”€ main.go
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ docker-compose.yml
└── Makefile

πŸ”§ Configuration

The server reads configuration from (in priority order):

  1. Environment variables
  2. data/config.json (written by setup wizard)
  3. Built-in defaults

Key environment variables

Variable Default Description
SERVER_HOST 0.0.0.0 Listen address
SERVER_PORT 8080 Listen port
MONGODB_URI β€” MongoDB connection string (enables MongoDB storage)
MONGODB_DATABASE openid MongoDB database name

When MONGODB_URI is set, all data (config + storage) is persisted to MongoDB.
Without it, the JSON file backend (data/openid.json) is used.

First-run Setup Wizard

Visit http://localhost:8080/setup (or pass --setup to the binary) to:

  • Set the issuer URL
  • Choose storage backend
  • Create the first admin user
  • Optionally pre-create an OAuth client

πŸ” OpenID Connect Endpoints

Endpoint Method Description
/.well-known/openid-configuration GET OIDC Discovery document
/.well-known/jwks.json GET JSON Web Key Set (all valid keys)
/authorize GET Authorization endpoint
/token POST Token endpoint
/userinfo GET / POST UserInfo endpoint
/revoke POST Token revocation (RFC 7009)
/introspect POST Token introspection (RFC 7662)
/login GET / POST Login page (rendered server-side)
/consent GET / POST Consent page (rendered server-side)

Dynamic Client Registration

Enabled by default at /register:

Endpoint Method Description
/register POST Register a new client (RFC 7591)
/register/:client_id GET Read registration (RFC 7592)
/register/:client_id PUT Update registration (RFC 7592)
/register/:client_id DELETE Delete registration

πŸ› οΈ Admin API

All admin API routes are under /api/ and require a Bearer token obtained via POST /api/auth/login.

The admin portal uses session-based authentication (no token issued) to keep admin sessions out of the OIDC token store.

Auth

Method Path Description
POST /api/auth/login Admin login
POST /api/auth/logout Admin logout

Users

Method Path Description
GET /api/users List users
POST /api/users Create user
GET /api/users/:id Get user
PUT /api/users/:id Update user
DELETE /api/users/:id Delete user

OAuth Clients

Method Path Description
GET /api/clients List clients
POST /api/clients Create client
GET /api/clients/:id Get client
PUT /api/clients/:id Update client
DELETE /api/clients/:id Delete client
POST /api/clients/:id/regenerate-secret Rotate client secret

Signing Keys

Method Path Description
GET /api/keys List all signing keys with cert details
POST /api/settings/rotate-keys Rotate active key (body: {"validity_days":90})
GET /api/keys/:id/csr Generate PKCS#10 CSR for the key
POST /api/keys/:id/import-cert Import CA-signed cert (body: {"cert_pem":"..."})

Tokens

Method Path Description
GET /api/tokens List tokens (filter by subject, client, type, active)
DELETE /api/tokens/:id Revoke token

Audit Log

Method Path Description
GET /api/audit Query audit log (filter by action, actor, date range)

Settings

Method Path Description
GET /api/settings Get server settings
PUT /api/settings Update server settings

πŸ”‘ Signing Key Lifecycle

Generate key pair + self-signed cert
           β”‚
           β–Ό
    KID = x5t#S256(cert)        ← RFC 7517 Β§4.9
    ExpiresAt = cert.NotAfter
    JWKS includes x5c + x5t#S256
           β”‚
           β”œβ”€β”€ (optional) Generate CSR ──► Submit to CA
           β”‚                                    β”‚
           β”‚                         Receive signed cert
           β”‚                                    β”‚
           └────────────── Import Cert ◄─────────
                                β”‚
                    KID re-derived from new cert
                    ExpiresAt updated from new cert
                    JWKS updated automatically
           β”‚
           β–Ό
    Rotate Key
    Old key stays in JWKS until its cert expires
    New key becomes active

πŸ“‹ Development Commands

make build-all     # Build frontend then Go binary
make build         # Build Go binary only (requires frontend/dist)
make build-frontend # Build React admin UI
make run           # Build frontend + run server
make test          # Run all Go tests
make lint          # Run golangci-lint
make fmt           # Run gofmt
make deps          # Download Go + npm dependencies
make clean         # Remove build artifacts
make install-tools # Install golangci-lint v2.5.0

πŸ§ͺ Test Client

An interactive test client for exploring OIDC flows is included:

go run examples/test-client.go
# Visit http://localhost:9090

The test client walks through:

  • Dynamic client registration
  • Authorization Code Flow with PKCE
  • Implicit Flow
  • Token refresh
  • UserInfo fetch
  • Token introspection

πŸ“Š Audit Events

All security-relevant operations produce structured audit log entries:

Category Actions
User user.login, user.login_failed, user.consent_granted, user.consent_denied
Token token.issued, token.revoked
Client client.registered
Admin admin.login, admin.user.*, admin.client.*, admin.settings.updated, admin.keys.rotated

Each entry records: timestamp, action, actor (type + ID), resource, status, IP address, user agent, and optional metadata.


🐳 Docker

# Build image locally
docker build -t openid-server .

# JSON-file storage (development)
docker-compose --profile json-storage up -d

# MongoDB-backed (production-like)
MONGO_USER=admin MONGO_PASSWORD=secret \
  docker-compose --profile with-mongodb up -d

# Logs
docker logs openid-server -f

Data is persisted to the ./data volume mount.


πŸ—οΈ Storage Backends

JSON File (default)

  • Zero dependencies β€” single file on disk (data/openid.json)
  • Suitable for development and small single-instance deployments
  • Not suitable for multi-instance or high-write workloads

MongoDB

Set MONGODB_URI to switch. Supports:

  • Multi-instance deployments
  • High-throughput workloads
  • TTL indexes for automatic token expiry

πŸ”’ Security Notes

  • Passwords hashed with bcrypt (cost 10)
  • PKCE enforced for public clients
  • Nonce stored and checked to prevent replay attacks
  • auth_time propagated through session for max_age enforcement
  • Admin session uses server-side session store (not OIDC tokens)
  • Signing keys backed by X.509 certificates; KIDs are RFC 7517-compliant thumbprints
  • Old signing keys retained in JWKS until certificate expiry to avoid token validation gaps

For production hardening, additionally consider: TLS termination, rate limiting, MongoDB authentication, and HSM/KMS for key storage.


πŸ“„ License

MIT β€” free for personal and commercial use.

🀝 Contributing

Pull requests and issues are welcome. See docs/CONTRIBUTING.md for guidelines.