From accc0d20404852035876cb7cb4ce5ce7b5da6e64 Mon Sep 17 00:00:00 2001 From: Boris Rizov Date: Tue, 20 Feb 2024 13:25:43 +0100 Subject: [PATCH] feat: use a spring validator for SecureTokenRequest --- .../controller/SecureTokenController.java | 8 +++ .../dto/SecureTokenRequest.java | 9 --- .../SecureTokenRequestValidator.java | 57 +++++++++++++++++++ 3 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/eclipse/tractusx/managedidentitywallets/validator/SecureTokenRequestValidator.java diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/SecureTokenController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/SecureTokenController.java index 27046921d..bd185228c 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/SecureTokenController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/SecureTokenController.java @@ -44,10 +44,13 @@ import org.eclipse.tractusx.managedidentitywallets.exception.InvalidIdpTokenResponseException; import org.eclipse.tractusx.managedidentitywallets.interfaces.SecureTokenService; import org.eclipse.tractusx.managedidentitywallets.service.IdpAuthorization; +import org.eclipse.tractusx.managedidentitywallets.validator.SecureTokenRequestValidator; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -67,6 +70,11 @@ public class SecureTokenController { private final WalletRepository walletRepo; + @InitBinder + void initBinder(WebDataBinder webDataBinder) { + webDataBinder.addValidators(new SecureTokenRequestValidator()); + } + @SneakyThrows @PostMapping(path = "/api/token", consumes = { MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE }) @SecureTokenControllerApiDoc.PostSecureTokenDoc diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/SecureTokenRequest.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/SecureTokenRequest.java index e09cc252a..5eb7c931d 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/SecureTokenRequest.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/SecureTokenRequest.java @@ -22,8 +22,6 @@ package org.eclipse.tractusx.managedidentitywallets.dto; import com.fasterxml.jackson.annotation.JsonProperty; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -36,21 +34,14 @@ @Getter @Setter public class SecureTokenRequest { - @NotBlank private String audience; - @NotBlank - @NotNull @JsonProperty("client_id") private String clientId; - @NotBlank - @NotNull @JsonProperty("client_secret") private String clientSecret; - @NotBlank - @NotNull @JsonProperty("grant_type") private String grantType; diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/validator/SecureTokenRequestValidator.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/validator/SecureTokenRequestValidator.java new file mode 100644 index 000000000..273b898a3 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/validator/SecureTokenRequestValidator.java @@ -0,0 +1,57 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ****************************************************************************** + */ + +package org.eclipse.tractusx.managedidentitywallets.validator; + +import org.eclipse.tractusx.managedidentitywallets.dto.SecureTokenRequest; +import org.springframework.validation.Errors; +import org.springframework.validation.ValidationUtils; +import org.springframework.validation.Validator; + +public class SecureTokenRequestValidator implements Validator { + @Override + public boolean supports(Class clazz) { + return SecureTokenRequest.class.equals(clazz); + } + + @Override + public void validate(Object target, Errors errors) { + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "audience", "audience.empty", "The 'audience' cannot be empty or missing."); + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "clientId", "client_id.empty", "The 'client_id' cannot be empty or missing."); + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "clientSecret", "client_secret.empty", "The 'client_secret' cannot be empty or missing."); + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "grantType", "grant_type.empty", "The 'grant_type' cannot be empty or missing."); + SecureTokenRequest secureTokenRequest = (SecureTokenRequest) target; + if (secureTokenRequest.getAccessToken() != null && secureTokenRequest.getBearerAccessScope() != null) { + errors.rejectValue("accessToken", "access_token.incompatible", "The 'access_token' and the 'bearer_access_token' cannot be set together."); + errors.rejectValue("bearerAccessScope", "bearer_access_scope.incompatible", "The 'access_token' and the 'bearer_access_token' cannot be set together."); + } + if (secureTokenRequest.getAccessToken() == null && secureTokenRequest.getBearerAccessScope() == null) { + errors.rejectValue("accessToken", "access_token.incompatible", "Both the 'access_token' and the 'bearer_access_scope' are missing. At least one must be set."); + errors.rejectValue("bearerAccessScope", "bearer_access_scope.incompatible", "Both the 'access_token' and the 'bearer_access_scope' are missing. At least one must be set."); + } + if (secureTokenRequest.getAccessToken() != null) { + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "accessToken", "access_token.empty", "The 'access_token' cannot be empty or missing."); + } + if (secureTokenRequest.getBearerAccessScope() != null) { + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "bearerAccessScope", "bearer_access_scope.empty", "The 'bearer_access_scope' cannot be empty or missing."); + } + } +}