OIDC Module
OpenID Connect (OIDC) authentication and authorization module for IOTA SDK. The module is included in BuiltInModules and activates automatically when required settings are configured (OIDC_ISSUER_URL and OIDC_CRYPTO_KEY); no separate registration step is needed.
Features
- OpenID Connect Core 1.0 compliant
- OAuth 2.0 authorization framework
- PKCE (Proof Key for Code Exchange) support
- Multi-tenant architecture
- RSA signing keys with encryption at rest
- Refresh tokens with rotation
- Token revocation support
- User info endpoint
- JWKS (JSON Web Key Set) endpoint
- Discovery endpoint (.well-known/openid-configuration)
Quick Start
1. Run Migrations
make db migrate upThis creates the following tables:
oidc_clients- OAuth2/OIDC client applicationsoidc_auth_requests- Authorization requests (temporary storage)oidc_refresh_tokens- Refresh tokensoidc_signing_keys- RSA signing keys (encrypted)
2. Configure Environment
# .env
OIDC_ISSUER_URL=https://your-domain.com
OIDC_CRYPTO_KEY=your-secure-random-32-char-minimum-key-hereGenerate crypto key:
openssl rand -base64 323. Bootstrap Signing Keys
Start the application (keys will be auto-generated):
make run4. Register a Client
INSERT INTO oidc_clients (
client_id,
name,
application_type,
redirect_uris,
require_pkce
) VALUES (
'my-client-id',
'My Application',
'web',
ARRAY['http://localhost:3000/callback'],
true
);Or use the example script:
psql -d iota_erp -f modules/oidc/examples/client_setup.sql5. Test OIDC Flow
Use the provided shell script to test the complete flow:
bash modules/oidc/examples/curl_flow.shArchitecture
modules/oidc/
├── domain/
│ └── entities/
│ ├── client/ # OAuth2 client entity
│ ├── authrequest/ # Authorization request entity
│ └── token/ # Refresh token entity
├── services/
│ └── oidc_service.go # Business logic layer
├── infrastructure/
│ ├── persistence/ # Repository implementations
│ └── oidc/
│ ├── keys.go # RSA key management
│ └── storage.go # OP storage implementation
├── presentation/
│ └── controllers/
│ └── oidc_controller.go # HTTP handlers
└── examples/ # Example code and scriptsSupported Flows
Authorization Code Flow
Standard OAuth 2.0 authorization code flow with optional PKCE:
- Client initiates authorization request
- User authenticates and consents
- Authorization code is issued
- Client exchanges code for tokens
- Client uses access token to access resources
Refresh Token Flow
Obtain new access tokens using refresh tokens:
- Client sends refresh token to token endpoint
- Server validates refresh token
- New access token is issued
- Optional: New refresh token is issued (rotation)
Endpoints
| Endpoint | Description |
|---|---|
GET /.well-known/openid-configuration | Discovery endpoint |
GET /oidc/authorize | Authorization endpoint |
POST /oidc/token | Token endpoint |
GET /oidc/userinfo | User info endpoint |
GET /oidc/keys | JWKS endpoint |
POST /oidc/revoke | Token revocation endpoint |
See API Reference for detailed endpoint documentation.
Security
Key Management
- RSA signing keys are generated automatically on first run
- Private keys are encrypted using AES-256-GCM before storage
- Crypto key is derived from
OIDC_CRYPTO_KEYenvironment variable using SHA-256 - Keys are stored in the
oidc_signing_keystable
Token Security
- Access tokens are short-lived (default: 1 hour)
- Refresh tokens are long-lived (default: 30 days)
- Authorization codes expire quickly (default: 5 minutes)
- All tokens are JWTs signed with RS256
- Refresh tokens are hashed (SHA-256) before storage
Client Security
- Client secrets are hashed using bcrypt
- PKCE is required for public clients
- Redirect URIs must exactly match (no wildcards)
- HTTPS required in production
See Configuration for security best practices.
Multi-Tenant Support
The OIDC module fully supports IOTA SDK’s multi-tenant architecture:
- Clients are global (shared across tenants)
- Auth requests are scoped to tenant after user authentication
- Refresh tokens are scoped to user + tenant + client combination
- Token claims include
tenant_id - User info returns data for authenticated tenant only
Testing
Run all OIDC tests:
# Run all OIDC tests
go test ./modules/oidc/... -v
# Run specific test suite
go test ./modules/oidc/infrastructure/persistence -v
go test ./modules/oidc/domain/entities/client -v
go test ./modules/oidc/services -v
# Run with coverage
go test ./modules/oidc/... -cover