feat: disable local auth when OIDC is configured (resource server mode)
- UiAuthController.login returns 404 when OIDC issuer is configured - JwtAuthenticationFilter skips internal user tokens in OIDC mode (agents still work) - UserAdminController.createUser and resetPassword return 400 in OIDC mode Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.cameleer3.server.app.security.SecurityProperties;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -47,12 +48,15 @@ public class UserAdminController {
|
||||
private final RbacService rbacService;
|
||||
private final UserRepository userRepository;
|
||||
private final AuditService auditService;
|
||||
private final boolean oidcEnabled;
|
||||
|
||||
public UserAdminController(RbacService rbacService, UserRepository userRepository,
|
||||
AuditService auditService) {
|
||||
AuditService auditService, SecurityProperties securityProperties) {
|
||||
this.rbacService = rbacService;
|
||||
this.userRepository = userRepository;
|
||||
this.auditService = auditService;
|
||||
String issuer = securityProperties.getOidcIssuerUri();
|
||||
this.oidcEnabled = issuer != null && !issuer.isBlank();
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@@ -78,8 +82,12 @@ public class UserAdminController {
|
||||
@PostMapping
|
||||
@Operation(summary = "Create a local user")
|
||||
@ApiResponse(responseCode = "200", description = "User created")
|
||||
@ApiResponse(responseCode = "400", description = "Disabled in OIDC mode")
|
||||
public ResponseEntity<UserDetail> createUser(@RequestBody CreateUserRequest request,
|
||||
HttpServletRequest httpRequest) {
|
||||
if (oidcEnabled) {
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
String userId = "user:" + request.username();
|
||||
UserInfo user = new UserInfo(userId, "local",
|
||||
request.email() != null ? request.email() : "",
|
||||
@@ -178,10 +186,14 @@ public class UserAdminController {
|
||||
@PostMapping("/{userId}/password")
|
||||
@Operation(summary = "Reset user password")
|
||||
@ApiResponse(responseCode = "204", description = "Password reset")
|
||||
@ApiResponse(responseCode = "400", description = "Disabled in OIDC mode")
|
||||
public ResponseEntity<Void> resetPassword(
|
||||
@PathVariable String userId,
|
||||
@Valid @RequestBody SetPasswordRequest request,
|
||||
HttpServletRequest httpRequest) {
|
||||
if (oidcEnabled) {
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
userRepository.setPassword(userId, passwordEncoder.encode(request.password()));
|
||||
auditService.log("reset_password", AuditCategory.USER_MGMT, userId, null, AuditResult.SUCCESS, httpRequest);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -74,6 +74,12 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
JwtValidationResult result = jwtService.validateAccessToken(token);
|
||||
String subject = result.subject();
|
||||
|
||||
// In OIDC mode, only accept agent tokens via internal validation.
|
||||
// User tokens must go through the OIDC decoder path.
|
||||
if (oidcDecoder != null && subject != null && subject.startsWith("user:")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<String> roles = result.roles();
|
||||
if (!subject.startsWith("user:") && roles.isEmpty()) {
|
||||
roles = List.of("AGENT");
|
||||
|
||||
@@ -71,6 +71,10 @@ public class UiAuthController {
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||
public ResponseEntity<AuthTokenResponse> login(@RequestBody LoginRequest request,
|
||||
HttpServletRequest httpRequest) {
|
||||
if (isOidcEnabled()) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body(new AuthTokenResponse(null, null, "Local login disabled when OIDC is configured", null));
|
||||
}
|
||||
String configuredUser = properties.getUiUser();
|
||||
String configuredPassword = properties.getUiPassword();
|
||||
String subject = "user:" + request.username();
|
||||
@@ -149,6 +153,11 @@ public class UiAuthController {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOidcEnabled() {
|
||||
String issuer = properties.getOidcIssuerUri();
|
||||
return issuer != null && !issuer.isBlank();
|
||||
}
|
||||
|
||||
public record LoginRequest(String username, String password) {}
|
||||
public record RefreshRequest(String refreshToken) {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user