|
| 1 | +# Changelog |
| 2 | + |
| 3 | +All notable changes to this project will be documented in this file. |
| 4 | + |
| 5 | +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), |
| 6 | +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). |
| 7 | + |
| 8 | +## [1.4.0] - 2026-01-08 |
| 9 | + |
| 10 | +### Breaking Changes |
| 11 | + |
| 12 | +- **Default token length increased** from 16 to 32 characters for improved security (24 chars hidden entropy after 8-char prefix) |
| 13 | +- **Default `rotateStaleSeconds` changed** from 0 (disabled) to 3600 (1 hour) - secure by default |
| 14 | +- **Removed `deleteExpiredBatch`** from `OgiriTokenRepository` interface (now internal to service implementation) |
| 15 | +- **Removed `-Xjvm-default=all`** compiler flag requirement (no longer needed for consuming projects) |
| 16 | + |
| 17 | +### Security Fixes |
| 18 | + |
| 19 | +- **Fixed token cache timing attack**: Added constant-time delay (100ms minimum) to mask cache hit vs miss timing differences |
| 20 | +- **Hardened cache keys**: Cache keys now use SHA-256 hashes instead of plaintext tokens to prevent extraction from memory dumps |
| 21 | +- **Fixed user enumeration timing attack**: Added constant-time dummy password check when user not found to prevent timing-based username enumeration |
| 22 | +- **Increased default token length**: Changed from 16 to 32 characters to provide 24 chars of hidden entropy (after 8-char prefix) |
| 23 | +- **Enabled token rotation by default**: Changed default `rotateStaleSeconds` from 0 (disabled) to 3600 (1 hour) for periodic credential refresh |
| 24 | +- **Added path traversal attack logging**: Log warnings when URI parsing fails during bypass check to detect potential path traversal attempts |
| 25 | + |
| 26 | +### Performance Improvements |
| 27 | + |
| 28 | +- **Added batch token fetching**: New `findByUserIdAndClientIn` method enables single query for all sub-tokens, eliminating N+1 query problem in `buildAuthHeader` |
| 29 | +- **Added prefix fallback warning**: Log warning when token prefix lookup returns no candidates and falls back to full table scan |
| 30 | +- **Optimized `countByUserId`**: Sample repositories now use `COUNT(*)` query instead of loading all tokens |
| 31 | + |
| 32 | +### Repository Simplification |
| 33 | + |
| 34 | +- Removed `-Xjvm-default=all` compiler flag from `ogiri-core` and `sample-kotlin` build scripts |
| 35 | +- Moved batch cleanup logic from repository interface to service implementation |
| 36 | +- Java and Kotlin samples now have symmetric implementations |
| 37 | +- Cleaner separation between repository concerns and service orchestration |
| 38 | + |
| 39 | +### Documentation |
| 40 | + |
| 41 | +- Updated CHANGELOG with comprehensive 1.4.0 release notes |
| 42 | +- Updated security default warnings in configuration properties |
| 43 | +- Improved inline documentation for new security features |
| 44 | + |
| 45 | +## [1.3.1] - 2026-01-08 |
| 46 | + |
| 47 | +### Changed |
| 48 | + |
| 49 | +- **Simplified Repository Integration**: `OgiriTokenRepository` method names now follow Spring Data naming conventions, enabling direct interface extension without requiring the adapter pattern. |
| 50 | + |
| 51 | + - Users can now simply extend both `JpaRepository` (or `CrudRepository`) and `OgiriTokenRepository` in a single interface |
| 52 | + - Spring Data automatically generates all query implementations |
| 53 | + - Reduces boilerplate from 3 files (~65 lines) to 2 files (~15 lines) |
| 54 | + |
| 55 | +- **Method Renames** (Spring Data compatible naming): |
| 56 | + |
| 57 | + - `findAllByUserId()` → `findByUserIdOrderByUpdatedAtDesc()` |
| 58 | + - `findAllByUserIdAndTokenSubtype()` → `findByUserIdAndTokenSubtypeOrderByUpdatedAtDesc()` |
| 59 | + - `findAllByTokenType()` → `findByTokenType()` |
| 60 | + - `findValidTokensByPrefix()` → `findByTokenPrefixAndTokenTypeAndExpiryAtAfter()` |
| 61 | + |
| 62 | +- **Return Type Changes** (Java-friendly API): |
| 63 | + - `findById()` now returns `Optional<T>` instead of `T?` |
| 64 | + - `findByUserIdAndClient()` now returns `Optional<T>` instead of `T?` |
| 65 | + |
| 66 | +### Deprecated |
| 67 | + |
| 68 | +- `AbstractJpaTokenRepositoryAdapter` in `ogiri-jpa` module is now deprecated. Use direct interface extension instead. |
| 69 | + |
| 70 | +### Migration Guide |
| 71 | + |
| 72 | +**Before (1.3.0 and earlier):** |
| 73 | + |
| 74 | +```kotlin |
| 75 | +// Required 3 files: Entity + JPA Repository + Adapter |
| 76 | +interface MyTokenJpaRepository : JpaRepository<MyToken, Long> { |
| 77 | + fun findByUserIdAndClient(userId: Long, client: String): MyToken? |
| 78 | + // ... many more methods |
| 79 | +} |
| 80 | + |
| 81 | +class MyTokenRepositoryAdapter( |
| 82 | + private val jpaRepository: MyTokenJpaRepository |
| 83 | +) : AbstractJpaTokenRepositoryAdapter<MyToken, MyTokenJpaRepository>(jpaRepository) |
| 84 | +``` |
| 85 | + |
| 86 | +**After (1.3.1+):** |
| 87 | + |
| 88 | +```kotlin |
| 89 | +// Only 2 files: Entity + Repository Interface |
| 90 | +@Repository |
| 91 | +interface MyTokenRepository : |
| 92 | + JpaRepository<MyToken, Long>, |
| 93 | + OgiriTokenRepository<MyToken> |
| 94 | +``` |
| 95 | + |
| 96 | +**Method call updates (if calling repository directly):** |
| 97 | + |
| 98 | +```kotlin |
| 99 | +// Old |
| 100 | +repository.findAllByUserId(userId) |
| 101 | +repository.findByUserIdAndClient(userId, client) // returned T? |
| 102 | + |
| 103 | +// New |
| 104 | +repository.findByUserIdOrderByUpdatedAtDesc(userId) |
| 105 | +repository.findByUserIdAndClient(userId, client).orElse(null) // returns Optional<T> |
| 106 | +``` |
| 107 | + |
| 108 | +## [1.3.0] - 2025-01-08 |
| 109 | + |
| 110 | +### Added |
| 111 | + |
| 112 | +- **New `ogiri-jpa` Module**: Dedicated JPA/Hibernate support module that reduces boilerplate by ~70% |
| 113 | + - `OgiriBaseTokenEntity`: `@MappedSuperclass` with all 15+ token fields pre-annotated |
| 114 | + - `AbstractJpaTokenRepositoryAdapter`: Base adapter eliminating ~80 lines of repository boilerplate |
| 115 | + - `OgiriJpaAutoConfiguration`: Spring Boot auto-configuration for the JPA module |
| 116 | +- **PasswordEncoder Auto-Configuration**: Automatically provides `BCryptPasswordEncoder` when no `PasswordEncoder` bean exists |
| 117 | +- **OgiriMissingBeanFailureAnalyzer**: Helpful error messages when required beans are missing, with specific guidance for each bean type |
| 118 | +- **Configuration Processor**: IDE autocomplete support for `ogiri.*` properties |
| 119 | +- Token prefix indexing for O(1) database lookups (performance optimization) |
| 120 | +- Configurable `max-bearer-token-size` property (default 8192, DoS protection) |
| 121 | +- Configurable `cleanup.batch-size` property for batched token deletion |
| 122 | +- Cookie configuration properties (`enabled`, `secure`, `http-only`, `same-site`, `path`) |
| 123 | +- Startup warnings for insecure configurations |
| 124 | +- New repository methods: `findValidTokensByPrefix`, `countByUserId`, `deleteExpiredBatch` |
| 125 | + |
| 126 | +### Changed |
| 127 | + |
| 128 | +- **Sample Applications**: Updated to use `ogiri-jpa` module, demonstrating the simplified approach |
| 129 | +- **Documentation**: Restructured to highlight `ogiri-jpa` as the recommended path for JPA users |
| 130 | +- **CI Workflows**: Updated to build, test, and publish the new `ogiri-jpa` module |
| 131 | +- Token cleanup now uses batched deletion for large datasets |
| 132 | +- Bearer token size validation is now configurable |
| 133 | + |
| 134 | +### Installation |
| 135 | + |
| 136 | +**With JPA Support (Recommended):** |
| 137 | + |
| 138 | +```kotlin |
| 139 | +implementation("com.quantipixels.ogiri:ogiri-jpa:1.3.0") |
| 140 | +``` |
| 141 | + |
| 142 | +**Core Only (Custom Persistence):** |
| 143 | + |
| 144 | +```kotlin |
| 145 | +implementation("com.quantipixels.ogiri:ogiri-core:1.3.0") |
| 146 | +``` |
| 147 | + |
| 148 | +### Database Migration (Optional) |
| 149 | + |
| 150 | +For optimal performance, add `token_prefix` column: |
| 151 | + |
| 152 | +- Add `token_prefix VARCHAR(8)` column to tokens table |
| 153 | +- Add index on `token_prefix` (partial index for PostgreSQL recommended) |
| 154 | + |
| 155 | +See [Migration Guide](migration-guide.md#migrating-to-130) for detailed upgrade instructions. |
| 156 | + |
| 157 | +### Upgrade Notes |
| 158 | + |
| 159 | +- This release is fully backward compatible |
| 160 | +- Existing `ogiri-core` users can continue without changes |
| 161 | +- JPA users are encouraged to migrate to `ogiri-jpa` for reduced boilerplate (see [Migration Guide](migration-guide.md)) |
| 162 | + |
| 163 | +## [1.2.1] - 2025-01-07 |
| 164 | + |
| 165 | +### Added |
| 166 | + |
| 167 | +- Comprehensive test suite for token and security services |
| 168 | +- Initial secure cookie support with secure defaults (enhanced with properties in 1.3.0) |
| 169 | +- Token cleanup optimization with batched deletion |
| 170 | +- Fallback error messages in OgiriAuthenticationEntryPoint to prevent 500 errors when messages.properties is missing |
| 171 | + |
| 172 | +### Changed |
| 173 | + |
| 174 | +- Renamed SubTokenRegistry to OgiriSubTokenRegistry for consistency |
| 175 | +- OgiriRouteRegistry method renamed from `registrations()` to `routes()` |
| 176 | + |
| 177 | +### Fixed |
| 178 | + |
| 179 | +- Bearer token authentication now returns 401 with proper error message instead of 500 |
| 180 | + |
| 181 | +## [1.2.0] - 2025-12-12 |
| 182 | + |
| 183 | +### Added |
| 184 | + |
| 185 | +- **Interface-First Design**: Introduced `OgiriToken` interface as the primary contract for tokens, allowing implementation flexibility without forced inheritance. |
| 186 | +- **Migration Guide**: Added [Migration Guide](migration-guide.md) to assist with the transition to 1.2.0. |
| 187 | + |
| 188 | +### Changed |
| 189 | + |
| 190 | +- **Renamed Core Classes**: |
| 191 | + - `BaseToken` → `OgiriBaseToken` |
| 192 | + - `TokenRepository` → `OgiriTokenRepository` |
| 193 | + - `TokenService` → `OgiriTokenService` |
| 194 | + - `GeneratedTokens` → `OgiriGeneratedTokens` |
| 195 | +- **Updated Type Bounds**: All generic type parameters now use `<T : OgiriToken>` instead of `<T : BaseToken>`. |
| 196 | +- **Documentation**: Comprehensive updates to reflect the new interface-first architecture. |
| 197 | + |
| 198 | +### Upgrade Notes |
| 199 | + |
| 200 | +- This release involves renaming core classes. Please refer to the [Migration Guide](migration-guide.md) for detailed instructions on updating your code. |
| 201 | + |
| 202 | +## [1.1.1] - 2025-12-11 |
| 203 | + |
| 204 | +### Added |
| 205 | + |
| 206 | +- GitHub Pages automatic deployment workflow with mike versioning |
| 207 | +- Documentation versioning support with multi-version dropdown |
| 208 | +- Documentation improvements and standardization |
| 209 | +- `scripts/publish-docs.sh` for manual documentation deployment |
| 210 | +- `docs/versioning-guide.md` for comprehensive versioning documentation |
| 211 | +- `docs/github-pages-setup.md` deployment and setup guide |
| 212 | + |
| 213 | +### Changed |
| 214 | + |
| 215 | +- **Documentation restructured** - Removed 60% duplication |
| 216 | + - Consolidated CLAUDE.md into AGENTS.md (600 → 200 lines) |
| 217 | + - Simplified README.md (342 → 97 lines) |
| 218 | + - Merged redundant files (release.md, migration.md, getting-started.md) |
| 219 | +- Standardized all documentation filenames to lowercase with hyphens |
| 220 | +- Updated mkdocs.yml with mike versioning provider |
| 221 | +- Enhanced .github/workflows/docs.yml with three-job deployment pipeline |
| 222 | +- Improved AGENTS.md as comprehensive AI assistant guidance (from CLAUDE.md) |
| 223 | + |
| 224 | +### Fixed |
| 225 | + |
| 226 | +- All documentation cross-references verified (0 broken links) |
| 227 | +- Consistent file naming across docs directory |
| 228 | +- GitHub Pages configuration for automatic deployments |
| 229 | + |
| 230 | +### Documentation Quality |
| 231 | + |
| 232 | +- 11 focused core docs (down from 13) |
| 233 | +- Single source of truth for all topics |
| 234 | +- 5-minute quickstart guide for new users |
| 235 | +- Clear information hierarchy |
| 236 | +- Professional Material theme configuration |
| 237 | + |
| 238 | +## [1.1.0] - 2025-12-09 |
| 239 | + |
| 240 | +### Added |
| 241 | + |
| 242 | +- `OgiriUser.getOgiriUserId()` for conflict-free Java getter while retaining Kotlin property access |
| 243 | +- Documentation for overriding auto-configured `OgiriTokenAuthenticationFilter` with custom bean/subclass |
| 244 | +- Java sample repository with `findAllByUserIdAndTokenSubtype(...)` for sub-token queries |
| 245 | +- `parseBearerToken()` with fallback in auth filter for Base64/JSON bearer payloads |
| 246 | +- `OgiriSubTokenRegistration.validate()` plus `OgiriTokenService` helpers (`getSubToken`, `revokeSubToken`, `renewSubTokenAndGetHeaders`) |
| 247 | + |
| 248 | +### Changed |
| 249 | + |
| 250 | +- Replaced deprecated `NoOpPasswordEncoder` in tests with inline `PasswordEncoder` stub |
| 251 | +- Token service and filters now consistently call `user.getOgiriUserId()` |
| 252 | +- `scripts/release.sh` supports `-f/--force` for reusing/overwriting existing tags |
| 253 | + |
| 254 | +### Fixed |
| 255 | + |
| 256 | +- Java sample `SampleOgiriUserDirectory.SampleUser` now implements `getOgiriUserId()` |
| 257 | + |
| 258 | +### Upgrade Notes |
| 259 | + |
| 260 | +If upgrading from 1.0.x: |
| 261 | + |
| 262 | +1. **Update version** - Change dependency to `1.1.0` |
| 263 | +2. **Implement `getOgiriUserId()`** - Java implementations must add `long getOgiriUserId()` method |
| 264 | +3. **Add `findAllByUserIdAndTokenSubtype()`** - Required in `OgiriTokenRepository` for sub-token rotation |
| 265 | +4. **Review filter overrides** - If you register `OgiriTokenAuthenticationFilter`, auto-configuration will use your bean |
| 266 | + |
| 267 | +## [1.0.4] - 2025-12-08 |
| 268 | + |
| 269 | +### Fixed |
| 270 | + |
| 271 | +- Removed conflicting `jitpack.yml` configuration |
| 272 | + |
| 273 | +## [1.0.3] - 2025-12-08 |
| 274 | + |
| 275 | +### Fixed |
| 276 | + |
| 277 | +- Fixed `.jitpack.yml` configuration for package usage |
| 278 | +- Fixed Spotless breaking build |
| 279 | +- Fixed tests failing in GitHub Actions |
| 280 | + |
| 281 | +## [1.0.2] - 2025-12-06 |
| 282 | + |
| 283 | +### Fixed |
| 284 | + |
| 285 | +- **Test Infrastructure:** Fixed `InMemoryTokenRepository.save()` losing transient `plainToken` property during data class copy operations |
| 286 | +- **Test Assertions:** Fixed type mismatch in token type comparisons (String vs TokenType enum) |
| 287 | + |
| 288 | +### Changed |
| 289 | + |
| 290 | +- Updated GitHub Actions badge URLs to correct repository name (`mosobande/ogiri`) |
| 291 | +- Updated POM metadata URLs to point to correct GitHub repository |
| 292 | +- Configured JitPack support with `.jitpack.yml` |
| 293 | +- Configured Spotless formatter across all modules |
| 294 | +- Centralized version management in `.ogiri-version` |
| 295 | + |
| 296 | +### Security |
| 297 | + |
| 298 | +- Verified GitHub Actions credentials are properly scoped |
| 299 | + |
| 300 | +## [1.0.1] - 2025-12-05 |
| 301 | + |
| 302 | +### Added |
| 303 | + |
| 304 | +- Centralized version management in `settings.gradle.kts` |
| 305 | +- changelog.md, security.md, contributing.md, code-of-conduct.md |
| 306 | +- `.github/dependabot.yml` for automated dependency updates |
| 307 | + |
| 308 | +### Changed |
| 309 | + |
| 310 | +- Enhanced `docs/database.md` with schema file references |
| 311 | +- Improved `.github/workflows/lint.yml` error messaging |
| 312 | +- Externalized database credentials in sample applications |
| 313 | + |
| 314 | +### Fixed |
| 315 | + |
| 316 | +- Hardcoded PostgreSQL credentials now use environment variables |
| 317 | +- Lint workflow provides better error guidance |
| 318 | + |
| 319 | +### Security |
| 320 | + |
| 321 | +- Established vulnerability disclosure process (24-hour SLA) |
| 322 | +- Added automated dependency scanning with Dependabot |
| 323 | +- Created comprehensive security policy |
| 324 | + |
| 325 | +## [1.0.0] - 2025-12-05 |
| 326 | + |
| 327 | +### Added |
| 328 | + |
| 329 | +- Initial public release |
| 330 | +- Token-based authentication with pluggable sub-tokens |
| 331 | +- Database-agnostic `TokenRepository<T>` interface |
| 332 | +- Spring Boot auto-configuration with `OgiriSecurityAutoConfiguration` |
| 333 | +- Filter-based authentication via `OgiriTokenAuthenticationFilter` |
| 334 | +- Configurable token rotation policies with grace periods |
| 335 | +- Support for custom sub-tokens via `OgiriSubTokenRegistration` |
| 336 | + |
| 337 | +### Database Support |
| 338 | + |
| 339 | +- **SQL:** PostgreSQL, MySQL/MariaDB, Oracle, SQL Server, H2 |
| 340 | +- **NoSQL:** MongoDB, Redis, DynamoDB, Cassandra, Firebase |
| 341 | +- **Legacy:** Adapter pattern for existing token tables |
| 342 | +- Bundled schema files for PostgreSQL, MySQL, and H2 |
| 343 | + |
| 344 | +### CI/CD |
| 345 | + |
| 346 | +- GitHub Actions workflows for build, test, lint, and release |
| 347 | +- Automated Maven Central publishing with GPG signing |
| 348 | +- Automatic snapshot deployments on main branch |
| 349 | +- Tag-based release triggering (`v*.*.*`) |
| 350 | + |
| 351 | +### Sample Applications |
| 352 | + |
| 353 | +- Pure Java sample application |
| 354 | +- Kotlin Spring Boot sample application |
| 355 | +- Both demonstrate required SPI implementations |
| 356 | + |
| 357 | +## License |
| 358 | + |
| 359 | +Apache License 2.0 |
0 commit comments