diff --git a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java index 37393f70..c3620c8c 100644 --- a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java +++ b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/JwtAuthenticationFilter.java @@ -52,7 +52,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { JwtValidationResult result = jwtService.validateAccessToken(token); String subject = result.subject(); - if (subject.startsWith("ui:")) { + if (subject.startsWith("user:")) { // UI user token — authenticate with roles from JWT List authorities = toAuthorities(result.roles()); UsernamePasswordAuthenticationToken auth = diff --git a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/OidcAuthController.java b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/OidcAuthController.java index ed9bade4..ee16939a 100644 --- a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/OidcAuthController.java +++ b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/OidcAuthController.java @@ -110,7 +110,7 @@ public class OidcAuthController { OidcTokenExchanger.OidcUserInfo oidcUser = tokenExchanger.exchange(request.code(), request.redirectUri()); - String userId = "oidc:" + oidcUser.subject(); + String userId = "user:oidc:" + oidcUser.subject(); String issuerHost = URI.create(config.get().issuerUri()).getHost(); String provider = "oidc:" + issuerHost; @@ -127,8 +127,8 @@ public class OidcAuthController { userRepository.upsert(new UserInfo( userId, provider, oidcUser.email(), oidcUser.name(), roles, Instant.now())); - String accessToken = jwtService.createAccessToken(userId, "ui", roles); - String refreshToken = jwtService.createRefreshToken(userId, "ui", roles); + String accessToken = jwtService.createAccessToken(userId, "user", roles); + String refreshToken = jwtService.createRefreshToken(userId, "user", roles); return ResponseEntity.ok(new AuthTokenResponse(accessToken, refreshToken)); } catch (ResponseStatusException e) { diff --git a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/UiAuthController.java b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/UiAuthController.java index 36ae17b9..e030c078 100644 --- a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/UiAuthController.java +++ b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/security/UiAuthController.java @@ -28,7 +28,7 @@ import java.util.List; * Authentication endpoints for the UI (local credentials). *

* Validates credentials against environment-configured username/password, - * then issues JWTs with {@code ui:} prefixed subjects and ADMIN roles. + * then issues JWTs with {@code user:} prefixed subjects and ADMIN roles. * Upserts the user into the user store on login. */ @RestController @@ -70,7 +70,7 @@ public class UiAuthController { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid credentials"); } - String subject = "ui:" + request.username(); + String subject = "user:" + request.username(); List roles = List.of("ADMIN"); // Upsert local user into store @@ -81,8 +81,8 @@ public class UiAuthController { log.warn("Failed to upsert local user to store (login continues): {}", e.getMessage()); } - String accessToken = jwtService.createAccessToken(subject, "ui", roles); - String refreshToken = jwtService.createRefreshToken(subject, "ui", roles); + String accessToken = jwtService.createAccessToken(subject, "user", roles); + String refreshToken = jwtService.createRefreshToken(subject, "user", roles); log.info("UI user logged in: {}", request.username()); return ResponseEntity.ok(new AuthTokenResponse(accessToken, refreshToken)); @@ -96,14 +96,14 @@ public class UiAuthController { public ResponseEntity refresh(@RequestBody RefreshRequest request) { try { JwtValidationResult result = jwtService.validateRefreshToken(request.refreshToken()); - if (!result.subject().startsWith("ui:")) { + if (!result.subject().startsWith("user:")) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Not a UI token"); } // Preserve roles from the refresh token List roles = result.roles(); - String accessToken = jwtService.createAccessToken(result.subject(), "ui", roles); - String refreshToken = jwtService.createRefreshToken(result.subject(), "ui", roles); + String accessToken = jwtService.createAccessToken(result.subject(), "user", roles); + String refreshToken = jwtService.createRefreshToken(result.subject(), "user", roles); return ResponseEntity.ok(new AuthTokenResponse(accessToken, refreshToken)); } catch (ResponseStatusException e) { diff --git a/cameleer3-server-app/src/test/java/com/cameleer3/server/app/security/JwtServiceTest.java b/cameleer3-server-app/src/test/java/com/cameleer3/server/app/security/JwtServiceTest.java index 1fb9ba8d..3219a442 100644 --- a/cameleer3-server-app/src/test/java/com/cameleer3/server/app/security/JwtServiceTest.java +++ b/cameleer3-server-app/src/test/java/com/cameleer3/server/app/security/JwtServiceTest.java @@ -75,10 +75,10 @@ class JwtServiceTest { @Test void accessToken_rolesRoundTrip() { List roles = List.of("ADMIN", "OPERATOR"); - String token = jwtService.createAccessToken("ui:admin", "ui", roles); + String token = jwtService.createAccessToken("user:admin", "user", roles); JwtService.JwtValidationResult result = jwtService.validateAccessToken(token); - assertEquals("ui:admin", result.subject()); - assertEquals("ui", result.group()); + assertEquals("user:admin", result.subject()); + assertEquals("user", result.group()); assertEquals(roles, result.roles()); } diff --git a/cameleer3-server-core/src/main/java/com/cameleer3/server/core/security/JwtService.java b/cameleer3-server-core/src/main/java/com/cameleer3/server/core/security/JwtService.java index c3afda2a..f3a31f78 100644 --- a/cameleer3-server-core/src/main/java/com/cameleer3/server/core/security/JwtService.java +++ b/cameleer3-server-core/src/main/java/com/cameleer3/server/core/security/JwtService.java @@ -14,7 +14,7 @@ public interface JwtService { /** * Validated JWT payload. * - * @param subject the {@code sub} claim (agent ID or {@code ui:}) + * @param subject the {@code sub} claim (agent ID or {@code user:}) * @param group the {@code group} claim * @param roles the {@code roles} claim (e.g. {@code ["AGENT"]}, {@code ["ADMIN"]}) */ diff --git a/cameleer3-server-core/src/main/java/com/cameleer3/server/core/security/UserInfo.java b/cameleer3-server-core/src/main/java/com/cameleer3/server/core/security/UserInfo.java index ffabd508..2af614e9 100644 --- a/cameleer3-server-core/src/main/java/com/cameleer3/server/core/security/UserInfo.java +++ b/cameleer3-server-core/src/main/java/com/cameleer3/server/core/security/UserInfo.java @@ -6,7 +6,7 @@ import java.util.List; /** * Represents a persisted user in the system. * - * @param userId unique identifier (e.g. OIDC {@code sub} or {@code ui:}) + * @param userId unique identifier (e.g. OIDC {@code sub} or {@code user:}) * @param provider authentication provider ({@code "local"}, {@code "oidc:"}) * @param email user email (may be empty) * @param displayName display name (may be empty)