novactl - Boilerplate CLI with Keycloak Device Flow Auth
novactl serves as a production-ready boilerplate for building Python Command-Line Interface (CLI) applications that require secure authentication against Keycloak (or potentially other OIDC providers) using the OAuth 2.0 Device Authorization Grant. It leverages Typer for the CLI framework, Rich for enhanced terminal output, and keyring for secure local token storage.
This project provides the core authentication logic (login, logout, status, token validation, refresh, secure storage) so you can focus on building your CLI's specific commands.
Features
- Secure Authentication: Uses Keycloak's OAuth 2.0 Device Authorization Grant, suitable for headless or terminal-based applications.
- Token Management: Handles access, ID, and refresh tokens.
- Automatic Refresh: Attempts to automatically refresh expired access tokens using the refresh token.
- Secure Storage: Stores tokens securely in the system's native keyring (macOS Keychain, Windows Credential Manager, GNOME Keyring, etc.).
- Configuration: Uses a clear YAML configuration file (
~/.config/novactl/novactl.ymlby default) with schema validation. - Robust: Includes network retry logic, error handling, and structured logging.
- Modern CLI: Built with Typer and Rich for a great developer and user experience.
- Boilerplate Ready: Designed to be easily adapted for your own CLI application.
Installation
Prerequisites
- Python 3.8+
pip(Python package installer)- A compatible system keyring backend (most modern OSs have one built-in).
From PyPI (Recommended for Users)
# Ensure you have the latest pip
pip install --upgrade pip
pip install novactl
From Source (Development)
- Clone the repository:
git clone https://github.com/c0mpiler/novactl.git cd novactl
- Install in editable mode with development dependencies:
pip install -e ".[dev]"
Configuration
Initial Setup
On the first run of any command requiring configuration (like login), novactl will create a default configuration file at ~/.config/novactl/novactl.yml if one doesn't exist.
You MUST edit this file to provide your specific Keycloak instance details:
# ~/.config/novactl/novactl.yml
# --- Required Keycloak Settings --- #
# Base URL of the Keycloak server (e.g., https://keycloak.example.com)
keycloak_server_url: YOUR_KEYCLOAK_SERVER_URL_HERE
# The Keycloak realm name to authenticate against.
keycloak_realm: YOUR_KEYCLOAK_REALM_HERE
# The Client ID registered in Keycloak for this CLI application.
keycloak_client_id: YOUR_CLI_CLIENT_ID_HERE
# --- Optional Settings (Defaults shown) --- #
# Space-separated list of additional OAuth scopes to request during login.
# 'offline_access' is crucial for getting refresh tokens for persistent sessions.
# Default: "openid email profile offline_access"
# additional_scopes: openid email profile offline_access custom_scope
# The service name used when storing tokens in the system keyring.
# Changing this isolates tokens if multiple instances use this boilerplate.
# Default: "novactl"
# keyring_service_name: my-awesome-cli
# Leeway (seconds) for token expiration validation to handle clock skew.
# Default: 60
# token_leeway_seconds: 60
# Verify server SSL/TLS certificates. Set to false ONLY for trusted dev environments.
# Can also be a path to a custom CA bundle file.
# Default: true
# ssl_verify: true
# Application log level for file logging (~/.config/novactl/novactl.log).
# Options: DEBUG, INFO, WARNING, ERROR, CRITICAL
# Default: WARNING
# log_level: DEBUG
Keycloak Client Configuration
The keycloak_client_id you configure must correspond to a public client in your Keycloak realm. Critical settings include:
- Client type:
OpenID Connect - Client ID: (Matches
keycloak_client_idinnovactl.yml) - Client authentication:
Off(It's a public client) - Authorization:
Off - Authentication flow: Ensure
Standard flowandDirect grantare enabled. Most importantly:- Device authorization grant:
On
- Device authorization grant:
- Redirect URIs / Web Origins: Typically not required for device flow.
Usage
Get help:
novactl --help
Authentication Commands
novactl login: Initiates the browser-based device flow. Follow on-screen instructions.novactl logout: Clears local tokens from the keyring and provides the Keycloak logout URL.novactl status: Checks if logged in and if the current tokens are valid (attempts refresh if needed).novactl whoami: Displays user information from the ID token.novactl get-roles: Shows roles assigned to the user from the access token.novactl tkn [access|id|refresh] [--decode]: Displays the specified token (raw or decoded).
Example Session
# 1. Login
novactl login
# Follow browser prompts...
# Output: Login successful. Welcome, <username>!
# 2. Check status
novactl status
# Output: Status: Logged in and session appears valid.
# Session valid for approx: 0:04:55
# 3. See user info
novactl whoami
# Output: Displays table with user details...
# 4. View raw access token
novactl tkn
# Output: Raw JWT...
# 5. Decode ID token
novactl tkn id --decode
# Output: Decoded JSON payload...
# 6. Logout
novactl logout
# Output: Local session cleared. ... [Optional Logout URL]
Using as a Boilerplate / Template
- Fork or Copy: Fork this repository or copy the
src/directory into your project. - Rename Package:
- Update the
[project.name]inpyproject.tomlto your CLI's name (e.g.,my-cli). - Update the script name in
[project.scripts](e.g.,my-cli = nova_controller_cli.main:app). - Consider renaming the
src/nova_controller_clidirectory tosrc/my_cliand update imports accordingly (inmain.py,tests/, etc.). - Change
keyring_service_nameinconfig.py(ornovactl.yml) to avoid conflicts.
- Update the
- Customize
main.py:- Keep the
main_callbackand_ensure_authenticatedhelper. - Keep the auth commands (
login,logout,status,whoami,get-roles,tkn) as they are useful for managing authentication. - Add your own commands: Use the
@app.command()decorator to add commands specific to your application's functionality. Protect commands requiring authentication by calling_ensure_authenticated("your-command-name")at the beginning. - Access Tokens: Inside your authenticated commands, use
auth.get_tokens()to retrieve the current valid tokens. The access token (tokens['access_token']) can then be used inAuthorization: Bearer <token>headers when making API calls.
- Keep the
- Update
pyproject.toml: Modify authors, description, keywords, URLs, and classifiers. - Update
README.md: Tailor the README to your specific CLI application. - Update
LICENSE: Ensure the license file reflects your chosen license (if different from MIT). - Review
config.py: Adjust default config values or logging setup if necessary.
Contributing
Contributions to improve this boilerplate are welcome! Please fork the repository, create a feature branch, add tests, and submit a pull request.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Metadata
Release files for novactl 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| novactl-0.1.1.tar.gz | 32.1 kB | With provenance | Details for novactl-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| novactl-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for novactl-0.1.1-py3-none-any.whl |
Total release size: 58.0 kB
Release files / novactl-0.1.1.tar.gz
| Download URL | novactl-0.1.1.tar.gz |
|---|---|
| Size | 32.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a48e8e802ef841dce2b8613a48b384133d869d30fec052d2237ae87986734b84
|
|
BLAKE2b-256 checksum How to use checksums |
e643c48cc84443750255c009fc4599cc153011562c244f0cf21e923e55a74621
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 26, 2025.
Transparency logRelease files / novactl-0.1.1-py3-none-any.whl
| Download URL | novactl-0.1.1-py3-none-any.whl |
|---|---|
| Size | 25.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
71c7b80d97a3646535496a098b49be24c7fed17fd0afcb7700915f02e0d1e952
|
|
BLAKE2b-256 checksum How to use checksums |
c0b59b2f092518bd0e4a38c6ed01dd2a97917cad13166b5eaa2d62a95c710ce7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 26, 2025.
Transparency logSecurity for novactl 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for novactl-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 26, 2025.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.