Secrets and Keys
Every installation from the Full Stack Quick Start starts with the same tokens, keys, and passwords. Anyone with access to the quick start files knows them. Replace them before you store real data or expose your installation to a network.
This page lists every secret in the starter setup, what it protects, and what happens when you change it. Some secrets are replaced as part of another step, such as connecting your own identity provider or database. Those are listed here and covered in detail on their own pages.
Overview
| Secret | Service | Effect of changing it |
|---|---|---|
| Key storage encryption key | Core | Set once. Keys stored before the change can no longer be read. |
| OpenID4VCI encryption keys | Core | Held credentials can no longer be refreshed or reissued. |
| OpenID4VCI nonce signing keys | Core | In-progress issuance flows fail. Safe to change any time. |
| STS signing key | BFF | Operator sessions and service tokens are invalidated. |
| WRPR signing key | WRPR | Public API responses are signed with the new key. |
| Static tokens | Core, Bridge, WRPR | Callers fail until updated with the new token. |
| Session cookie secret | oauth2-proxy | Operators are signed out. |
| Identity provider credentials | Keycloak, all services | Sign-in and technical user tokens fail until updated. |
| Database and cache credentials | Databases, Redis | Services cannot connect until updated. |
Generating values
Generate a new value for every secret. Do not reuse values across secrets or across environments.
| Kind | Command |
|---|---|
| 32-byte hex key or token | openssl rand -hex 32 |
| Ed25519 private key, PKCS #8, one line | openssl genpkey -algorithm ed25519 | tr '\n' ' ' |
| oauth2-proxy cookie secret | openssl rand -base64 32 | tr -- '+/' '-_' |
| Password | openssl rand -base64 24 |
Write private keys on a single line, as the command above produces:
sts.token.privateKey="-----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEI... -----END PRIVATE KEY-----"
Core encryption keys
Core encrypts sensitive data with keys from its configuration. Core does not start if a required key is missing.
Key storage encryption key
Encrypts private keys held in INTERNAL key storage.
ONE_keyStorage__INTERNAL__params__private__encryption="<32-byte hex>"
Set this key before you create any keys, and do not change it afterwards. Keys stored before a change can no longer be read, and there is currently no procedure for re-encrypting them.
Store this key in a secure location outside your installation. If it is
lost, keys in INTERNAL storage cannot be recovered.
OpenID4VCI encryption keys
When Core holds credentials, these keys encrypt the access and refresh tokens it receives from issuers. Each OpenID4VCI issuance protocol instance requires its own key:
ONE_issuanceProtocol__OPENID4VCI_FINAL1__params__private__encryption="<32-byte hex>"
ONE_issuanceProtocol__OPENID4VCI_FINAL1_SWIYU__params__private__encryption="<32-byte hex>"
ONE_issuanceProtocol__OPENID4VCI_FINAL1_HAIP__params__private__encryption="<32-byte hex>"
If you change a key, stored tokens can no longer be used. Credentials already held continue to work, but they can no longer be refreshed and new batches cannot be requested.
OpenID4VCI nonce signing keys
Sign the nonces used during issuance. Each OpenID4VCI issuance protocol instance requires its own key:
ONE_issuanceProtocol__OPENID4VCI_FINAL1__params__private__nonce__signingKey="<32-byte hex>"
ONE_issuanceProtocol__OPENID4VCI_FINAL1_SWIYU__params__private__nonce__signingKey="<32-byte hex>"
ONE_issuanceProtocol__OPENID4VCI_FINAL1_HAIP__params__private__nonce__signingKey="<32-byte hex>"
Changing a key only affects issuance flows in progress at the time of the change.
Signing keys
The BFF and WRPR sign tokens and responses with Ed25519 private keys in PKCS #8 format.
STS signing key
The BFF signs the tokens issued by its Secure Token Service (STS) with this key:
sts.token.privateKey="<Ed25519 private key, one line>"
Changing the key invalidates all operator sessions and issued STS tokens. Services that validate STS tokens cache the BFF's public keys, so tokens signed with the previous key may be accepted for a short time after the change.
WRPR signing key
WRPR signs its public API responses with this key:
public.api.signing.privateKey="<Ed25519 private key, one line>"
After a change, WRPR signs all new responses with the new key.
Static tokens
In the starter setup, Core, Bridge, and WRPR accept requests authenticated with a static token. Each token appears in the receiving service's configuration and in the configuration of every service that calls it. Change all occurrences together:
| Token | Set in the service | Set in each caller |
|---|---|---|
| Core | ONE_app__auth__staticToken (.core.env) | core.api.staticToken (.bff.env, .bridge.env, .wrpr.env) |
| Bridge | auth.staticToken (.bridge.env) | bridge.api.staticToken (.bff.env) |
| WRPR | auth.staticToken (.wrpr.env) | wrpr.api.staticToken (.bff.env) |
Static tokens are for development and testing. For production, replace them with STS authentication.
Session cookie secret
oauth2-proxy encrypts operator session cookies with cookie_secret in
oauth2-proxy.cfg. Changing it signs out all operators.
Identity provider credentials
The services authenticate to the identity provider with client secrets:
| Client | Where the secret is set |
|---|---|
| Login client, used by oauth2-proxy | clientSecret (alpha-config.yml) |
| Technical client, used by BFF, Bridge, and WRPR | auth.technicalUserCredentials.clientSecret (.bff.env); spring.security.oauth2.client.registration.keycloakClient.client-secret (.bridge.env, .wrpr.env) |
When you connect your own identity provider, it issues new client secrets.
Starter Keycloak
If you keep the starter Keycloak running while you test, change its shared defaults in the Keycloak admin console:
Change the admin password. The default is
admin/admin.Change the password of
example_user, or delete the user.Regenerate the secrets of
login-clientandone-bff, then update the files listed above.
Database and cache credentials
Each database has a user password and a root password. The user password appears in both the database's configuration and the service's configuration:
| Database | Database configuration | Service configuration |
|---|---|---|
| Core | .core_mariadb.env | ONE_app__databaseUrl (.core.env) |
| BFF | .bff_mariadb.env | MYSQL_PASSWORD (.bff.env) |
| Bridge | .bridge_mariadb.env | MYSQL_PASSWORD (.bridge.env) |
| WRPR | .wrpr_mariadb.env | MYSQL_PASSWORD (.wrpr.env) |
| Keycloak | .keycloak_postgres.env | KEYCLOAK_DATABASE_PASSWORD (.keycloak.env) |
Redis runs without a password in the starter setup.
The database images set passwords only when the database is first created. To change passwords on an existing database, change them in the database as well. See Databases.
Feature-specific secrets
Some features require credentials for external services. They are empty in the starter setup and only needed if you enable the feature:
- Remote key storage (
keyStorage, for example Azure Key Vault): client credentials for the vault. - QES document signing (
documentSignerProvider): client credentials for the signing provider. See Wallet-Centric Approach. - Email (
spring.mail.username,spring.mail.passwordin.bff.env): SMTP credentials.
Where to keep secrets
The quick start stores secrets in plain text in configuration and environment files. For any shared or long-running installation:
- Do not commit files that contain real secrets to version control.
- Supply secrets from your platform's secret store, such as Docker secrets, Kubernetes secrets, or a vault.
- Keep secrets separate from other configuration, so the rest of your configuration can be shared and versioned.
For Core, one way to keep secrets separate is a dedicated configuration
file passed as the last --config. Core merges it like any other layer.
See Configuring Your Installation.