use of io.getlime.security.powerauth.rest.api.spring.exception.authentication.PowerAuthInvalidRequestException in project powerauth-restful-integration by lime-company.
the class ActivationService method createActivation.
/**
* Create activation.
*
* @param request Create activation layer 1 request.
* @param eciesContext PowerAuth ECIES encryption context.
* @return Create activation layer 1 response.
* @throws PowerAuthActivationException In case create activation fails.
* @throws PowerAuthRecoveryException In case activation recovery fails.
*/
public ActivationLayer1Response createActivation(ActivationLayer1Request request, EciesEncryptionContext eciesContext) throws PowerAuthActivationException, PowerAuthRecoveryException {
try {
final String applicationKey = eciesContext.getApplicationKey();
final EciesEncryptedRequest activationData = request.getActivationData();
final String ephemeralPublicKey = activationData.getEphemeralPublicKey();
final String encryptedData = activationData.getEncryptedData();
final String mac = activationData.getMac();
final String nonce = activationData.getNonce();
final Map<String, String> identity = request.getIdentityAttributes();
final Map<String, Object> customAttributes = (request.getCustomAttributes() != null) ? request.getCustomAttributes() : new HashMap<>();
// Validate inner encryption
if (nonce == null && !"3.0".equals(eciesContext.getVersion())) {
logger.warn("Missing nonce for protocol version: {}", eciesContext.getVersion());
throw new PowerAuthActivationException();
}
switch(request.getType()) {
// Regular activation which uses "code" identity attribute
case CODE:
{
// Check if identity attributes are present
if (identity == null || identity.isEmpty()) {
logger.warn("Identity attributes are missing for code activation");
throw new PowerAuthActivationException();
}
// Extract data from request and encryption object
final String activationCode = identity.get("code");
if (activationCode == null || activationCode.isEmpty()) {
logger.warn("Activation code is missing");
throw new PowerAuthActivationException();
}
// Call PrepareActivation method on PA server
final PrepareActivationResponse response = powerAuthClient.prepareActivation(activationCode, applicationKey, ephemeralPublicKey, encryptedData, mac, nonce);
// Create context for passing parameters between activation provider calls
final Map<String, Object> context = new LinkedHashMap<>();
Map<String, Object> processedCustomAttributes = customAttributes;
// In case a custom activation provider is enabled, process custom attributes and save any flags
if (activationProvider != null) {
processedCustomAttributes = activationProvider.processCustomActivationAttributes(customAttributes, response.getActivationId(), response.getUserId(), response.getApplicationId(), ActivationType.CODE, context);
List<String> activationFlags = activationProvider.getActivationFlags(identity, processedCustomAttributes, response.getActivationId(), response.getUserId(), response.getApplicationId(), ActivationType.CODE, context);
if (activationFlags != null && !activationFlags.isEmpty()) {
powerAuthClient.addActivationFlags(response.getActivationId(), activationFlags);
}
}
boolean notifyActivationCommit = false;
if (response.getActivationStatus() == ActivationStatus.ACTIVE) {
// Activation was committed instantly due to presence of Activation OTP.
notifyActivationCommit = true;
} else {
// Otherwise check if activation should be committed instantly and if yes, perform commit.
if (activationProvider != null && activationProvider.shouldAutoCommitActivation(identity, customAttributes, response.getActivationId(), response.getUserId(), response.getApplicationId(), ActivationType.CODE, context)) {
CommitActivationResponse commitResponse = powerAuthClient.commitActivation(response.getActivationId(), null);
notifyActivationCommit = commitResponse.isActivated();
}
}
// Notify activation provider about an activation commit.
if (activationProvider != null && notifyActivationCommit) {
activationProvider.activationWasCommitted(identity, customAttributes, response.getActivationId(), response.getUserId(), response.getApplicationId(), ActivationType.CODE, context);
}
// Prepare and return encrypted response
return prepareEncryptedResponse(response.getEncryptedData(), response.getMac(), processedCustomAttributes);
}
// Custom activation
case CUSTOM:
{
// Check if there is a custom activation provider available, return an error in case it is not available
if (activationProvider == null) {
logger.warn("Activation provider is not available");
throw new PowerAuthActivationException();
}
// Check if identity attributes are present
if (identity == null || identity.isEmpty()) {
logger.warn("Identity attributes are missing for custom activation");
throw new PowerAuthActivationException();
}
// Create context for passing parameters between activation provider calls
final Map<String, Object> context = new LinkedHashMap<>();
// Lookup user ID using a provided identity attributes
final String userId = activationProvider.lookupUserIdForAttributes(identity, context);
// If no user was found or user ID is invalid, return an error
if (userId == null || userId.equals("") || userId.length() > 255) {
logger.warn("Invalid user ID: {}", userId);
throw new PowerAuthActivationException();
}
// Resolve maxFailedCount and activationExpireTimestamp parameters, null value means use value configured on PowerAuth server
final Integer maxFailed = activationProvider.getMaxFailedAttemptCount(identity, customAttributes, userId, ActivationType.CUSTOM, context);
final Long maxFailedCount = maxFailed == null ? null : maxFailed.longValue();
final Long activationValidityPeriod = activationProvider.getValidityPeriodDuringActivation(identity, customAttributes, userId, ActivationType.CUSTOM, context);
Date activationExpireTimestamp = null;
if (activationValidityPeriod != null) {
Instant now = Instant.now();
Instant expiration = now.plusMillis(activationValidityPeriod);
activationExpireTimestamp = Date.from(expiration);
}
// Create activation for a looked up user and application related to the given application key
final CreateActivationResponse response = powerAuthClient.createActivation(userId, activationExpireTimestamp, maxFailedCount, applicationKey, ephemeralPublicKey, encryptedData, mac, nonce);
// Process custom attributes using a custom logic
final Map<String, Object> processedCustomAttributes = activationProvider.processCustomActivationAttributes(customAttributes, response.getActivationId(), userId, response.getApplicationId(), ActivationType.CUSTOM, context);
// Save activation flags in case the provider specified any flags
final List<String> activationFlags = activationProvider.getActivationFlags(identity, processedCustomAttributes, response.getActivationId(), userId, response.getApplicationId(), ActivationType.CUSTOM, context);
if (activationFlags != null && !activationFlags.isEmpty()) {
powerAuthClient.addActivationFlags(response.getActivationId(), activationFlags);
}
// Check if activation should be committed instantly and if yes, perform commit
if (activationProvider.shouldAutoCommitActivation(identity, customAttributes, response.getActivationId(), userId, response.getApplicationId(), ActivationType.CUSTOM, context)) {
final CommitActivationResponse commitResponse = powerAuthClient.commitActivation(response.getActivationId(), null);
if (commitResponse.isActivated()) {
activationProvider.activationWasCommitted(identity, customAttributes, response.getActivationId(), userId, response.getApplicationId(), ActivationType.CUSTOM, context);
}
}
// Prepare encrypted activation data
final EciesEncryptedResponse encryptedActivationData = new EciesEncryptedResponse(response.getEncryptedData(), response.getMac());
// Prepare the created activation response data
final ActivationLayer1Response responseL1 = new ActivationLayer1Response();
responseL1.setCustomAttributes(processedCustomAttributes);
responseL1.setActivationData(encryptedActivationData);
// Return response
return responseL1;
}
// Activation using recovery code
case RECOVERY:
{
// Check if identity attributes are present
if (identity == null || identity.isEmpty()) {
logger.warn("Identity attributes are missing for activation recovery");
throw new PowerAuthActivationException();
}
// Extract data from request and encryption object
final String recoveryCode = identity.get("recoveryCode");
final String recoveryPuk = identity.get("puk");
if (recoveryCode == null || recoveryCode.isEmpty()) {
logger.warn("Recovery code is missing");
throw new PowerAuthActivationException();
}
if (recoveryPuk == null || recoveryPuk.isEmpty()) {
logger.warn("Recovery PUK is missing");
throw new PowerAuthActivationException();
}
// Create context for passing parameters between activation provider calls
final Map<String, Object> context = new LinkedHashMap<>();
// Resolve maxFailedCount, user ID is not known
Long maxFailedCount = null;
if (activationProvider != null) {
final Integer maxFailed = activationProvider.getMaxFailedAttemptCount(identity, customAttributes, null, ActivationType.RECOVERY, context);
maxFailedCount = maxFailed == null ? null : maxFailed.longValue();
}
// Call RecoveryCodeActivation method on PA server
final RecoveryCodeActivationResponse response = powerAuthClient.createActivationUsingRecoveryCode(recoveryCode, recoveryPuk, applicationKey, maxFailedCount, ephemeralPublicKey, encryptedData, mac, nonce);
Map<String, Object> processedCustomAttributes = customAttributes;
// In case a custom activation provider is enabled, process custom attributes and save any flags
if (activationProvider != null) {
processedCustomAttributes = activationProvider.processCustomActivationAttributes(customAttributes, response.getActivationId(), response.getUserId(), response.getApplicationId(), ActivationType.RECOVERY, context);
final List<String> activationFlags = activationProvider.getActivationFlags(identity, processedCustomAttributes, response.getActivationId(), response.getUserId(), response.getApplicationId(), ActivationType.RECOVERY, context);
if (activationFlags != null && !activationFlags.isEmpty()) {
powerAuthClient.addActivationFlags(response.getActivationId(), activationFlags);
}
}
// Automatically commit activation by default, the optional activation provider can override automatic commit
if (activationProvider == null || activationProvider.shouldAutoCommitActivation(identity, customAttributes, response.getActivationId(), response.getUserId(), response.getApplicationId(), ActivationType.RECOVERY, context)) {
final CommitActivationResponse commitResponse = powerAuthClient.commitActivation(response.getActivationId(), null);
if (activationProvider != null && commitResponse.isActivated()) {
activationProvider.activationWasCommitted(identity, customAttributes, response.getActivationId(), response.getUserId(), response.getApplicationId(), ActivationType.RECOVERY, context);
}
}
// Prepare and return encrypted response
return prepareEncryptedResponse(response.getEncryptedData(), response.getMac(), processedCustomAttributes);
}
default:
logger.warn("Invalid activation request");
throw new PowerAuthInvalidRequestException();
}
} catch (PowerAuthClientException ex) {
if (ex.getPowerAuthError() instanceof PowerAuthErrorRecovery) {
final PowerAuthErrorRecovery errorRecovery = (PowerAuthErrorRecovery) ex.getPowerAuthError();
logger.debug("Invalid recovery code, current PUK index: {}", errorRecovery.getCurrentRecoveryPukIndex());
throw new PowerAuthRecoveryException(ex.getMessage(), "INVALID_RECOVERY_CODE", errorRecovery.getCurrentRecoveryPukIndex());
}
logger.warn("Creating PowerAuth activation failed, error: {}", ex.getMessage());
logger.debug(ex.getMessage(), ex);
throw new PowerAuthActivationException();
} catch (PowerAuthActivationException ex) {
// Do not swallow PowerAuthActivationException for custom activations.
// See: https://github.com/wultra/powerauth-restful-integration/issues/199
logger.warn("Creating PowerAuth activation failed, error: {}", ex.getMessage());
throw ex;
} catch (Exception ex) {
logger.warn("Creating PowerAuth activation failed, error: {}", ex.getMessage());
logger.debug(ex.getMessage(), ex);
throw new PowerAuthActivationException();
}
}
use of io.getlime.security.powerauth.rest.api.spring.exception.authentication.PowerAuthInvalidRequestException in project powerauth-restful-integration by lime-company.
the class UpgradeService method upgradeCommit.
/**
* Commit upgrade of activation to version 3.
* @param signatureHeader PowerAuth signature HTTP header.
* @param httpServletRequest HTTP servlet request.
* @return Commit upgrade response.
* @throws PowerAuthAuthenticationException in case authentication fails.
* @throws PowerAuthUpgradeException In case upgrade commit fails.
*/
public Response upgradeCommit(String signatureHeader, HttpServletRequest httpServletRequest) throws PowerAuthAuthenticationException, PowerAuthUpgradeException {
try {
// Extract request body
final byte[] requestBodyBytes = authenticationProvider.extractRequestBodyBytes(httpServletRequest);
if (requestBodyBytes == null || requestBodyBytes.length == 0) {
// Expected request body is {}, do not accept empty body
logger.warn("Empty request body");
throw new PowerAuthInvalidRequestException();
}
// Verify signature, force signature version during upgrade to version 3
final List<PowerAuthSignatureTypes> allowedSignatureTypes = Collections.singletonList(PowerAuthSignatureTypes.POSSESSION);
final PowerAuthApiAuthentication authentication = authenticationProvider.validateRequestSignatureWithActivationDetails("POST", requestBodyBytes, "/pa/upgrade/commit", signatureHeader, allowedSignatureTypes, 3);
// In case signature verification fails, upgrade fails, too
if (!authentication.getAuthenticationContext().isValid() || authentication.getActivationContext().getActivationId() == null) {
logger.debug("Signature validation failed");
throw new PowerAuthSignatureInvalidException();
}
// Get signature HTTP headers
final String activationId = authentication.getActivationContext().getActivationId();
final PowerAuthSignatureHttpHeader httpHeader = (PowerAuthSignatureHttpHeader) authentication.getHttpHeader();
final String applicationKey = httpHeader.getApplicationKey();
// Commit upgrade on PowerAuth server
final CommitUpgradeResponse upgradeResponse = powerAuthClient.commitUpgrade(activationId, applicationKey);
if (upgradeResponse.isCommitted()) {
return new Response();
} else {
logger.debug("Upgrade commit failed");
throw new PowerAuthUpgradeException();
}
} catch (PowerAuthAuthenticationException ex) {
throw ex;
} catch (Exception ex) {
logger.warn("PowerAuth upgrade commit failed, error: {}", ex.getMessage());
logger.debug(ex.getMessage(), ex);
throw new PowerAuthUpgradeException();
}
}
use of io.getlime.security.powerauth.rest.api.spring.exception.authentication.PowerAuthInvalidRequestException in project powerauth-restful-integration by lime-company.
the class ActivationController method removeActivation.
/**
* Remove activation.
* @param signatureHeader PowerAuth signature HTTP header.
* @return PowerAuth RESTful response with {@link ActivationRemoveResponse} payload.
* @throws PowerAuthActivationException In case activation access fails.
* @throws PowerAuthAuthenticationException In case the signature validation fails.
*/
@RequestMapping(value = "remove", method = RequestMethod.POST)
public ObjectResponse<ActivationRemoveResponse> removeActivation(@RequestHeader(value = PowerAuthSignatureHttpHeader.HEADER_NAME) String signatureHeader) throws PowerAuthActivationException, PowerAuthAuthenticationException {
// Request body needs to be set to null because the SDK uses null for the signature, although {} is sent as request body
PowerAuthApiAuthentication apiAuthentication = authenticationProvider.validateRequestSignature("POST", null, "/pa/activation/remove", signatureHeader);
if (apiAuthentication == null || apiAuthentication.getActivationContext().getActivationId() == null) {
logger.debug("Signature validation failed");
throw new PowerAuthSignatureInvalidException();
}
if (!"2.0".equals(apiAuthentication.getVersion()) && !"2.1".equals(apiAuthentication.getVersion())) {
logger.warn("Endpoint does not support PowerAuth protocol version {}", apiAuthentication.getVersion());
throw new PowerAuthInvalidRequestException();
}
ActivationRemoveResponse response = activationServiceV3.removeActivation(apiAuthentication);
return new ObjectResponse<>(response);
}
use of io.getlime.security.powerauth.rest.api.spring.exception.authentication.PowerAuthInvalidRequestException in project powerauth-restful-integration by lime-company.
the class ActivationController method removeActivation.
/**
* Remove activation.
* @param signatureHeader PowerAuth signature HTTP header.
* @param httpServletRequest HTTP servlet request.
* @return PowerAuth RESTful response with {@link ActivationRemoveResponse} payload.
* @throws PowerAuthActivationException In case activation access fails.
* @throws PowerAuthAuthenticationException In case the signature validation fails.
*/
@RequestMapping(value = "remove", method = RequestMethod.POST)
public ObjectResponse<ActivationRemoveResponse> removeActivation(@RequestHeader(value = PowerAuthSignatureHttpHeader.HEADER_NAME) String signatureHeader, HttpServletRequest httpServletRequest) throws PowerAuthActivationException, PowerAuthAuthenticationException {
byte[] requestBodyBytes = authenticationProvider.extractRequestBodyBytes(httpServletRequest);
PowerAuthApiAuthentication apiAuthentication = authenticationProvider.validateRequestSignature("POST", requestBodyBytes, "/pa/activation/remove", signatureHeader);
if (apiAuthentication == null || apiAuthentication.getActivationContext().getActivationId() == null) {
logger.debug("Signature validation failed");
throw new PowerAuthSignatureInvalidException();
}
if (!"3.0".equals(apiAuthentication.getVersion()) && !"3.1".equals(apiAuthentication.getVersion())) {
logger.warn("Endpoint does not support PowerAuth protocol version {}", apiAuthentication.getVersion());
throw new PowerAuthInvalidRequestException();
}
ActivationRemoveResponse response = activationServiceV3.removeActivation(apiAuthentication);
return new ObjectResponse<>(response);
}
use of io.getlime.security.powerauth.rest.api.spring.exception.authentication.PowerAuthInvalidRequestException in project powerauth-restful-integration by lime-company.
the class SecureVaultController method unlockVault.
/**
* Request the vault unlock key.
* @param signatureHeader PowerAuth signature HTTP header.
* @param request Vault unlock request data.
* @param httpServletRequest HTTP servlet request.
* @return PowerAuth RESTful response with {@link VaultUnlockResponse} payload.
* @throws PowerAuthAuthenticationException In case authentication fails.
* @throws PowerAuthSecureVaultException In case unlocking the vault fails.
*/
@RequestMapping(value = "unlock", method = RequestMethod.POST)
public ObjectResponse<VaultUnlockResponse> unlockVault(@RequestHeader(value = PowerAuthSignatureHttpHeader.HEADER_NAME, defaultValue = "unknown") String signatureHeader, @RequestBody(required = false) ObjectRequest<VaultUnlockRequest> request, HttpServletRequest httpServletRequest) throws PowerAuthAuthenticationException, PowerAuthSecureVaultException {
// Request object is not validated - it is optional for version 2
// Parse the header
PowerAuthSignatureHttpHeader header = new PowerAuthSignatureHttpHeader().fromValue(signatureHeader);
// Validate the header
try {
PowerAuthSignatureHttpHeaderValidator.validate(header);
} catch (InvalidPowerAuthHttpHeaderException ex) {
logger.warn("Signature HTTP header validation failed, error: {}", ex.getMessage());
logger.debug(ex.getMessage(), ex);
throw new PowerAuthSignatureInvalidException();
}
if (!"2.0".equals(header.getVersion()) && !"2.1".equals(header.getVersion())) {
logger.warn("Endpoint does not support PowerAuth protocol version {}", header.getVersion());
throw new PowerAuthInvalidRequestException();
}
VaultUnlockResponse response = secureVaultServiceV2.vaultUnlock(signatureHeader, request.getRequestObject(), httpServletRequest);
return new ObjectResponse<>(response);
}
Aggregations