Repository navigation
Keep secrets
Tokens and passwords belong in the credential store of the system, which encrypts them for the user and keeps them from other users, and not in a file or a row of the store. In this guide, a mail application saves an API token, shows that it has one, and forgets it.

The secrets belong to the application by its name, so the application needs one:
public class Vault {
public static void main(String[] args) {
ApplicationParameters parameters = ApplicationParameters.builder().name("Mail").build();
try (Application application = Application.create(parameters)) {
Secrets secrets = application.secrets();
application.bind(
"saveToken",
String.class,
token -> {
secrets.set("api-token", token);
return null;
});
application.bind("savedToken", Void.class, _ -> secrets.get("api-token").orElse(null));
application.bind("forgetToken", Void.class, _ -> secrets.delete("api-token"));
application.show(
WindowParameters.builder()
.title("Mail")
.size(new WindowSize(560, 380))
.resource("secrets/index.html")
.build());
application.run();
}
}
}| Method | What it does |
|---|---|
set(key, value) |
Saves value under key, in place of the value that was there. |
get(key) |
Returns the value, or an empty Optional when there is none. |
delete(key) |
Deletes the value, and returns whether there was one. |
A value takes at most Secrets.MAXIMUM_SIZE, 2560 bytes in UTF-8: the limit of the Credential
Manager of Windows, kept on every platform, so that what works on one works on all. A longer value
or a blank key throws IllegalArgumentException. If the system refuses, for example because the
user didn't unlock the store, the call throws SecretStoreFailedException.
The page asks Java whether a token is saved, and shows only its end:
const show = (token) => {
document.querySelector("#status").textContent = token === null
? "No token is saved."
: `A token is saved: ${"•".repeat(8)}${token.slice(-4)}`;
};
window.savedToken().then(show);
document.querySelector("#save").addEventListener("submit", async (event) => {
event.preventDefault();
const token = document.querySelector("#token").value;
await window.saveToken(token);
document.querySelector("#token").value = "";
show(await window.savedToken());
});There is no lwjwae.secrets on the page, on purpose: a secret that the page can read is a secret
that every script on the page can read. Bind what the page needs, such as a call that signs a
request with the token, and keep the token itself in Java.
| Platform | Where the secret goes |
|---|---|
| Windows | A generic credential of the Credential Manager, named APPLICATION/KEY, such as Mail/api-token. |
| macOS | A generic password of the login keychain, with the application as the service and the key as the account. |
| Linux | A password of the Secret Service, such as GNOME Keyring or KWallet, through libsecret, with the application and the key as its attributes. |
- A call blocks until the system answers, and the system can first ask the user to unlock the store. A handler of a binding runs on a virtual thread of its own, so it can call it; on the UI thread, don't.
- On Linux, the desktop needs a running Secret Service. GNOME and KDE Plasma start one with the session; a minimal window manager might not.
- On Windows,
cmdkey /list:Mail*lists the secrets of the application, and Credential Manager in the Control Panel shows them under Windows Credentials.
Tutorial
- Set up the project
- Open a window
- Call Java from the page
- Send events from Java to the page
- Draw your own title bar
- Export notes through a native dialog
- Keep the application in the tray
- Show notifications
- Give the application an icon and a name
- Build a native executable
- Package the application
Guides
- Pass objects through the bridge
- Stream bytes between the page and Java
- Open several windows
- Place and control a window
- Make a transparent window
- Add menus
- Register global shortcuts
- Show progress in the taskbar
- Use the clipboard
- Handle dropped files
- Zoom the page
- Set the window icon
- Follow the theme of the desktop
- Use cookies
- Store data in SQLite
- Keep secrets
- Show dialogs
- Run a single instance
- Open your own links and files
- Update the application
- Handle page permissions
- Handle links and page loads
Reference