The Keychain service provides secure storage for passwords, API tokens, and other sensitive data using the macOS Keychain. Data is encrypted at rest and protected by the system. Access it via app.keychain.
# Store a credential
app.keychain.set("MyApp", "api_token", "sk-abc123")
# Retrieve it later
token = app.keychain.get("MyApp", "api_token")
Methods¶
get(service, account)¶
Retrieve a password from the keychain.
app.keychain.get(service: str, account: str) -> str | None
| Parameter | Type | Description |
|---|---|---|
service |
str |
Service name, typically your app identifier (e.g., "com.myapp") |
account |
str |
Account name (username, email, or key identifier) |
Returns the stored password as a string, or None if no matching entry exists.
set(service, account, password)¶
Store a password in the keychain. If an entry already exists for the given service/account combination, it is updated.
app.keychain.set(service: str, account: str, password: str) -> bool
| Parameter | Type | Description |
|---|---|---|
service |
str |
Service name |
account |
str |
Account name |
password |
str |
The password or secret to store |
Returns True if stored successfully.
delete(service, account)¶
Delete a password from the keychain.
app.keychain.delete(service: str, account: str) -> bool
| Parameter | Type | Description |
|---|---|---|
service |
str |
Service name |
account |
str |
Account name |
Returns True if deleted successfully.
exists(service, account)¶
Check whether a keychain entry exists without retrieving its value.
app.keychain.exists(service: str, account: str) -> bool
| Parameter | Type | Description |
|---|---|---|
service |
str |
Service name |
account |
str |
Account name |
Returns True if the entry exists, False otherwise.
Examples¶
Store and retrieve an API token¶
import nib
def main(app: nib.App):
app.title = "Keychain"
app.icon = nib.SFSymbol("key.fill")
app.width = 340
app.height = 250
SERVICE = "com.myapp"
ACCOUNT = "api_token"
token_field = nib.SecureField(placeholder="Enter API token")
status = nib.Text("", foreground_color=nib.Color.SECONDARY)
def save_token():
if token_field.text:
success = app.keychain.set(SERVICE, ACCOUNT, token_field.text)
status.content = "Saved!" if success else "Failed to save"
else:
status.content = "Enter a token first"
def load_token():
token = app.keychain.get(SERVICE, ACCOUNT)
if token:
status.content = f"Token: {token[:8]}..."
else:
status.content = "No token stored"
def delete_token():
success = app.keychain.delete(SERVICE, ACCOUNT)
status.content = "Deleted" if success else "Nothing to delete"
app.on_appear = load_token
app.build(
nib.VStack(
controls=[
nib.Text("API Token Manager", font=nib.Font.HEADLINE),
token_field,
nib.HStack(
controls=[
nib.Button("Save", action=save_token, style=nib.ButtonStyle.BORDERED_PROMINENT),
nib.Button("Load", action=load_token, style=nib.ButtonStyle.BORDERED),
nib.Button("Delete", action=delete_token, role=nib.ButtonRole.DESTRUCTIVE),
],
spacing=8,
),
status,
],
spacing=12,
padding=20,
)
)
nib.run(main)
Login form with keychain persistence¶
import nib
def main(app: nib.App):
app.title = "Login"
app.icon = nib.SFSymbol("person.crop.circle")
app.width = 320
app.height = 220
SERVICE = "com.myapp.login"
username = nib.TextField(placeholder="Username")
password = nib.SecureField(placeholder="Password")
status = nib.Text("", foreground_color=nib.Color.SECONDARY)
def login():
if username.text and password.text:
# Save credentials for next session
app.keychain.set(SERVICE, "username", username.text)
app.keychain.set(SERVICE, "password", password.text)
status.content = f"Logged in as {username.text}"
def load_saved():
saved_user = app.keychain.get(SERVICE, "username")
if saved_user:
username.text = saved_user
status.content = "Loaded saved credentials"
app.on_appear = load_saved
app.build(
nib.Form(
controls=[
username,
password,
nib.Button("Login", action=login, style=nib.ButtonStyle.BORDERED_PROMINENT),
status,
],
padding=20,
)
)
nib.run(main)