Skip to main content

User Service

Service Type: Broker Platform REST Microservice Language: Kotlin / Micronaut Framework Database: PostgreSQL (owned) Messaging: Kafka producer and consumer Identity Provider: Keycloak Status: Implemented (v0.1)


Overview

User Service is responsible for user identity management within the DEUSS Broker Platform. It manages user profiles, registration, invitation tokens, elevated roles, passkeys, on-chain accounts, account recovery, and identity-verification records. The service integrates with Keycloak for identity and passkey administration, Registry Service for on-chain user registration and recovery, Company Service for validating company-related user roles, SMTP for email delivery, and Kafka for user-related domain events.


Business Responsibilities

  • User Management — Create, retrieve, update, list, and delete user accounts
  • User Registration — Register users using invitation tokens and profile data
  • Invitation Management — Generate, verify, list, and revoke invitation tokens
  • Role Management — Assign and remove ADMIN and ORIGINATOR roles
  • Passkey Management — Coordinate passkey registration and passkey lifecycle
  • On-chain Account Management — Register users on-chain and maintain linked wallet accounts
  • Account Recovery — Coordinate passkey recovery between Keycloak, User Service, and Registry Service
  • Identity Verification — Store identity-verification records and calculate the current verification state
  • Email Communication — Send registration and other user-related emails through SMTP
  • User Event Publication — Publish registration and passkey events to Kafka
  • Originator Role Synchronization — Automatically assign or remove the ORIGINATOR role based on company events

Owned Data

The service owns the following user-related data:

  • deuss_user — User identity and profile information
  • deuss_user_role — User roles and role assignments
  • invite_token — Invitation tokens used during onboarding
  • deuss_user_onchain_account — User-owned blockchain accounts
  • deuss_passkey — Passkey credentials linked to on-chain accounts
  • identity_verification_record — Historical and active identity-verification records
  • Refresh-token and legacy authentication records where still applicable in the migration history

Key Data Rules

  • User email is used as a unique identity attribute.
  • A user may have on-chain accounts and linked passkeys.
  • At most one passkey can be active for a given on-chain account.
  • Users with an existing on-chain identity cannot be deleted.
  • Users who are administrators in a company or originator organization cannot be deleted.
  • Identity-verification records may be historical, with at most one active record expected.

Inbound Interfaces

Public REST API

The public API is defined in user-public.openapi.yaml.

User Management

EndpointMethodPurpose
/users/meGETRetrieve the currently authenticated user
/users/mePATCHUpdate the current user's profile
/users/meDELETEDelete the current user's account when permitted
/admin/usersGETList users with pagination and email filtering
/admin/users/{id}GETRetrieve a user by ID
/admin/users/{id}PATCHUpdate a user by ID
/admin/users/{id}DELETEDelete a user by ID
/findPOSTResolve a user ID from an email address
/users/{id}/accountsGETRetrieve a user's on-chain accounts

Registration and Invitations

EndpointMethodPurpose
/auth/registerPOSTRegister a user using an invitation token
/admin/invitesGETList invitation tokens
/admin/invites/generatePOSTGenerate invitation token(s)
/invites/verifyPOSTVerify whether an invitation token is valid
/admin/invites/{token}DELETERevoke an invitation token

Roles

EndpointMethodPurpose
/admin/users/{id}/roles/adminPOSTAssign the ADMIN role
/admin/users/{id}/roles/adminDELETERemove the ADMIN role
/users/{id}/roles/originatorPOSTAssign the ORIGINATOR role
/users/{id}/roles/originatorDELETERemove the ORIGINATOR role

Identity Verification and Recovery

EndpointMethodPurpose
/users/identity_verification_recordsPOSTCreate an identity-verification record
/users/me/recoveryPOSTStart recovery of the current user's passkey/on-chain identity

Internal REST API

The internal API is defined in user-internal.openapi.yaml.

EndpointMethodPurpose
/api/internal/usersGETRetrieve basic data for multiple users
/api/internal/users/{id}GETRetrieve a user by ID
/api/internal/users/{id}/accountsGETRetrieve a user's on-chain accounts
/api/internal/users/email/{email}GETResolve user data by email
/api/internal/users/{id}/register-corePOSTEnsure the user is registered in Registry Service
/api/internal/users/email/{email}/tokensPOSTGenerate an invitation token for a new user

Kafka Consumer

The service consumes originator-related company events.

TopicEventPurpose
OriginatorEvents.UPDATEDOriginatorEmployeeEventAssign or remove the ORIGINATOR role when an employee is added to or removed from an originator organization

The event type is provided through a message header.


Outbound Interfaces

Kafka Producers

The service publishes user-related domain events.

TopicEventPurpose
RegistrationEvents.CREATEDRegistrationCreatedEventNotify other services that a user was registered
RegistrationEvents.PASSKEY_CREATEDPasskeyCreatedEventNotify other services that a passkey/on-chain account was created

Keycloak

User Service uses the Keycloak Admin API for identity and passkey operations, including:

  • Managing user identity data
  • Retrieving a user's passkey
  • Deleting passkeys during recovery
  • Coordinating passkey registration and replacement
  • Supporting authentication-related flows Keycloak is the external identity provider, while User Service stores the application-level user record and its relationship to on-chain accounts.

Registry Service

User Service calls Registry Service for blockchain-related user operations:

  • Register a user on-chain
  • Create or recover a user's blockchain identity
  • Obtain the Registry/Core user ID
  • Retrieve the resulting wallet address
  • Coordinate passkey recovery Blockchain side effects are performed by Registry Service. User Service stores the resulting references and keeps its local state synchronized.

Company Service

User Service uses Company Service to validate whether a user is an administrator in a company or originator organization. This validation is important before deleting a user account.

SMTP Mail Server

The service sends email notifications through SMTP using:

  • SMTP host and port
  • SMTP credentials
  • Configured sender name and address The exact set of email templates and notification scenarios is implemented in the service code.

PostgreSQL

User Service accesses its own PostgreSQL database through JPA/Hibernate. Flyway manages schema migrations.


Kafka Integration

Status: Enabled

Producers

  • User registration events
  • Passkey-created events

Consumer

  • Originator employee updates Kafka is used for:
  • Propagating user lifecycle events
  • Synchronizing originator roles based on company membership changes
  • Notifying downstream services about passkey and on-chain account creation

Key Business Rules

  1. Registration requires an invitation token.
  2. Invitation tokens can be generated, verified, consumed, and revoked.
  3. Admin users can manage users and invitation tokens.
  4. Only authorized users can assign elevated roles.
  5. ADMIN role assignment requires an existing ADMIN user.
  6. ORIGINATOR role assignment can be performed by an ADMIN or ORIGINATOR user.
  7. A user cannot be deleted when an on-chain identity already exists.
  8. A user cannot be deleted while acting as an administrator in a company or originator organization.
  9. On-chain onboarding is idempotent.
  10. A newly registered user is registered with Registry Service using passkey data from Keycloak.
  11. Passkey recovery deactivates the current local passkey and removes Keycloak passkeys before re-registration.
  12. At most one active passkey exists for an on-chain account.
  13. Originator role assignments are synchronized from company events.
  14. Identity-verification records are stored historically and used to calculate the current verification state.

On-chain User Onboarding Flow

  1. A user completes registration using a valid invitation token.
  2. User Service obtains the user's passkey from Keycloak.
  3. User Service calls Registry Service to create the user's on-chain identity.
  4. Registry Service returns the Core/Registry user ID and wallet address.
  5. User Service stores:
    • the Core/Registry user ID,
    • the on-chain account,
    • the passkey reference.
  6. User Service publishes a PasskeyCreatedEvent to Kafka. Registry Service performs the blockchain operation; User Service coordinates the workflow and stores local references.

Passkey Recovery Flow

  1. The user starts recovery through /users/me/recovery.
  2. User Service verifies that an on-chain account exists.
  3. The active local passkey is deactivated.
  4. Existing Keycloak passkeys are removed.
  5. The user registers a new passkey in Keycloak.
  6. User Service detects the new passkey.
  7. Registry Service is called to recover or update the on-chain identity.
  8. The new passkey and account state are stored locally.

Identity Verification

The service stores identity-verification records with:

  • Verification state
  • Valid-from date
  • Valid-to date
  • Optional external session ID The currently implemented creation flow creates a record in VERIFIED state, valid from the current date for one year. The session_id is currently unused and reserved for a future external KYC provider integration. Supported states include:
  • NOT_REQUESTED
  • PENDING_VERIFICATION
  • VERIFIED
  • FAILED

Deployment

Runtime Stack:

  • Kotlin
  • Micronaut
  • Java 25 OpenJDK runtime
  • Netty
  • PostgreSQL
  • Hibernate/JPA
  • Flyway
  • Kafka
  • Keycloak Admin Client
  • SMTP mail client
  • Shared DEUSS blockchain library Configuration:
  • Application name: user-service
  • HTTP port: 8080
  • Database: user_service_db
  • Flyway migrations enabled
  • Kafka group ID: user-service
  • JWT and refresh-token configuration enabled
  • Keycloak Admin integration enabled by default
  • Optional blockchain-related local configuration Relevant Environment Variables:
  • DATABASE_URL
  • DATABASE_USER
  • DATABASE_PASSWORD
  • COMPANY_SERVICE_URL
  • REGISTRY_SERVICE_URL
  • JWT_GENERATOR_SIGNATURE_SECRET
  • JWT_GENERATOR_INVITE_TOKEN_EXPIRY
  • JWT_GENERATOR_REFRESH_TOKEN_EXPIRY
  • SMTP_HOST
  • SMTP_PORT
  • SMTP_USERNAME
  • SMTP_PASSWORD
  • SMTP_FROM_NAME
  • SMTP_FROM_ADDRESS
  • KEYCLOAK_ADMIN_ENABLED
  • KEYCLOAK_SERVER_URL
  • KEYCLOAK_REALM
  • KEYCLOAK_CLIENT_ID
  • KEYCLOAK_CLIENT_SECRET
  • KAFKA_GROUP_ID
  • CHAIN_ENABLED Sensitive credentials are supplied through deployment configuration and are not owned by the application source code. Container:
  • Alpine-based image
  • OpenJDK 25
  • Runs under a non-root runtime user
  • Uses tini as the init process
  • Enables JVM container support

External Integrations

Keycloak

Primary identity and passkey provider.

Registry Service

Core service responsible for blockchain identity operations.

Company Service

Used for company membership and administrator checks.

SMTP Provider

Used for outbound user-related emails.

Kafka

Used for user lifecycle events and originator-role synchronization.


Observability

  • Structured logging through DeussLogger
  • Auto-logging on selected administrative operations
  • Transactional processing for user and role changes
  • Kafka consumer logging for unknown or invalid event types
  • Database audit timestamps on user-related records
  • Standard Micronaut health and utility endpoints through the shared framework
  • Metrics integration: not verified in the analyzed source

Architectural Characteristics

  • Identity Aggregator — Combines local user data with Keycloak identity data and blockchain identity references.
  • On-chain Coordination Layer — Coordinates blockchain onboarding and recovery through Registry Service rather than interacting directly with the chain.
  • Event-Driven Role Synchronization — Originator roles are updated based on company events.
  • Hybrid Integration Model — Uses REST for synchronous service-to-service calls and Kafka for domain events.
  • Invitation-Based Onboarding — Registration is controlled through server-side invitation tokens.
  • Passkey-Centric Identity Model — Current on-chain identity flows are based on passkey credentials.
  • Locally Owned User State — User Service remains authoritative for application-level user records, roles, invitation tokens, and local account/passkey relationships.

Relationships with Other Services

  • Registry Service
    • Registers users on-chain
    • Supports on-chain identity recovery
    • Provides Core/Registry user identifiers and wallet addresses
  • Company Service
    • Provides company-related user validation
    • Supports deletion checks and role-related constraints
  • Keycloak
    • Provides external identity and passkey administration
    • Supports passkey registration, lookup, deletion, and recovery
  • Other Broker Platform Services
    • Consume user and passkey events
    • Use internal APIs to resolve user IDs, emails, and on-chain accounts
  • Kafka/Event Consumers
    • Receive user registration and passkey events
    • Provide company-originator events consumed by User Service

Documentation Sources:

  • Source: whitelabel/user-service/src/main/kotlin/
  • Controllers: whitelabel/user-service/src/main/kotlin/cz/deuss/userservice/controller/
  • Registration: .../registration/
  • Services: .../service/
  • Kafka: .../kafka/
  • Database models: .../database/model/
  • Migrations: whitelabel/user-service/src/main/resources/db/migration/
  • Public API: api-specifications/src/main/resources/whitelabel/user-service/public/user-public.openapi.yaml
  • Internal API: api-specifications/src/main/resources/whitelabel/user-service/internal/user-internal.openapi.yaml
  • Configuration: whitelabel/user-service/src/main/resources/application.yaml
  • Container: whitelabel/user-service/Dockerfile
  • Build dependencies: whitelabel/user-service/build.gradle.kts