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
ADMINandORIGINATORroles - 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 informationdeuss_user_role— User roles and role assignmentsinvite_token— Invitation tokens used during onboardingdeuss_user_onchain_account— User-owned blockchain accountsdeuss_passkey— Passkey credentials linked to on-chain accountsidentity_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
| Endpoint | Method | Purpose |
|---|---|---|
/users/me | GET | Retrieve the currently authenticated user |
/users/me | PATCH | Update the current user's profile |
/users/me | DELETE | Delete the current user's account when permitted |
/admin/users | GET | List users with pagination and email filtering |
/admin/users/{id} | GET | Retrieve a user by ID |
/admin/users/{id} | PATCH | Update a user by ID |
/admin/users/{id} | DELETE | Delete a user by ID |
/find | POST | Resolve a user ID from an email address |
/users/{id}/accounts | GET | Retrieve a user's on-chain accounts |
Registration and Invitations
| Endpoint | Method | Purpose |
|---|---|---|
/auth/register | POST | Register a user using an invitation token |
/admin/invites | GET | List invitation tokens |
/admin/invites/generate | POST | Generate invitation token(s) |
/invites/verify | POST | Verify whether an invitation token is valid |
/admin/invites/{token} | DELETE | Revoke an invitation token |
Roles
| Endpoint | Method | Purpose |
|---|---|---|
/admin/users/{id}/roles/admin | POST | Assign the ADMIN role |
/admin/users/{id}/roles/admin | DELETE | Remove the ADMIN role |
/users/{id}/roles/originator | POST | Assign the ORIGINATOR role |
/users/{id}/roles/originator | DELETE | Remove the ORIGINATOR role |
Identity Verification and Recovery
| Endpoint | Method | Purpose |
|---|---|---|
/users/identity_verification_records | POST | Create an identity-verification record |
/users/me/recovery | POST | Start recovery of the current user's passkey/on-chain identity |
Internal REST API
The internal API is defined in user-internal.openapi.yaml.
| Endpoint | Method | Purpose |
|---|---|---|
/api/internal/users | GET | Retrieve basic data for multiple users |
/api/internal/users/{id} | GET | Retrieve a user by ID |
/api/internal/users/{id}/accounts | GET | Retrieve a user's on-chain accounts |
/api/internal/users/email/{email} | GET | Resolve user data by email |
/api/internal/users/{id}/register-core | POST | Ensure the user is registered in Registry Service |
/api/internal/users/email/{email}/tokens | POST | Generate an invitation token for a new user |
Kafka Consumer
The service consumes originator-related company events.
| Topic | Event | Purpose |
|---|---|---|
OriginatorEvents.UPDATED | OriginatorEmployeeEvent | Assign 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.
| Topic | Event | Purpose |
|---|---|---|
RegistrationEvents.CREATED | RegistrationCreatedEvent | Notify other services that a user was registered |
RegistrationEvents.PASSKEY_CREATED | PasskeyCreatedEvent | Notify 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
- Registration requires an invitation token.
- Invitation tokens can be generated, verified, consumed, and revoked.
- Admin users can manage users and invitation tokens.
- Only authorized users can assign elevated roles.
- ADMIN role assignment requires an existing ADMIN user.
- ORIGINATOR role assignment can be performed by an ADMIN or ORIGINATOR user.
- A user cannot be deleted when an on-chain identity already exists.
- A user cannot be deleted while acting as an administrator in a company or originator organization.
- On-chain onboarding is idempotent.
- A newly registered user is registered with Registry Service using passkey data from Keycloak.
- Passkey recovery deactivates the current local passkey and removes Keycloak passkeys before re-registration.
- At most one active passkey exists for an on-chain account.
- Originator role assignments are synchronized from company events.
- Identity-verification records are stored historically and used to calculate the current verification state.
On-chain User Onboarding Flow
- A user completes registration using a valid invitation token.
- User Service obtains the user's passkey from Keycloak.
- User Service calls Registry Service to create the user's on-chain identity.
- Registry Service returns the Core/Registry user ID and wallet address.
- User Service stores:
- the Core/Registry user ID,
- the on-chain account,
- the passkey reference.
- User Service publishes a
PasskeyCreatedEventto Kafka. Registry Service performs the blockchain operation; User Service coordinates the workflow and stores local references.
Passkey Recovery Flow
- The user starts recovery through
/users/me/recovery. - User Service verifies that an on-chain account exists.
- The active local passkey is deactivated.
- Existing Keycloak passkeys are removed.
- The user registers a new passkey in Keycloak.
- User Service detects the new passkey.
- Registry Service is called to recover or update the on-chain identity.
- 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
VERIFIEDstate, valid from the current date for one year. Thesession_idis currently unused and reserved for a future external KYC provider integration. Supported states include: NOT_REQUESTEDPENDING_VERIFICATIONVERIFIEDFAILED
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_URLDATABASE_USERDATABASE_PASSWORDCOMPANY_SERVICE_URLREGISTRY_SERVICE_URLJWT_GENERATOR_SIGNATURE_SECRETJWT_GENERATOR_INVITE_TOKEN_EXPIRYJWT_GENERATOR_REFRESH_TOKEN_EXPIRYSMTP_HOSTSMTP_PORTSMTP_USERNAMESMTP_PASSWORDSMTP_FROM_NAMESMTP_FROM_ADDRESSKEYCLOAK_ADMIN_ENABLEDKEYCLOAK_SERVER_URLKEYCLOAK_REALMKEYCLOAK_CLIENT_IDKEYCLOAK_CLIENT_SECRETKAFKA_GROUP_IDCHAIN_ENABLEDSensitive 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
runtimeuser - Uses
tinias 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