Boilerplate CLI with Keycloak/OAuth2 Device Flow Authentication using Typer and Rich.
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file novactl-0.1.1.tar.gz.
File metadata
- Download URL: novactl-0.1.1.tar.gz
- Upload date:
- Size: 32.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a48e8e802ef841dce2b8613a48b384133d869d30fec052d2237ae87986734b84
|
|
| MD5 |
267b5459d0c9f74a87092bfae85ee04a
|
|
| BLAKE2b-256 |
e643c48cc84443750255c009fc4599cc153011562c244f0cf21e923e55a74621
|
Provenance
The following attestation bundles were made for novactl-0.1.1.tar.gz:
Publisher:
publish.yml on c0mpiler/novactl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
novactl-0.1.1.tar.gz -
Subject digest:
a48e8e802ef841dce2b8613a48b384133d869d30fec052d2237ae87986734b84 - Sigstore transparency entry: 203202912
- Sigstore integration time:
-
Permalink:
c0mpiler/novactl@38df209c2ffb309257b6f65f8ec3d3abfb879abd -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/c0mpiler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@38df209c2ffb309257b6f65f8ec3d3abfb879abd -
Trigger Event:
push
-
Statement type:
File details
Details for the file novactl-0.1.1-py3-none-any.whl.
File metadata
- Download URL: novactl-0.1.1-py3-none-any.whl
- Upload date:
- Size: 25.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71c7b80d97a3646535496a098b49be24c7fed17fd0afcb7700915f02e0d1e952
|
|
| MD5 |
19ba10f39518472b55cb879b2a112ca5
|
|
| BLAKE2b-256 |
c0b59b2f092518bd0e4a38c6ed01dd2a97917cad13166b5eaa2d62a95c710ce7
|
Provenance
The following attestation bundles were made for novactl-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on c0mpiler/novactl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
novactl-0.1.1-py3-none-any.whl -
Subject digest:
71c7b80d97a3646535496a098b49be24c7fed17fd0afcb7700915f02e0d1e952 - Sigstore transparency entry: 203202913
- Sigstore integration time:
-
Permalink:
c0mpiler/novactl@38df209c2ffb309257b6f65f8ec3d3abfb879abd -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/c0mpiler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@38df209c2ffb309257b6f65f8ec3d3abfb879abd -
Trigger Event:
push
-
Statement type: