Skip to content

Commit

Permalink
Merge pull request #120 from wultra/develop
Browse files Browse the repository at this point in the history
Prepare release 1.2.0
  • Loading branch information
romanstrobl authored Dec 28, 2021
2 parents 6ed3b21 + 5656c1e commit 394a7f8
Show file tree
Hide file tree
Showing 34 changed files with 845 additions and 205 deletions.
28 changes: 24 additions & 4 deletions docs/Deploying-Enrollment-Server.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,35 @@

This chapter explains how to deploy Enrollment Server.

<-- begin box warning -->
The enrollment server component will need to be customized in case you need to customize the activation process. The customization is described in the tutorial [Implementing the Server-Side for Authentication in Mobile Banking Apps (SCA)](https://developers.wultra.com/products/mobile-token/2021-05/tutorials/Authentication-in-Mobile-Apps/Server-Side-Tutorial#deploying-the-enrollment-server).
<-- end -->

## Downloading Enrollment Server

You can download the latest `enrollment-server.war` from the [Enrollment Server releases page](https://github.com/wultra/enrollment-server/releases).

## Configuring Enrollment Server

The default implementation of an Enrollment Server has only one compulsory configuration parameter `powerauth.service.url` that configures the SOAP endpoint location of a PowerAuth Server. The default value for this property points to `localhost`:
The default implementation of an Enrollment Server has only one compulsory configuration parameter `powerauth.service.url` that configures the REST service location of a PowerAuth Server. The default value for this property points to `localhost`:

```bash
powerauth.service.url=http://localhost:8080/powerauth-java-server/soap
powerauth.service.url=http://localhost:8080/powerauth-java-server/rest
```

## Setting Up SOAP Service Credentials
## Setting Up REST Service Credentials

_(optional)_ In case Enrollment Server uses a [restricted access flag in the server configuration](https://github.com/wultra/powerauth-server/blob/develop/docs/Deploying-PowerAuth-Server.md#enabling-powerauth-server-security), you need to configure credentials for the Enrollment Server so that it can connect to the SOAP service:
_(optional)_ In case PowerAuth Server uses a [restricted access flag in the server configuration](https://github.com/wultra/powerauth-server/blob/develop/docs/Deploying-PowerAuth-Server.md#enabling-powerauth-server-security), you need to configure credentials for the Enrollment Server so that it can connect to the REST service:

```sh
powerauth.service.security.clientToken=
powerauth.service.security.clientSecret=
```

<-- begin box info -->
The RESTful interface is secured using Basic HTTP Authentication (pre-emptive). The credentials are stored in the `pa_integration` table.
<-- end -->

## Configuring Push Server

The Enrollment Server also allows simple device registration to push notifications by calling PowerAuth Push Server API. While configuring this URL is technically optional, we recommend configuring the push server URL:
Expand All @@ -39,6 +47,18 @@ The default configuration works best with Apache Tomcat server running on defaul

To deploy Enrollment Server to Apache Tomcat, simply copy the WAR file in your `webapps` folder or deploy it using the "Tomcat Web Application Manager" application (usually deployed on default Tomcat address `http://localhost:8080/manager`).

## Deploying Enrollment Server Outside the Container

You can also execute WAR file directly using the following command:

```bash
java -jar enrollment-server.war
```

<-- begin box warning -->
You can overwrite the port using `-Dserver.port=8090` parameter to avoid port conflicts.
<-- end -->

## Deploying Enrollment Server On JBoss / Wildfly

Follow the extra instructions in chapter [Deploying Enrollment Server on JBoss / Wildfly](./Deploying-Wildfly.md).
12 changes: 7 additions & 5 deletions docs/Deploying-Wildfly.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ Enrollment Server contains the following configuration in `jboss-deployment-stru
<subsystem name="logging" />
</exclude-subsystems>
<resources>
<!-- use WAR provided Bouncy Castle -->
<resource-root path="WEB-INF/lib/bcprov-jdk15on-${BC_VERSION}.jar" use-physical-code-source="true"/>
</resources>
<dependencies>
<module name="com.wultra.powerauth.enrollment-server.conf" />
</dependencies>
Expand Down Expand Up @@ -81,7 +86,7 @@ Use the `logback.xml` file to configure logging, for example:
The `application-ext.properties` file is used to override default configuration properties, for example:
```
# PowerAuth Client configuration
powerauth.service.url=http://[host]:[port]/powerauth-java-server/soap
powerauth.service.url=http://[host]:[port]/powerauth-java-server/rest
# PowerAuth Push Server configuration
powerauth.push.service.url=http://[host]:[port]/powerauth-push-server
Expand All @@ -91,7 +96,4 @@ Enrollment Server Spring application uses the `ext` Spring profile which activat

### Bouncy Castle Installation

The Bouncy Castle module for JBoss / Wildfly needs to be enabled as a global module for Enrollment Server.

Follow the instructions in the [Installing Bouncy Castle](https://github.com/wultra/powerauth-server/blob/develop/docs/Installing-Bouncy-Castle.md) chapter of PowerAuth Server documentation.
Note that the instructions differ based on Java version and application server type.
Since Enrollment Server in version `1.1.x`, installing the Bouncy Castle into Wildfy Server is no longer required. The latest version is bundled with the app and cryptographic primitives should work out of the box.
18 changes: 9 additions & 9 deletions enrollment-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@
<description>Base implementation of the enrollment server.</description>

<artifactId>enrollment-server</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
<packaging>war</packaging>

<parent>
<groupId>com.wultra.security</groupId>
<artifactId>enrollment-server-parent</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand All @@ -41,24 +41,24 @@
<dependency>
<groupId>com.wultra.security</groupId>
<artifactId>mtoken-model</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>io.getlime.security</groupId>
<artifactId>powerauth-restful-security-spring</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>io.getlime.security</groupId>
<artifactId>powerauth-push-client</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
</dependency>

<!-- Bouncy Castle -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
<version>1.69</version>
</dependency>

<!-- Spring Dependencies -->
Expand Down Expand Up @@ -100,20 +100,20 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>

<!-- Documentation -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.9</version>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-security</artifactId>
<version>1.5.9</version>
<version>1.6.2</version>
</dependency>

</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

package com.wultra.app.enrollmentserver.configuration;

import io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuthAnnotationInterceptor;
import io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuthEncryptionArgumentResolver;
import io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuthWebArgumentResolver;
import io.getlime.security.powerauth.rest.api.spring.annotation.support.PowerAuthAnnotationInterceptor;
import io.getlime.security.powerauth.rest.api.spring.annotation.support.PowerAuthEncryptionArgumentResolver;
import io.getlime.security.powerauth.rest.api.spring.annotation.support.PowerAuthWebArgumentResolver;
import io.getlime.security.powerauth.rest.api.spring.filter.PowerAuthRequestFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* PowerAuth Enrollment Server
* Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
*/
package com.wultra.app.enrollmentserver.controller.api;

import com.wultra.app.enrollmentserver.errorhandling.ActivationCodeException;
import com.wultra.app.enrollmentserver.errorhandling.InvalidRequestObjectException;
import com.wultra.app.enrollmentserver.impl.service.ActivationCodeService;
import com.wultra.app.enrollmentserver.model.request.ActivationCodeRequest;
import com.wultra.app.enrollmentserver.model.response.ActivationCodeResponse;
import io.getlime.core.rest.model.base.request.ObjectRequest;
import io.getlime.core.rest.model.base.response.ObjectResponse;
import io.getlime.security.powerauth.crypto.lib.encryptor.ecies.model.EciesScope;
import io.getlime.security.powerauth.crypto.lib.enums.PowerAuthSignatureTypes;
import io.getlime.security.powerauth.rest.api.spring.annotation.EncryptedRequestBody;
import io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuth;
import io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuthEncryption;
import io.getlime.security.powerauth.rest.api.spring.authentication.PowerAuthApiAuthentication;
import io.getlime.security.powerauth.rest.api.spring.encryption.EciesEncryptionContext;
import io.getlime.security.powerauth.rest.api.spring.exception.PowerAuthAuthenticationException;
import io.swagger.v3.oas.annotations.Parameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
* Controller publishing REST services for obtaining a new activation code.
*
* @author Petr Dvorak, petr@wultra.com
*/
@ConditionalOnProperty(
value = "enrollment-server.activation-spawn.enabled",
havingValue = "true"
)
@RestController
@RequestMapping(value = "api/activation")
public class ActivationCodeController {

private static final Logger logger = LoggerFactory.getLogger(ActivationCodeController.class);

private final ActivationCodeService activationCodeService;

/**
* Default autowiring constructor.
*
* @param activationCodeService Activation code service.
*/
@Autowired
public ActivationCodeController(ActivationCodeService activationCodeService) {
this.activationCodeService = activationCodeService;
}

/**
* Controller request handler for requesting the activation code.
*
* @param request Request with activation OTP.
* @param eciesContext ECIES encryption context.
* @param apiAuthentication Authentication object with user and app details.
* @return New activation code, activation code signature and activation ID.
* @throws PowerAuthAuthenticationException In case user authentication fails.
* @throws InvalidRequestObjectException In case the object validation fails.
* @throws ActivationCodeException In case fetching the activation code fails.
*/
@RequestMapping(value = "code", method = RequestMethod.POST)
@PowerAuthEncryption(scope = EciesScope.ACTIVATION_SCOPE)
@PowerAuth(resourceId = "/api/activation/code", signatureType = {
PowerAuthSignatureTypes.POSSESSION_BIOMETRY,
PowerAuthSignatureTypes.POSSESSION_KNOWLEDGE
})
public ObjectResponse<ActivationCodeResponse> requestActivationCode(@EncryptedRequestBody ObjectRequest<ActivationCodeRequest> request,
@Parameter(hidden = true) EciesEncryptionContext eciesContext,
@Parameter(hidden = true) PowerAuthApiAuthentication apiAuthentication) throws PowerAuthAuthenticationException, InvalidRequestObjectException, ActivationCodeException {
// Check if the authentication object is present
if (apiAuthentication == null) {
logger.error("Unable to verify device registration when fetching activation code");
throw new PowerAuthAuthenticationException("Unable to verify device registration when fetching activation code");
}

// Check if the request was correctly decrypted
if (eciesContext == null) {
logger.error("ECIES encryption failed when fetching activation code");
throw new PowerAuthAuthenticationException("ECIES decryption failed when fetching activation code");
}

if (request == null || request.getRequestObject() == null) {
logger.error("Invalid request received when fetching activation code");
throw new PowerAuthAuthenticationException("Invalid request received when fetching activation code");
}

// Request the activation code details.
final ActivationCodeResponse response = activationCodeService.requestActivationCode(request.getRequestObject(), apiAuthentication);
return new ObjectResponse<>(response);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
import com.wultra.security.powerauth.lib.mtoken.model.request.OperationApproveRequest;
import com.wultra.security.powerauth.lib.mtoken.model.request.OperationRejectRequest;
import com.wultra.security.powerauth.lib.mtoken.model.response.OperationListResponse;
import io.getlime.security.powerauth.rest.api.base.authentication.PowerAuthApiAuthentication;
import io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuth;
import io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuthToken;
import io.getlime.security.powerauth.rest.api.spring.authentication.PowerAuthApiAuthentication;
import io.swagger.v3.oas.annotations.Parameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -56,7 +56,7 @@
matchIfMissing = true
)
@RestController
@RequestMapping("/api/auth/token/app")
@RequestMapping("api/auth/token/app")
public class MobileTokenController {

private static final Logger logger = LoggerFactory.getLogger(MobileTokenController.class);
Expand Down Expand Up @@ -170,7 +170,7 @@ public Response operationApprove(@RequestBody ObjectRequest<OperationApproveRequ
if (auth != null && auth.getUserId() != null) {
final String userId = auth.getUserId();
final Long applicationId = auth.getApplicationId();
final PowerAuthSignatureTypes signatureFactors = auth.getSignatureFactors();
final PowerAuthSignatureTypes signatureFactors = auth.getAuthenticationContext().getSignatureType();
return mobileTokenService.operationApprove(userId, applicationId, operationId, data, signatureFactors);
} else {
// make sure to fail operation as well, to increase the failed number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
import io.getlime.core.rest.model.base.request.ObjectRequest;
import io.getlime.core.rest.model.base.response.Response;
import io.getlime.security.powerauth.crypto.lib.enums.PowerAuthSignatureTypes;
import io.getlime.security.powerauth.rest.api.base.authentication.PowerAuthApiAuthentication;
import io.getlime.security.powerauth.rest.api.base.exception.PowerAuthAuthenticationException;
import io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuthToken;
import io.getlime.security.powerauth.rest.api.spring.authentication.PowerAuthApiAuthentication;
import io.getlime.security.powerauth.rest.api.spring.exception.PowerAuthAuthenticationException;
import io.swagger.v3.oas.annotations.Parameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -111,9 +111,9 @@ private Response registerDeviceImpl(

// Check if the context is authenticated - if it is, add activation ID.
// This assures that the activation is assigned with a correct device.
String userId = apiAuthentication.getUserId();
String activationId = apiAuthentication.getActivationId();
Long applicationId = apiAuthentication.getApplicationId();
final String userId = apiAuthentication.getUserId();
final String activationId = apiAuthentication.getActivationContext().getActivationId();
final Long applicationId = apiAuthentication.getApplicationId();

return pushRegistrationService.registerDevice(request, userId, activationId, applicationId);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* PowerAuth Enrollment Server
* Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
*/
package com.wultra.app.enrollmentserver.errorhandling;

/**
* Exception thrown in case activation code cannot be fetched for any reason.
*
* @author Petr Dvorak, petr@wultra.com
*/
public class ActivationCodeException extends Exception {
private static final long serialVersionUID = 368452747764248241L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
package com.wultra.app.enrollmentserver.errorhandling;

import io.getlime.core.rest.model.base.response.ErrorResponse;
import io.getlime.security.powerauth.rest.api.base.exception.PowerAuthAuthenticationException;
import io.getlime.security.powerauth.rest.api.spring.exception.PowerAuthAuthenticationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -122,4 +122,16 @@ public class DefaultExceptionHandler {
return new ErrorResponse(ex.getCode(), ex.getMessage());
}

/**
* Handling of activation code exceptions.
* @param ex Exception.
* @return Response with error details.
*/
@ExceptionHandler(ActivationCodeException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public @ResponseBody ErrorResponse handleActivationCodeException(ActivationCodeException ex) {
logger.warn("Unable to fetch activation code", ex);
return new ErrorResponse("ACTIVATION_CODE_FAILED", "Unable to fetch activation code.");
}

}
Loading

0 comments on commit 394a7f8

Please sign in to comment.