Skip to content

gematik/popp-sample-code

Repository files navigation

PoPP Sample Implementation

Overview

This project provides a sample implementation of the PoPP-Service and PoPP-Client according to gemSpec_PoPP_Service. The eGK-Hash-Datenbank is implemented as PostgresSQL database.

You can run the components either locally or via Docker Quick start.

Building and running the project locally

⚙️ Prerequisites

All keys and p12 stores contained in this repository are intentionally published to allow the project to run out of the box after cloning.

Notes

  • Ensure ports '8081' (PoPP-Client), 5432 (eGK-Hash-Datenbank) and 8443 (PoPP-Service) are free.
  • You can modify compose.yaml to fit your environment.

Step-by-step guide

Build

  ./mvnw clean install

Optionally without tests:

  ./mvnw clean install -Dmaven.test.skip=true

or

  ./mvnw clean install -DskipTests=true

Configuration

All described configuration options must be implemented in the application-dev.yaml of the PoPP-Client.

a) Standard-Kartenleser

"Standard-Kartenleser" is a PC/SC card reader, which is typically connected via USB.

By default, the PoPP-Client uses the first Standard-Kartenleser it detects. However, you can specify explicitly which Standard-Kartenleser to use.

cardreader:
      name: "<card reader name>"

The name is case-sensitive but does not have to be complete, for example with "REINER SCT" the Standard-Kartenleser named "REINER SCT cyberJack RFID standard 1" will be found.

b) Konnektor

Optional: Certificates for TLS

The PoPP-Client supports TLS connections using ECC for communication with your Konnektor. To enable and configure this, follow the steps below:

  1. Enable TLS by setting:

    connector:
      secure:
        enable: true
  • If your Konnektor does not have a resolvable domain name, disable hostname validation:

    connector:
      secure:
        hostname-validation: false
  • Upload your client certificate (e.g., keystore.p12) to the Konnektor client configuration.

  • Retrieve the Konnektor certificate (replace <KONNEKTOR_IP> and <PORT> with your specific Konnektor address):

    openssl s_client -showcerts -connect <Konnektor_IP>:<PORT>
    

    Depending on the Konnektor type, you might add a curves parameter to the command, e.g.:

    openssl s_client -showcerts -connect <Konnektor_IP>:<PORT> -curves brainpoolP256r1
    

    or a cipher parameter, e.g.:

    openssl s_client -showcerts -connect <Konnektor_IP>:<PORT> -cipher ECDHE-ECDSA-AES128-GCM-SHA256
    
  • Import the Konnektor certificate including the whole trust chain into your truststore (e.g., truststore.p12):

    keytool -import -alias connector-server -file server-cert.pem -keystore truststore.p12
    
  • Note: The connector.secure.keystore, connector.secure.truststore, and their respective passwords are used only for communication with the Konnektor. This is distinct from the TLS configuration used for communication with the PoPP server.

Address and context

Configure your Konnektor address and context:

connector:
  end-point-url: <ip address and port of event-service endpoint of Konnektor>
  terminal-configuration:
  log-ws: <if SOAP messages should be logged>
  secure:
    enable: <If TLS should be used>
    hostname-validation: <The Hostname of the Konnektor should be validated>
    keystore: <Keystore with the client certificate>
    keystore-password: <Password of the keystore>
    trust-all: <If all certificates should be trusted, only for testing purposes>
    truststore: <Truststore with the Konnektor certificate and its trust chain>
    truststore-password: <Password of the truststore>
  context:
    clientSystemId: <ClientSystemId for Konnektor Context>
    workplaceId: <WorkplaceId for Konnektor Context>
    mandantId: <MandantId for Konnektor Context>

Example:

connector:
  end-point-url: "http://127.0.0.1"
  terminal-configuration:
  log-ws: true
  secure:
    enable: false
    hostname-validation: true
    keystore: keystore.p12
    keystore-password: changeit
    trust-all: false
    truststore: truststore.p12
    truststore-password: changeit
  context:
    clientSystemId: "ClientID1"
    workplaceId: "Workplace1"
    mandantId: "Mandant1"

Supported Konnektor functions

c) Virtual Card

If you want to use a virtual card instead a card reader or Konnektor you can configure it as follows. This allows testing without any card-related hardware. The card data will be read from the XML image file specified.

virtual-card:
  image-file: <XML image file>

Execution

Quick start (Docker, full profile – recommended for testing with the virtual card)

For a quick out-of-the-box setup (including PoPP-Client, PoPP-Service, and the eGK-Hash-Datenbank), this project provides a Docker Compose full profile.

This mode is especially useful for:

  • testing the virtual card
  • running the complete PoPP stack without card readers or a Konnektor

1. Build Docker images via Maven

Docker images are built as part of the Maven build.
Make sure Docker image creation is enabled:

./mvnw clean install -Dskip.dockerbuild=false

This step builds the Docker images local/popp/popp-server:<version> and local/popp/popp-client:<version>.

2. Start the full stack via Docker Compose

docker compose -f docker/compose.yaml --profile full up

This starts:

  • PoPP-Server
  • eGK-Hash-Datenbank (PostgreSQL)
  • PoPP-Client (without card reader/Konnektor, using virtual card)

3. Verify startup

Once all containers are running, the following endpoints are available:

4. Testing with a virtual card

The full Docker profile is intended to be used together with the virtual card configuration. You can test it via the Swagger-Ui with the /token endpoint as described below with the communication type contact-virtual.

This allows testing PoPP flows without any card-related hardware.

Start the eGK-Hash-Datenbank

If you want to run the PoPP-Service with out Docker, you need to start the eGK-Hash-Datenbank.

  cd popp-server/docker && docker compose --file postgres-dev.yaml up

For powershell use:

  cd popp-server/docker; docker compose --file postgres-dev.yaml up

To stop and remove the containers, run the following command:

  cd docker && docker compose down

For powershell use:

  cd docker; docker compose down)

Start the PoPP-Service

  ./mvnw -pl popp-server spring-boot:run

Start the PoPP-Client

  ./mvnw -pl popp-client spring-boot:run

For Linux with additional argument:

  ./mvnw -pl popp-client spring-boot:run -Dspring-boot.run.jvmArguments="-Dsun.security.smartcardio.library=/lib/x86_64-linux-gnu/libpcsclite.so.1"

Alternatively: Docker usage (Service & Database)

  cd docker && docker compose up

The client must be started locally!

Executing the tests

To execute the tests for the whole project, run the following command:

  ./mvnw clean test

To execute also the integration tests, run the following command:

  ./mvnw clean verify

To execute the tests for a specific module, use the -pl option to specify the module name. For example, to run the tests for the popp-client module, run:

  ./mvnw -pl popp-client clean test

Generate a PoPP-Token

The client provides the following POST endpoint to generate a PoPP-Token:

POST http://localhost:8081/token

With Request Body:

{
  "communicationType": "<one of the supported types>",
  "clientSessionId": "<optional>"
}

The request parameter clientsessionid is optional. If set, the clientsessionid will overwrite the Konnektor clientsessionid from StartCardSession

The communication type must be one of the following:

  • contact-standard
    • use contact-based interface from Standard-Kartenleser
  • contactless-standard
    • use contactless interface from Standard-Kartenleser
  • contact-virtual
    • use a virtual card from a card image file, no card reader needed
  • contact-connector
    • use contact-based interface from eHealth-Kartenterminal via Konnektor
  • contactless-connector
    • use contactless interface from eHealth-Kartenterminal via Konnektor
  • contact-connector-via-standard-terminal
    • generate sample messages for Konnektor via contact-based interface from Standard-Kartenleser \

Example usage

To generate a PoPP token, you can use the Swagger UI. Open the following URL in your browser: http://localhost:8081/swagger-ui.html

Alternatively, you can use this curl command in the terminal, e.g.:

curl -X POST http://localhost:8081/token \
  -H "Content-Type: application/json" \
  -d '{
    "communicationType": "contact-standard",
    "clientSessionId": "123456"
  }'

To view the generated PoPP-Token, check the console output of the client.

For PoPP-Token claims see api-popp.

Sequence diagrams

PoPP-Token with Standard-Kartenleser

PoPP-Token with Standard-Kartenleser

PoPP-Token with Konnektor

PoPP-Token with Standard-Kartenleser

PoPP-Token with Standard-Kartenleser instead of Konnektor for generating sample messages

PoPP-Token with Standard-Kartenleser

License

Copyright 2025-2026 gematik GmbH

Apache License, Version 2.0

See the LICENSE for the specific language governing permissions and limitations under the License

Additional Notes and Disclaimer from gematik GmbH

  1. Copyright notice: Each published work result is accompanied by an explicit statement of the license conditions for use. These are regularly typical conditions in connection with open source or free software. Programs described/provided/linked here are free software, unless otherwise stated.
  2. Permission notice: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    1. The copyright notice (Item 1) and the permission notice (Item 2) shall be included in all copies or substantial portions of the Software.
    2. The software is provided "as is" without warranty of any kind, either express or implied, including, but not limited to, the warranties of fitness for a particular purpose, merchantability, and/or non-infringement. The authors or copyright holders shall not be liable in any manner whatsoever for any damages or other claims arising from, out of or in connection with the software or the use or other dealings with the software, whether in an action of contract, tort, or otherwise.
    3. The software is the result of research and development activities, therefore not necessarily quality assured and without the character of a liable product. For this reason, gematik does not provide any support or other user assistance (unless otherwise stated in individual cases and without justification of a legal obligation). Furthermore, there is no claim to further development and adaptation of the results to a more current state of the art.
  3. Gematik may remove published results temporarily or permanently from the place of publication at any time without prior notice or justification.
  4. Please note: Parts of this code may have been generated using AI-supported technology. Please take this into account, especially when troubleshooting, for security analyses and possible adjustments.

About

This repository provides sample code for popp. It demonstrates their interaction and key features, serving as a starting point for developers who want to understand or integrate popp components into their projects.

Resources

License

Apache-2.0, Unknown licenses found

Licenses found

Apache-2.0
LICENSE
Unknown
license-header.txt

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors