This is the AuthServer module of the OpenESPI GreenButton Java monorepo. It is a modern Spring Boot 3.5 OAuth2 Authorization Server built with Spring Authorization Server 1.3+, providing secure authentication and authorization services for the Green Button ecosystem.
🚀 Migration Complete: This module has been fully migrated to Spring Boot 3.5 with Java 21, featuring enterprise-grade OAuth2 flows, comprehensive testing suite, and NAESB ESPI 4.0 compliance with TLS 1.3 enforcement.
This module provides OAuth2 Authorization Server capabilities as part of the OpenESPI GreenButton Java monorepo. It offers secure OAuth2 authorization flows compliant with Green Button Alliance ESPI standards, working seamlessly with the openespi-datacustodian resource server module.
- ✅ Java 21 with Maven 3.8+ compilation
- ✅ Unit & Integration Tests with JaCoCo coverage reporting
- ✅ Security Scanning with OWASP dependency check and Trivy
- ✅ Code Quality analysis with SonarCloud integration
- ✅ Docker Container builds with security hardening
- ✅ OAuth2 Flow Testing with live authorization server validation
- ✅ Multi-Database Testing with TestContainers (MySQL, PostgreSQL)
- ✅ Artifact Management with automated JAR and coverage uploads
- Spring Authorization Server 1.3+: Modern OAuth2/OIDC implementation with Java 21
- NAESB ESPI 4.0 Compliance: TLS 1.3 ONLY enforcement with approved cipher suites
- ESPI Opaque Tokens: Standard ESPI-compliant opaque access tokens (default)
- JWT Support (Experimental): Optional JWT tokens for future ESPI versions
- Multi-Grant Support: authorization_code, client_credentials, refresh_token flows
- Dynamic Client Registration: RFC 7591 compliant with ESPI validation
- OIDC UserInfo Endpoint: ESPI-specific claims and Green Button Alliance extensions
- Certificate-Based Authentication: X.509 client certificate support with trust stores
- HTTPS Enforcement: Production-grade TLS 1.3 with Perfect Forward Secrecy
- OAuth2 Consent Management: Professional consent UI with granular permissions
- Security Headers: Comprehensive HSTS, CSP, and NAESB ESPI 4.0 compliance headers
- OAuth2 Client Management API: Comprehensive CRUD operations with pagination
- DataCustodian Integration: Seamless integration with OpenESPI-DataCustodian-java
- Admin APIs: Token and client management with metrics and analytics
- Database-Backed Storage: JDBC repository with MySQL, PostgreSQL, H2 support
- Flyway Migrations: Database schema management with ESPI 4.0 enhancements
- Docker Containerization: Multi-stage builds with security hardening
- Kubernetes Ready: Helm charts and deployment manifests included
- Monitoring Integration: Prometheus metrics and Grafana dashboards
- CI/CD Pipeline: 5-stage GitHub Actions with security scanning
┌─────────────────────────────────────────────────────────────┐
│ OpenESPI Authorization Server │
├─────────────────────────────────────────────────────────────┤
│ OAuth2 Endpoints: │
│ • /oauth2/authorize (Authorization endpoint) │
│ • /oauth2/token (Token endpoint) │
│ • /oauth2/jwks (JSON Web Key Set) │
│ • /oauth2/consent (User consent page) │
│ │
│ Client Registration: │
│ • /connect/register (Dynamic client registration)│
│ • /connect/register/{id} (Get client information) │
│ │
│ Admin Endpoints: │
│ • /admin/oauth2/tokens (Token management) │
│ • /admin/oauth2/clients (Client management) │
│ • /admin/oauth2/authorizations (Authorization management) │
├─────────────────────────────────────────────────────────────┤
│ ESPI Components: │
│ • EspiTokenCustomizer (JWT token enhancement) │
│ • ConsentController (ESPI-aware consent flow) │
│ • ClientRegistrationController (Dynamic client registration) │
│ • OAuthAdminController (Administrative APIs) │
│ • JdbcRegisteredClientRepository (Database-backed clients) │
└─────────────────────────────────────────────────────────────┘
| Component | Status | Details |
|---|---|---|
| Database Migration | ✅ Complete | Flyway scripts for MySQL/PostgreSQL with ESPI 4.0 enhancements |
| OAuth2 Client Management | ✅ Complete | RESTful CRUD API with pagination and bulk operations |
| DataCustodian Integration | ✅ Complete | User verification, scope validation, authorization grants |
| OIDC UserInfo Endpoint | ✅ Complete | ESPI claims, Green Button extensions, consent-aware release |
| OAuth2 Consent Pages | ✅ Complete | Professional UI with granular permissions and mobile support |
| API Documentation | ✅ Complete | OpenAPI 3.0, integration guides, Postman collections |
| Certificate Authentication | ✅ Complete | X.509 client certificates with trust store management |
| Deployment Infrastructure | ✅ Complete | Docker, Kubernetes, monitoring, CI/CD pipeline |
| Spring Boot 3.5 Migration | ✅ Complete | API compatibility fixes, Jakarta validation, OAuth2 updates |
- Performance Optimization: Redis caching, query optimization, load testing
- Security Enhancements: Automated certificate renewal, advanced monitoring
- Production Monitoring: Prometheus/Grafana integration, alerting rules
- Documentation: Interactive Swagger UI, SDK generation, tutorials
- Java 21 or higher
- Maven 3.8+
- MySQL 8.0+ or PostgreSQL 13+ (for production)
# Clone the monorepo (contains this module)
git clone https://github.com/GreenButtonAlliance/OpenESPI-GreenButton-Java.git
cd OpenESPI-GreenButton-Java
# Build all modules including openespi-authserver
mvn clean install
# Run the AuthServer module with local H2 profile
cd openespi-authserver && mvn spring-boot:run -P local
# Access H2 Console: http://localhost:9999/h2-console
# JDBC URL: jdbc:h2:mem:oauth2_authserver
# Username: sa
# Password: (empty)# Start MySQL and create database
mysql -u root -p
CREATE DATABASE oauth2_authserver;
CREATE USER 'openespi_user'@'localhost' IDENTIFIED BY 'openespi_password';
GRANT ALL PRIVILEGES ON oauth2_authserver.* TO 'openespi_user'@'localhost';
# Run the AuthServer module with MySQL profile
cd openespi-authserver && mvn spring-boot:run -P dev-mysqlDefault (ESPI Compliant):
espi:
token:
format: opaque # ESPI standard - opaque access tokensExperimental JWT Support:
espi:
token:
format: jwt # Experimental - for future ESPI versions| Profile | Database | Purpose |
|---|---|---|
local |
H2 in-memory | Local development |
dev-mysql |
MySQL | Development with persistent storage |
dev-postgresql |
PostgreSQL | Development with PostgreSQL |
prod |
Environment-specific | Production deployment |
For production deployment:
# Database Configuration
DB_URL=jdbc:mysql://localhost:3306/oauth2_authserver
DB_USERNAME=openespi_user
DB_PASSWORD=secure_password
# OAuth2 Configuration
OAUTH2_ISSUER_URI=https://auth.yourdomain.com
JWT_KEYSTORE_PATH=/path/to/keystore.p12
JWT_KEYSTORE_PASSWORD=keystore_password
# SSL Configuration (if using HTTPS)
SERVER_SSL_ENABLED=true
SERVER_SSL_KEYSTORE=/path/to/ssl-keystore.p12
SERVER_SSL_KEYSTORE_PASSWORD=ssl_password# 1. Authorization Request
GET /oauth2/authorize?
response_type=code&
client_id=third_party&
redirect_uri=http://localhost:9090/callback&
scope=FB=4_5_15;IntervalDuration=3600&
state=random_state
# 2. User Login and Consent (via browser)
# 3. Authorization Code Response
HTTP/1.1 302 Found
Location: http://localhost:9090/callback?code=auth_code&state=random_state
# 4. Token Exchange
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic dGhpcmRfcGFydHk6c2VjcmV0
grant_type=authorization_code&
code=auth_code&
redirect_uri=http://localhost:9090/callback&
client_id=third_partyPOST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZGF0YV9jdXN0b2RpYW5fYWRtaW46c2VjcmV0
grant_type=client_credentials&
scope=DataCustodian_Admin_AccessESPI Standard (Default): Opaque access tokens as per ESPI specification
Experimental JWT Support: Optional JWT tokens include custom claims:
{
"sub": "[email protected]",
"aud": "third_party",
"iss": "http://localhost:9999",
"exp": 1735689600,
"iat": 1735686000,
"scope": ["FB=4_5_15;IntervalDuration=3600", "openid"],
"authorizationURI": "http://localhost:8080/espi/1_1/resource/Authorization/123",
"resourceURI": "http://localhost:8080/espi/1_1/resource/",
"espi_version": "1.1",
"espi_client_type": "customer",
"espi_grant_type": "authorization_code",
"data_custodian_endpoint": "http://localhost:8080",
"client_name": "ThirdParty Application"
}GET /oauth2/authorize- Authorization endpointPOST /oauth2/token- Token endpointGET /oauth2/jwks- JSON Web Key SetPOST /oauth2/revoke- Token revocationPOST /oauth2/introspect- Token introspectionGET /.well-known/oauth-authorization-server- Discovery endpoint
POST /connect/register- Dynamic client registration (RFC 7591)GET /connect/register/{client_id}- Get client information
GET /oauth2/consent- User consent pagePOST /oauth2/consent- Process consent
GET /admin/oauth2/tokens- List active tokensDELETE /admin/oauth2/tokens/{tokenId}- Revoke tokenGET /admin/oauth2/clients- List registered clientsGET /admin/oauth2/clients/{clientId}- Get specific clientDELETE /admin/oauth2/clients/{clientId}- Delete clientDELETE /admin/oauth2/clients/{clientId}/tokens- Revoke all client tokensGET /admin/oauth2/authorizations- List authorizations
The Authorization Server supports RFC 7591 (OAuth 2.0 Dynamic Client Registration Protocol) with ESPI-specific validations.
POST /connect/register
Content-Type: application/json
{
"client_name": "My ThirdParty App",
"redirect_uris": [
"https://myapp.example.com/callback"
],
"grant_types": ["authorization_code", "refresh_token"],
"scope": "openid profile FB=4_5_15;IntervalDuration=3600;BlockDuration=monthly;HistoryLength=13",
"token_endpoint_auth_method": "client_secret_basic"
}{
"client_id": "espi_client_1735689600_abc123",
"client_secret": "generated_secret_here",
"client_name": "My ThirdParty App",
"client_id_issued_at": 1735689600,
"client_secret_expires_at": 0,
"redirect_uris": [
"https://myapp.example.com/callback"
],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "client_secret_basic",
"scope": "openid profile FB=4_5_15;IntervalDuration=3600;BlockDuration=monthly;HistoryLength=13"
}The client registration process validates:
- Scopes: Must be ESPI-compliant scopes or standard OIDC scopes
- Grant Types: Only
authorization_code,client_credentials, andrefresh_tokenare supported - Redirect URIs: Must be absolute HTTPS URIs (HTTP allowed for localhost development)
- Client Authentication: Supports
client_secret_basic,client_secret_post, andnone
openid- OpenID Connect identityprofile- User profile informationFB=4_5_15;IntervalDuration=3600;BlockDuration=monthly;HistoryLength=13- Monthly usage data (1-hour intervals)FB=4_5_15;IntervalDuration=900;BlockDuration=monthly;HistoryLength=13- Monthly usage data (15-minute intervals)DataCustodian_Admin_Access- Administrative access to DataCustodianThirdParty_Admin_Access- Administrative access for ThirdParty applications
# Run unit tests for this module only
mvn test -pl openespi-authserver
# Run integration tests for this module
mvn verify -pl openespi-authserver
# Run with test coverage
mvn test jacoco:report -pl openespi-authserver
# Run all tests in the monorepo
mvn clean testThe authorization server uses Spring Authorization Server's standard schema with ESPI extensions:
oauth2_registered_client- OAuth2 client registrationsoauth2_authorization- Authorization grants and tokensoauth2_authorization_consent- User consent recordsespi_application_info- ESPI-specific application metadata
- Use external database (MySQL/PostgreSQL)
- Configure proper JWT signing keys
- Enable HTTPS/TLS
- Set secure session configuration
- Configure CORS policies
- Enable audit logging
- Set up monitoring and alerting
- Regular security updates
For production, replace the auto-generated RSA key pair:
@Bean
public JWKSource<SecurityContext> jwkSource() {
// Load from external keystore
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("/path/to/keystore.p12"),
keystorePassword.toCharArray());
// ... configure RSAKey from keystore
}The DataCustodian (Resource Server) validates tokens from this Authorization Server:
ESPI Standard (Opaque Tokens):
# DataCustodian application.yml
spring:
security:
oauth2:
resourceserver:
opaque-token:
introspection-uri: http://localhost:9999/oauth2/introspect
client-id: datacustodian_resource_server
client-secret: secretExperimental (JWT Tokens):
# DataCustodian application.yml (experimental)
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://localhost:9999ThirdParty applications use this server for OAuth2 flows:
# ThirdParty application.yml
spring:
security:
oauth2:
client:
registration:
datacustodian:
client-id: third_party
client-secret: secret
authorization-grant-type: authorization_code
redirect-uri: http://localhost:9090/oauth/callback
provider:
datacustodian:
authorization-uri: http://localhost:9999/oauth2/authorize
token-uri: http://localhost:9999/oauth2/token
jwk-set-uri: http://localhost:9999/oauth2/jwksGET /actuator/health- Application healthGET /actuator/info- Application informationGET /actuator/metrics- MetricsGET /actuator/env- Environment properties
Configure logging for OAuth2 events:
logging:
level:
org.springframework.security.oauth2: DEBUG
org.greenbuttonalliance.espi: DEBUG- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Licensed under the Apache License, Version 2.0. See LICENSE for details.
This project is part of the Green Button Alliance initiative for standardized energy data access.
For more information about OpenESPI and Green Button: