Coder Social home page Coder Social logo

wultra / powerauth-server Goto Github PK

View Code? Open in Web Editor NEW
17.0 7.0 12.0 17.97 MB

PowerAuth Server component is the back-end counterpart of PowerAuth Mobile SDK that holds device registrations and verifies MFA signatures.

License: GNU Affero General Public License v3.0

Java 94.01% HTML 0.19% JavaScript 5.67% CSS 0.12%
authentication psd2 transaction-signing strong-customer-authentication passwordless passwordless-authentication multi-factor-authentication mfa

powerauth-server's Introduction

PowerAuth Server

Build Status Status GitHub issues License: AGPL v3

PowerAuth Server is a core back-end application that realizes the PowerAuth protocol cryptography. It is responsible for device registration, activation lifecycle, application management and integration security.

Documentation

For the most recent documentation and tutorials, please visit PowerAuth Server Documentation on GitHub or visit developers.wultra.com.

License

PowerAuth Server is licensed using GNU AGPLv3 license. Please consult us at [email protected] for the software use.

powerauth-server's People

Contributors

bantercz avatar dependabot[bot] avatar hvge avatar jandusil avatar jnpsk avatar meddox avatar petrdvorak avatar romanstrobl avatar saalistaja avatar snyk-bot avatar zcgandcomp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

powerauth-server's Issues

Investigate Spring Vault

We should investigate Spring Vault project in scope of deploying PowerAuth stack:

http://projects.spring.io/spring-vault

The typical use case for Vault is securing all plain text passwords and keys from application.properties. This could improve resilience of PowerAuth against internal attacks.

Remove unused signature types

Currently, we do not have any good use-case for following signature types:

  • KNOWLEDGE
  • BIOMETRY
  • POSSESSION_KNOWLEDGE_BIOMETRY

I believe we should remove these values accordingly.

When fetching application detail, check if application exists

Currently, if client asks for application with ID that does not exist, we return SOAP fault with NPE.

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <SOAP-ENV:Fault>
            <faultcode>SOAP-ENV:Server</faultcode>
            <faultstring xml:lang="en">java.lang.NullPointerException</faultstring>
        </SOAP-ENV:Fault>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Improve logging of PowerAuth Server

We should add logging messages to PowerAuth server with levels WARNING, INFO and FINE.

When adding log messages we should be careful not to flood the logs on default level (INFO).

Minor JavaDoc issue

[WARNING] /Users/petrdvorak/Development/git/powerauth-server/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/KeyEncryptionMode.java:59: warning - @return tag has no arguments.

When initializing activation, check for applicationId

Currently, the initActivation method attempts to fetch master key pair from the database based on applicationId. In case no app with provided applicationId exists, we throw error about missing key pair. As a result, the issue with invalid applicationId is hard to debug.

We should check if given application exists first...

Implement personalized and non-personalized variants of createOfflineSignaturePayload

We should distinguish two modes of operation for createOfflineSignaturePayload:

  • personalized - uses activationId to obtain KEY_SERVER_PRIVATE which is used in ECDSA signature
  • non-personalized - uses applicationId to obtain KEY_SERVER_MASTER_PRIVATE which is used in ECDSA signature

Furthermore, we should remove message from offline signatures, the message should be already present in signed data. We should also deprecate usage of dataHash in favor of data (in future data size can be decreased if required, so data in offline signature payload response may differ from data in offline signature request).

Loading signature type form database is case sensitive

Older versions of PowerAuth were using lowercased String to store signature type. Now, we have migrated the String type to Enum, which is more appropriate, but uses uppercase under the hood.

This causes issues when loading data from database created previously - lowercase items are incorrectly converted to Enums...

Database deadlock when multiple PA signatures are validated at the same time

When our mobile client is trying to create (/pa/token/create) a multiple tokens at the same time (for the same activation), then some of the requests ends with an unknown error:

{"status":"ERROR","responseObject":{"code":"ERROR_GENERIC","message":"error.unknown"}}

After a small investigation in the logs, we found out a database deadlock on the PA server:

2017-12-07 14:09:48.802  WARN 1 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1213, SQLState: 40001
2017-12-07 14:09:48.802 ERROR 1 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper   : Deadlock found when trying to get lock; try restarting transaction
2017-12-07 14:09:48.802  INFO 1 --- [nio-8080-exec-7] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements

UPDATE

The actual problem is not related to the tokens at all. Look for discussion below.

Add method to lookup application by name

Currently, application is identified by a Long id, which is not very handy in a multi-environment infrastructure (since the same application may have multiple ID).

We should introduce some unique app identifier specified upon application creation, so that deployer can specify IDs such as "MOB_BANK" - for example, we can add method to lookup application by name (applicationName).

Application can then use codes as a name to lookup application and assign it to application name / icon / description / other attributes that have nothing to do with PowerAuth protocol and software stack.

Add information about BLOCK reason

When user blocks the device, we should be able to assign a reason. Also, we should have a flag to indicate that the device was blocked by the bank and therefore cannot be unblocked by the user.

Application level record encryption

At the moment, we store device related server private key as a plain text in the database. This is not a big issue in some scenarios, since back-ends are in a secure infrastructure with very limited access, however we could still improve security of the key by:

  1. Introducing a new property (in case the property is not set, no encryption is used):
powerauth.server.db.master.encryption.key=MTIzNDU2Nzg5MDEyMzQ1Ng==
  1. Using conversion mechanism whenever loading a serverPrivateKey value for the activation entity.

Note that since there is the good old rule "Same data should result in different encrypted values", we should introduce IV value for the encryption that should be stored with the value, such as (pseudo-code):

public byte[] encrypt(byte[] orig, SecretKey key) {
    byte[] iv = Bytes.random(16);
    byte[] encrypted = aes.encrypt(orig, iv, key);
    byte[] record = iv.append(encrypted)
    return record;
}

public byte[] decrypt(byte[] record, SecretKey key) {
    byte[] iv = record.byteRange(0, 16); // offset, length
    byte[] encrypted = record.byteRange(16, -1); // offset, remaining
    byte[] orig = aes.decrypt(encrypted, iv, key);
    return orig;
}

Also, in order to achieve consistency between activation record and encrypted server private key (to avoid partial record swap), we should pay attention to how we construct the encryption key. It should be derived from the master DB encryption key using KDF_INTERNAL with user ID and activation ID derivate as a base, like so:

public SecretKey deriveSecretKey(SecretKey masterDbEncryptionKey, String userId, String activationId) {
    String base = activationId.getBytes("UTF-8");
    String salt = userId.getBytes("UTF-8");
    byte[] index = PBKDF2.expand(base, salt, iterations, lengthInBits);
    return KDF_INTERNAL.derive(masterDbEncryptionKey, index);
}

Since we need entity context in order to achieve this, we very likely aren't able to use (aspect / annotation based) converter...

Improve input parameter validation

The service behavior sometimes assumes it receives correct attribute values from our integration libraries. We should implement more bulletproof parameter checking.

This issue does not have a large impact, since it assumes incorrect deployment or invalid server setup.

Hide default spring JDBC properties behind PowerAuth properties

In order to be able to configure PowerAuth 2.0 Server JDBC properties globally (not for a given context), it would be nice to allow configuration using other than Spring default properties.

Following new properties should be introduced:

spring.datasource.url=${powerauth.datasource.url}
spring.datasource.username=${powerauth.datasource.username}
spring.datasource.password=${powerauth.datasource.password}
spring.datasource.driver-class-name=${powerauth.datasource.driver-class-name}
spring.jpa.properties.hibernate.default_schema=${powerauth.jpa.properties.hibernate.default_schema}

JDK 9 support

Following changes are required (based on what we currently know):

  1. Upgrade maven versions as follows:
    <maven-jar-plugin.version>3.0.2</maven-jar-plugin.version>
    <maven-javadoc-plugin.version>3.0.0</maven-javadoc-plugin.version>
    <maven-war-plugin.version>3.1.0</maven-war-plugin.version>
  2. Resolve Java EE compilation dependencies (deprecated libraries which are going to be removed in JDK 11)
  3. Prepare list of Java EE libraries required to be deployed externally
  4. Remove Bouncy Castle provider from all war files, the library should be placed into Tomcat lib folder instead
  5. Write documentation

Use subscribe() instead of block() in callbacks

While migrating to Spring boot 2.0.0 we replaced the AsyncRestTemplate with WebClient.

Althrough current implementation of callbacks works fine, its thread usage can be improved by leveraging a completely reactive WebClient instead of blocking in asynchronous code.

So instead of using the @Async annotation and WebClient.block() we should use WebClient.subscribe().

Expiration of activations

We should introduce expiration for activations. The expiration time should be configurable. We should also consider whether expiration should be tied to the number of signature verifications. We also need to implement a workflow for reactivation - the user needs to be informed about expired activation and a new activation work flow should be initiated.

It seems it is better not to force this setting and allow clients to migrate to enabled expiration at their own pace because it may have impact on the client application which enables activation (e.g. internet banking).

The reason for expiration of activations is increasing resistance against brute force attacks, and should remain optional only for clients who want such extra level of security.

Hibernate exception when creating activation on Oracle

The following exception occurs when creating an activation on Oracle database:

org.springframework.ws.soap.client.SoapFaultClientException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : io.getlime.security.powerauth.app.server.database.model.entity.ActivationHistoryEntity.activation -> io.getlime.security.powerauth.app.server.database.model.entity.ActivationRecordEntity; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : io.getlime.security.powerauth.app.server.database.model.entity.ActivationHistoryEntity.activation -> io.getlime.security.powerauth.app.server.database.model.entity.ActivationRecordEntity

Add support for MASTER_KEY_PAIR lifecycle

Currently, there is a collection of MASTER_KEY_PAIRs associated with every application. For the purpose of activation, the one that is the newest (ordered by timestamp_created) is used. We should add a better support for the lifecycle to the PA2.0 SW stack, namely:

  • Add a method to generate a new "replacement key pair" for an application in SOAP interface.
  • Add a method to make the replacement key pair active (disable the old key, enable the new one) in SOAP interface.
  • Add UI update to the PowerAuth 2.0 Admin in order to display the new replacement key pair's public key.

Startup error on Wildfly due to missing key converter

Exception occurs when PowerAuth server starts on Wildfly:

Convertor mustn't be null! Set convertor by calling PowerAuthConfiguration.INSTANCE.setConvertor()

Stack trace:

Convertor mustn't be null! Set convertor by calling PowerAuthConfiguration.INSTANCE.setConvertor().
	at io.getlime.security.powerauth.crypto.lib.config.PowerAuthConfiguration.getKeyConvertor(PowerAuthConfiguration.java:52)
	at io.getlime.security.powerauth.app.server.converter.ServerPrivateKeyConverter.<init>(ServerPrivateKeyConverter.java:64)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:170)
	... 40 more

It seems that the class instantiation order is different on Wildfly than on Tomcat. The setKeyConverter() method is called in class PowerAuthServiceImpl in a static block.

Add vault unlock reason

Currently, we just enable vault unlock. However, we should be able to specify the vault unlock reason for the auditing purposes. There are several reasons why user may need to use vault unlock:

  • Enabling Touch ID / Biometry
  • Signing a document
  • Retrieving an encryption key

Duplicate log messages

Log messages are duplicated in PowerAuth server in default configuration. Perhaps it is caused by multiple logging libraries.

See screenshot.

screen shot 2018-06-08 at 16 06 00

Rename long repository methods and use annotation

Currently, we use some extremely long names in repository interfaces, such as:

  • findByActivation_UserIdAndTimestampCreatedBetweenOrderByTimestampCreatedDescIdDesc
  • findByActivation_ApplicationIdAndActivation_UserIdAndTimestampCreatedBetweenOrderByTimestampCreatedDescIdDesc

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.