From 8ec27dca42bdd877be6989797ff3ae7529326ada Mon Sep 17 00:00:00 2001 From: Roman Strobl Date: Thu, 19 Jun 2025 21:28:33 +0200 Subject: [PATCH] Fix #581: Dynamic factor keys for crypto4 --- .../exception/PowerAuthBiometryException.java | 55 +++++++++ .../exception/PowerAuthPasswordException.java | 55 +++++++++ .../controller/v4/BiometryController.java | 87 +++++++++++++ .../controller/v4/PasswordController.java | 72 +++++++++++ .../exception/PowerAuthExceptionHandler.java | 24 ++++ .../spring/service/v4/BiometryService.java | 116 ++++++++++++++++++ .../spring/service/v4/KeyStoreService.java | 6 +- .../spring/service/v4/PasswordService.java | 92 ++++++++++++++ .../api/spring/util/PowerAuthVersionUtil.java | 15 +++ 9 files changed, 518 insertions(+), 4 deletions(-) create mode 100644 powerauth-restful-security-spring-annotation/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthBiometryException.java create mode 100644 powerauth-restful-security-spring-annotation/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthPasswordException.java create mode 100644 powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/controller/v4/BiometryController.java create mode 100644 powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/controller/v4/PasswordController.java create mode 100644 powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/BiometryService.java create mode 100644 powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/PasswordService.java diff --git a/powerauth-restful-security-spring-annotation/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthBiometryException.java b/powerauth-restful-security-spring-annotation/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthBiometryException.java new file mode 100644 index 00000000..dd86df8c --- /dev/null +++ b/powerauth-restful-security-spring-annotation/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthBiometryException.java @@ -0,0 +1,55 @@ +/* + * PowerAuth integration libraries for RESTful API applications, examples and + * related software components + * + * Copyright (C) 2025 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.rest.api.spring.exception; + +/** + * Exception raised in case PowerAuth fails to set up the biometry. + * + * @author Roman Strobl, roman.strobl@wultra.com + */ +public class PowerAuthBiometryException extends Exception { + + private static final String DEFAULT_CODE = "ERR_BIOMETRY"; + private static final String DEFAULT_ERROR = "POWER_AUTH_BIOMETRY_FAILURE"; + + /** + * Default constructor. + */ + public PowerAuthBiometryException() { + super(DEFAULT_ERROR); + } + + /** + * Get the default error code, used for example in REST response. + * @return Default error code. + */ + public String getDefaultCode() { + return DEFAULT_CODE; + } + + /** + * Get default error message, used for example in the REST response. + * @return Default error message. + */ + public String getDefaultError() { + return DEFAULT_ERROR; + } + +} diff --git a/powerauth-restful-security-spring-annotation/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthPasswordException.java b/powerauth-restful-security-spring-annotation/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthPasswordException.java new file mode 100644 index 00000000..caa24b68 --- /dev/null +++ b/powerauth-restful-security-spring-annotation/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthPasswordException.java @@ -0,0 +1,55 @@ +/* + * PowerAuth integration libraries for RESTful API applications, examples and + * related software components + * + * Copyright (C) 2025 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.rest.api.spring.exception; + +/** + * Exception raised in case PowerAuth fails to change the password. + * + * @author Roman Strobl, roman.strobl@wultra.com + */ +public class PowerAuthPasswordException extends Exception { + + private static final String DEFAULT_CODE = "ERR_PASSWORD_CHANGE"; + private static final String DEFAULT_ERROR = "POWER_AUTH_PASSWORD_CHANGE_FAILURE"; + + /** + * Default constructor. + */ + public PowerAuthPasswordException() { + super(DEFAULT_ERROR); + } + + /** + * Get the default error code, used for example in REST response. + * @return Default error code. + */ + public String getDefaultCode() { + return DEFAULT_CODE; + } + + /** + * Get default error message, used for example in the REST response. + * @return Default error message. + */ + public String getDefaultError() { + return DEFAULT_ERROR; + } + +} diff --git a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/controller/v4/BiometryController.java b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/controller/v4/BiometryController.java new file mode 100644 index 00000000..ac15147b --- /dev/null +++ b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/controller/v4/BiometryController.java @@ -0,0 +1,87 @@ +/* + * PowerAuth integration libraries for RESTful API applications, examples and + * related software components + * + * Copyright (C) 2018 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.rest.api.spring.controller.v4; + +import com.wultra.core.rest.model.base.response.Response; +import com.wultra.security.powerauth.crypto.lib.enums.PowerAuthCodeType; +import com.wultra.security.powerauth.crypto.lib.v4.encryptor.model.request.AeadEncryptedRequest; +import com.wultra.security.powerauth.crypto.lib.v4.encryptor.model.response.AeadEncryptedResponse; +import com.wultra.security.powerauth.rest.api.spring.annotation.PowerAuth; +import com.wultra.security.powerauth.rest.api.spring.authentication.PowerAuthApiAuthentication; +import com.wultra.security.powerauth.rest.api.spring.exception.PowerAuthAuthenticationException; +import com.wultra.security.powerauth.rest.api.spring.exception.PowerAuthBiometryException; +import com.wultra.security.powerauth.rest.api.spring.service.v4.BiometryService; +import com.wultra.security.powerauth.rest.api.spring.util.PowerAuthAuthenticationUtil; +import com.wultra.security.powerauth.rest.api.spring.util.PowerAuthVersionUtil; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Controller for biometry setup. + * + *

PowerAuth protocol versions: + *

    + *
  • 4.0
  • + *
+ * + * @author Roman Strobl, roman.strobl@wultra.com + * + */ +@RestController("biometryControllerV4") +@RequestMapping("/pa/v4/biometry") +@AllArgsConstructor +public class BiometryController { + + private final BiometryService biometryService; + + /** + * Set up biometry. + * @param request Encrypted request. + * @param auth Automatically injected PowerAuth authentication object. + * @return Encrypted response. + * @throws PowerAuthAuthenticationException In case any error occurs, including authentication code validation errors. + */ + @PostMapping(value = "add") + @PowerAuth(resourceId = "/pa/biometry/add", authenticationCodeType = PowerAuthCodeType.POSSESSION_KNOWLEDGE) + public AeadEncryptedResponse addBiometry(@RequestBody AeadEncryptedRequest request, PowerAuthApiAuthentication auth) throws PowerAuthAuthenticationException, PowerAuthBiometryException { + PowerAuthAuthenticationUtil.checkAuthentication(auth); + PowerAuthVersionUtil.checkUnsupportedVersion(auth.getVersion()); + PowerAuthVersionUtil.checkEncryptionParameters(auth.getVersion(), request); + return biometryService.addBiometry(request, auth); + } + + /** + * Remove biometry. + * @param auth Automatically injected PowerAuth authentication object. + * @return Response. + * @throws PowerAuthAuthenticationException In case any error occurs, including authentication code validation errors. + */ + @PostMapping(value = "remove") + @PowerAuth(resourceId = "/pa/biometry/remove", authenticationCodeType = PowerAuthCodeType.POSSESSION) + public Response removeBiometry(PowerAuthApiAuthentication auth) throws PowerAuthAuthenticationException, PowerAuthBiometryException { + PowerAuthAuthenticationUtil.checkAuthentication(auth); + PowerAuthVersionUtil.checkUnsupportedVersion(auth.getVersion()); + return biometryService.removeBiometry(auth.getActivationContext().getActivationId()); + } + +} diff --git a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/controller/v4/PasswordController.java b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/controller/v4/PasswordController.java new file mode 100644 index 00000000..5466b89b --- /dev/null +++ b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/controller/v4/PasswordController.java @@ -0,0 +1,72 @@ +/* + * PowerAuth integration libraries for RESTful API applications, examples and + * related software components + * + * Copyright (C) 2018 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.rest.api.spring.controller.v4; + +import com.wultra.security.powerauth.crypto.lib.enums.PowerAuthCodeType; +import com.wultra.security.powerauth.crypto.lib.v4.encryptor.model.request.AeadEncryptedRequest; +import com.wultra.security.powerauth.crypto.lib.v4.encryptor.model.response.AeadEncryptedResponse; +import com.wultra.security.powerauth.rest.api.spring.annotation.PowerAuth; +import com.wultra.security.powerauth.rest.api.spring.authentication.PowerAuthApiAuthentication; +import com.wultra.security.powerauth.rest.api.spring.exception.PowerAuthAuthenticationException; +import com.wultra.security.powerauth.rest.api.spring.exception.PowerAuthPasswordException; +import com.wultra.security.powerauth.rest.api.spring.service.v4.PasswordService; +import com.wultra.security.powerauth.rest.api.spring.util.PowerAuthAuthenticationUtil; +import com.wultra.security.powerauth.rest.api.spring.util.PowerAuthVersionUtil; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Controller for password change. + * + *

PowerAuth protocol versions: + *

    + *
  • 4.0
  • + *
+ * + * @author Roman Strobl, roman.strobl@wultra.com + * + */ +@RestController("passwordControllerV4") +@RequestMapping("/pa/v4/password") +@AllArgsConstructor +public class PasswordController { + + private final PasswordService passwordService; + + /** + * Change the password. + * @param request Encrypted request. + * @param auth Automatically injected PowerAuth authentication object. + * @return Encrypted response. + * @throws PowerAuthAuthenticationException In case any error occurs, including authentication code validation errors. + */ + @PostMapping(value = "change") + @PowerAuth(resourceId = "/pa/password/change", authenticationCodeType = PowerAuthCodeType.POSSESSION_KNOWLEDGE) + public AeadEncryptedResponse changePassword(@RequestBody AeadEncryptedRequest request, PowerAuthApiAuthentication auth) throws PowerAuthAuthenticationException, PowerAuthPasswordException { + PowerAuthAuthenticationUtil.checkAuthentication(auth); + PowerAuthVersionUtil.checkUnsupportedVersion(auth.getVersion()); + PowerAuthVersionUtil.checkEncryptionParameters(auth.getVersion(), request); + return passwordService.changePassword(request, auth); + } + +} diff --git a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthExceptionHandler.java b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthExceptionHandler.java index f6257c50..73afbb11 100644 --- a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthExceptionHandler.java +++ b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/exception/PowerAuthExceptionHandler.java @@ -130,4 +130,28 @@ public class PowerAuthExceptionHandler { return new ErrorResponse(ex.getDefaultCode(), ex.getDefaultError()); } + /** + * Handle PowerAuthPasswordException exceptions. + * @param ex Exception instance. + * @return Error response. + */ + @ExceptionHandler(value = PowerAuthPasswordException.class) + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + public @ResponseBody ErrorResponse handlePowerAuthPasswordException(PowerAuthPasswordException ex) { + logger.warn(ex.getMessage(), ex); + return new ErrorResponse(ex.getDefaultCode(), ex.getDefaultError()); + } + + /** + * Handle PowerAuthBiometryException exceptions. + * @param ex Exception instance. + * @return Error response. + */ + @ExceptionHandler(value = PowerAuthBiometryException.class) + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + public @ResponseBody ErrorResponse handlePowerAuthBiometryException(PowerAuthBiometryException ex) { + logger.warn(ex.getMessage(), ex); + return new ErrorResponse(ex.getDefaultCode(), ex.getDefaultError()); + } + } diff --git a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/BiometryService.java b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/BiometryService.java new file mode 100644 index 00000000..680f93b1 --- /dev/null +++ b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/BiometryService.java @@ -0,0 +1,116 @@ +/* + * PowerAuth integration libraries for RESTful API applications, examples and + * related software components + * + * Copyright (C) 2025 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.rest.api.spring.service.v4; + +import com.wultra.core.rest.model.base.response.Response; +import com.wultra.security.powerauth.client.model.error.PowerAuthClientException; +import com.wultra.security.powerauth.client.model.request.v4.AddBiometryRequest; +import com.wultra.security.powerauth.client.model.request.v4.RemoveBiometryRequest; +import com.wultra.security.powerauth.client.model.response.v4.AddBiometryResponse; +import com.wultra.security.powerauth.client.v4.PowerAuthClient; +import com.wultra.security.powerauth.crypto.lib.v4.encryptor.model.request.AeadEncryptedRequest; +import com.wultra.security.powerauth.crypto.lib.v4.encryptor.model.response.AeadEncryptedResponse; +import com.wultra.security.powerauth.http.PowerAuthAuthorizationHttpHeader; +import com.wultra.security.powerauth.rest.api.spring.authentication.PowerAuthApiAuthentication; +import com.wultra.security.powerauth.rest.api.spring.exception.PowerAuthBiometryException; +import com.wultra.security.powerauth.rest.api.spring.service.HttpCustomizationService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * Service for setting up biometry. + * + * @author Roman Strobl, roman.strobl@wultra.com + */ +@Service("biometryServiceV4") +@AllArgsConstructor +@Slf4j +public class BiometryService { + + private final PowerAuthClient powerAuthClient; + private final HttpCustomizationService httpCustomizationService; + + /** + * Set up biometry. + * @param request Encrypted request. + * @param auth PowerAuth API authentication. + * @return Encrypted response. + * @throws PowerAuthBiometryException In case internal API call fails. + */ + public AeadEncryptedResponse addBiometry(AeadEncryptedRequest request, PowerAuthApiAuthentication auth) throws PowerAuthBiometryException { + try { + final String activationId = auth.getActivationContext().getActivationId(); + final PowerAuthAuthorizationHttpHeader httpHeader = (PowerAuthAuthorizationHttpHeader) auth.getHttpHeader(); + final String applicationKey = httpHeader.getApplicationKey(); + final String protocolVersion = httpHeader.getVersion(); + final AddBiometryRequest addBiometryRequest = convertAddBiometryRequest(request, activationId, applicationKey, protocolVersion); + final AddBiometryResponse addBiometryResponse = powerAuthClient.addBiometry( + addBiometryRequest, + httpCustomizationService.getQueryParams(), + httpCustomizationService.getHttpHeaders() + ); + + final AeadEncryptedResponse response = new AeadEncryptedResponse(); + response.setEncryptedData(addBiometryResponse.getEncryptedData()); + response.setTimestamp(addBiometryResponse.getTimestamp()); + return response; + } catch (PowerAuthClientException ex) { + logger.warn("PowerAuth biometry setup failed, error: {}", ex.getMessage()); + logger.debug(ex.getMessage(), ex); + throw new PowerAuthBiometryException(); + } + } + + /** + * Remove biometry. + * @param activationId Activation identifier. + * @return Shared secret response. + * @throws PowerAuthBiometryException In case internal API call fails. + */ + public Response removeBiometry(String activationId) throws PowerAuthBiometryException { + try { + final RemoveBiometryRequest removeBiometryRequest = new RemoveBiometryRequest(); + removeBiometryRequest.setActivationId(activationId); + return powerAuthClient.removeBiometry( + removeBiometryRequest, + httpCustomizationService.getQueryParams(), + httpCustomizationService.getHttpHeaders() + ); + } catch (PowerAuthClientException ex) { + logger.warn("PowerAuth biometry remove failed, error: {}", ex.getMessage()); + logger.debug(ex.getMessage(), ex); + throw new PowerAuthBiometryException(); + } + } + + private static AddBiometryRequest convertAddBiometryRequest(AeadEncryptedRequest request, String activationId, String applicationKey, String protocolVersion) { + final AddBiometryRequest addBiometryRequest = new AddBiometryRequest(); + addBiometryRequest.setActivationId(activationId); + addBiometryRequest.setApplicationKey(applicationKey); + addBiometryRequest.setTemporaryKeyId(request.getTemporaryKeyId()); + addBiometryRequest.setNonce(request.getNonce()); + addBiometryRequest.setEncryptedData(request.getEncryptedData()); + addBiometryRequest.setProtocolVersion(protocolVersion); + addBiometryRequest.setTimestamp(request.getTimestamp()); + return addBiometryRequest; + } + +} diff --git a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/KeyStoreService.java b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/KeyStoreService.java index a1a81706..dd6d6294 100644 --- a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/KeyStoreService.java +++ b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/KeyStoreService.java @@ -27,8 +27,7 @@ import com.wultra.security.powerauth.rest.api.model.response.TemporaryKeyResponse; import com.wultra.security.powerauth.rest.api.spring.exception.PowerAuthTemporaryKeyException; import com.wultra.security.powerauth.rest.api.spring.service.HttpCustomizationService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -38,10 +37,9 @@ * @author Roman Strobl, roman.strobl@wultra.com */ @Service("keyStoreServiceV4") +@Slf4j public class KeyStoreService { - private static final Logger logger = LoggerFactory.getLogger(KeyStoreService.class); - private final PowerAuthClient powerAuthClient; private final HttpCustomizationService httpCustomizationService; diff --git a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/PasswordService.java b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/PasswordService.java new file mode 100644 index 00000000..5ba8ac37 --- /dev/null +++ b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/service/v4/PasswordService.java @@ -0,0 +1,92 @@ +/* + * PowerAuth integration libraries for RESTful API applications, examples and + * related software components + * + * Copyright (C) 2025 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package com.wultra.security.powerauth.rest.api.spring.service.v4; + +import com.wultra.security.powerauth.client.model.error.PowerAuthClientException; +import com.wultra.security.powerauth.client.model.request.v4.ChangePasswordRequest; +import com.wultra.security.powerauth.client.model.response.v4.ChangePasswordResponse; +import com.wultra.security.powerauth.client.v4.PowerAuthClient; +import com.wultra.security.powerauth.crypto.lib.v4.encryptor.model.request.AeadEncryptedRequest; +import com.wultra.security.powerauth.crypto.lib.v4.encryptor.model.response.AeadEncryptedResponse; +import com.wultra.security.powerauth.http.PowerAuthAuthorizationHttpHeader; +import com.wultra.security.powerauth.rest.api.spring.authentication.PowerAuthApiAuthentication; +import com.wultra.security.powerauth.rest.api.spring.exception.PowerAuthPasswordException; +import com.wultra.security.powerauth.rest.api.spring.service.HttpCustomizationService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * Service for changing password for the knowledge factor. + * + * @author Roman Strobl, roman.strobl@wultra.com + */ +@Service("passwordServiceV4") +@AllArgsConstructor +@Slf4j +public class PasswordService { + + private final PowerAuthClient powerAuthClient; + private final HttpCustomizationService httpCustomizationService; + + /** + * Change the password. + * @param request Encrypted request. + * @param auth PowerAuth API authentication. + * @return Encrypted response. + * @throws PowerAuthPasswordException In case internal API call fails. + */ + public AeadEncryptedResponse changePassword(AeadEncryptedRequest request, PowerAuthApiAuthentication auth) throws PowerAuthPasswordException { + try { + final String activationId = auth.getActivationContext().getActivationId(); + final PowerAuthAuthorizationHttpHeader httpHeader = (PowerAuthAuthorizationHttpHeader) auth.getHttpHeader(); + final String applicationKey = httpHeader.getApplicationKey(); + final String protocolVersion = httpHeader.getVersion(); + final ChangePasswordRequest changePasswordRequest = convertChangePasswordRequest(request, activationId, applicationKey, protocolVersion); + final ChangePasswordResponse changePasswordResponse = powerAuthClient.changePassword( + changePasswordRequest, + httpCustomizationService.getQueryParams(), + httpCustomizationService.getHttpHeaders() + ); + + final AeadEncryptedResponse response = new AeadEncryptedResponse(); + response.setEncryptedData(changePasswordResponse.getEncryptedData()); + response.setTimestamp(changePasswordResponse.getTimestamp()); + return response; + } catch (PowerAuthClientException ex) { + logger.warn("PowerAuth changing password failed, error: {}", ex.getMessage()); + logger.debug(ex.getMessage(), ex); + throw new PowerAuthPasswordException(); + } + } + + private static ChangePasswordRequest convertChangePasswordRequest(AeadEncryptedRequest request, String activationId, String applicationKey, String protocolVersion) { + final ChangePasswordRequest changePasswordRequest = new ChangePasswordRequest(); + changePasswordRequest.setActivationId(activationId); + changePasswordRequest.setApplicationKey(applicationKey); + changePasswordRequest.setTemporaryKeyId(request.getTemporaryKeyId()); + changePasswordRequest.setNonce(request.getNonce()); + changePasswordRequest.setEncryptedData(request.getEncryptedData()); + changePasswordRequest.setProtocolVersion(protocolVersion); + changePasswordRequest.setTimestamp(request.getTimestamp()); + return changePasswordRequest; + } + +} diff --git a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/util/PowerAuthVersionUtil.java b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/util/PowerAuthVersionUtil.java index c8ec8857..bf3aeccc 100644 --- a/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/util/PowerAuthVersionUtil.java +++ b/powerauth-restful-security-spring/src/main/java/com/wultra/security/powerauth/rest/api/spring/util/PowerAuthVersionUtil.java @@ -20,6 +20,7 @@ package com.wultra.security.powerauth.rest.api.spring.util; import com.wultra.security.powerauth.crypto.lib.encryptor.model.v3.EciesEncryptedRequest; +import com.wultra.security.powerauth.crypto.lib.v4.encryptor.model.request.AeadEncryptedRequest; import com.wultra.security.powerauth.rest.api.spring.exception.authentication.PowerAuthInvalidRequestException; import lombok.extern.slf4j.Slf4j; @@ -153,6 +154,20 @@ public static void checkEncryptionParameters(String version, EciesEncryptedReque checkMissingRequiredTemporaryKeyId(version, request.getTemporaryKeyId()); } + /** + * Checks if required encryption parameters are missing for the provided PowerAuth protocol version. + * Throws an exception if the required parameter is missing. + * + * @param version Version string to be checked. + * @param request Request to be verified. + * @throws PowerAuthInvalidRequestException If timestamp is required and missing. + */ + public static void checkEncryptionParameters(String version, AeadEncryptedRequest request) throws PowerAuthInvalidRequestException { + checkMissingRequiredNonce(version, request.getNonce()); + checkMissingRequiredTimestamp(version, request.getTimestamp()); + checkMissingRequiredTemporaryKeyId(version, request.getTemporaryKeyId()); + } + /** * Checks if the provided PowerAuth protocol version is unsupported. *