feat(auth): JWT authentication, user management, and hybrid CSRF - #45
Merged
Conversation
…d CSRF - oauth2-jose + oauth2-resource-server dependencies - JwtProperties (syncflow.jwt.*) + JwtSecurityConfig: HS256 encoder/decoder via Nimbus; secret validated (base64, >= 32 bytes) with clear startup errors - AuthSecurityBeans: BCrypt PasswordEncoder, AuthenticationManager (non- deprecated DaoAuthenticationProvider constructor), JwtAuthenticationConverter - WebSecurityConfig: oauth2ResourceServer JWT bearer for /api/**, hybrid CSRF (cookie repo, /api/** ignored), stateless, /api/auth/** public - V9 migration: app_users table + seeded admin (BCrypt) - SecurityConfig: /api/auth/** added to public paths
…omain - DbUserDetailsService: loads app_users, maps CSV roles to ROLE_ authorities - AuthService: authenticate via AuthenticationManager, issue JWT with scope claim carrying roles (no duplicate user-store query; carries authorities from the principal) - AuthController: /api/auth/login (401 for bad/disabled/locked), /api/auth/me - UserService + RoleConstants: user CRUD, role allow-list, password encoding, duplicate detection (thin controller, domain rules centralized) - UserManagementController: /api/users CRUD + roles, guarded by RBAC, @Valid Bean Validation - UserEntity (app_users) + UserRepository - AdminController: fix createOrg AI_USE->ORG_WRITE, guard revokeApiKey/getQuota
- ApiAuthContractTest: login success/bad-password/token-authed/unauthenticated assertions against the real security chain - AuthServiceTest, DbUserDetailsServiceTest, UserServiceTest, UserEntityMappingTest (guards the app_users table name against sample-table collision) - docs/api/auth.md: login/me endpoints, token usage, syncflow.jwt.* config - docs/security/authentication.md: auth model, accounts, CSRF policy, security considerations, threat mapping - api-stability-matrix: link auth endpoints
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements real authentication for the control plane: JWT login against a users table (BCrypt hashes), full user management, JWT validation via Spring Security oauth2 resource-server, and a hybrid CSRF policy. This resolves the previously-hollow security config (CSRF disabled, no auth mechanism) and the "Disabled Spring CSRF protection" scan finding.
Changes
Auth core
spring-security-oauth2-jose+spring-security-oauth2-resource-serverJwtProperties(syncflow.jwt.*) +JwtSecurityConfig— HS256 encoder/decoder via Nimbus; secret validated (base64, ≥ 32 bytes) with clear startup errorsPasswordEncoder,AuthenticationManager(non-deprecatedDaoAuthenticationProviderconstructor),JwtAuthenticationConverteroauth2ResourceServerJWT bearer for/api/**, hybrid CSRF (cookie repo,/api/**bearer paths ignored), stateless,/api/auth/**publicUsers
app_userstable + seededadmin(BCrypt). Namedapp_users(notusers) to avoid colliding with sample/integration tables.UserEntity,UserRepository,UserService(create/update/roles/delete, role allow-list, password encoding),RoleConstants,DbUserDetailsService(CSV roles →ROLE_*authorities)POST /api/auth/login,GET /api/auth/me,/api/usersCRUD + role assignment (guarded by existing RBAC,@ValidBean Validation)scopeclaim carrying roles; carries authorities from the authenticated principal (no duplicate user-store query)RBAC fixes
AdminController.createOrg:AI_USE→ORG_WRITE(copy-paste bug)revokeApiKey(APIKEY_REVOKE) andgetQuota(ORG_READ)Tests
ApiAuthContractTest: login success / bad-password 401 / token-authed 200 / unauthenticated 401AuthServiceTest,DbUserDetailsServiceTest,UserServiceTest,UserEntityMappingTest(guards theapp_userstable name)Docs
docs/api/auth.md— login/me endpoints, token usage,syncflow.jwt.*configdocs/security/authentication.md— auth model, CSRF policy, threat mappingDesign notes
TenantFilter→AuthorizationService/PolicyResolver) — no parallel authz model.Validation
./gradlew testgreen; all security + user + PgMongo suites pass.