{"id":9995,"library":"oathtool","title":"OATHTool","description":"oathtool is a command-line tool and Python library for generating one-time passwords, supporting both HOTP (HMAC-based) and TOTP (Time-based) algorithms. The current version is 2.4.0, and it maintains a stable, albeit infrequent, release schedule, focusing on reliability and security.","status":"active","version":"2.4.0","language":"en","source_language":"en","source_url":"https://github.com/jaraco/oathtool","tags":["security","otp","totp","hotp","authentication","2fa","cli"],"install":[{"cmd":"pip install oathtool","lang":"bash","label":"Install base library"},{"cmd":"pip install 'oathtool[cli]'","lang":"bash","label":"Install with CLI extras (keyring, clipboard)"}],"dependencies":[{"reason":"Used for secure storage of keys in some CLI operations.","package":"keyring","optional":true},{"reason":"Used for clipboard interaction in some CLI operations.","package":"jaraco.clipboard","optional":true}],"imports":[{"note":"TOTP is located in the `oathtool.totp` submodule, not directly under `oathtool`.","wrong":"import oathtool; oathtool.TOTP","symbol":"TOTP","correct":"from oathtool.totp import TOTP"},{"note":"HOTP is located in the `oathtool.hotp` submodule, not directly under `oathtool`.","wrong":"import oathtool; oathtool.HOTP","symbol":"HOTP","correct":"from oathtool.hotp import HOTP"}],"quickstart":{"code":"import os\nfrom oathtool.totp import TOTP\n\n# Retrieve your base32-encoded secret key from an environment variable.\n# Example: 'JBSWY3DPEHPK3PXP' (this is a placeholder, use your actual secret)\nsecret_base32 = os.environ.get('OATHTOOL_SECRET', 'JBSWY3DPEHPK3PXP')\n\nif secret_base32 == 'JBSWY3DPEHPK3PXP':\n    print(\"WARNING: Using a placeholder secret. Set OATHTOOL_SECRET environment variable for actual use.\")\n\ntry:\n    # Initialize the TOTP generator with your secret.\n    # oathtool expects the secret to be base32-encoded or raw bytes.\n    # If a base32 string is provided, it will be decoded automatically.\n    totp = TOTP(secret_base32)\n\n    # Generate the current time-based one-time password.\n    current_otp = totp.code()\n    print(f\"Generated TOTP: {current_otp}\")\n\n    # You can also get the remaining time until the next code.\n    # time_left = totp.time_left()\n    # print(f\"Time left until next code: {time_left} seconds\")\n\nexcept Exception as e:\n    print(f\"Error generating OTP: {e}\")\n    print(\"Ensure your OATHTOOL_SECRET is a valid base32 encoded string.\")","lang":"python","description":"This quickstart demonstrates how to generate a TOTP code using a base32-encoded secret key, typically obtained from a 2FA setup process. It emphasizes retrieving the secret securely from an environment variable and includes basic error handling for common key issues."},"warnings":[{"fix":"Ensure your secret key is a valid base32-encoded string (e.g., from a QR code or provided by the service). Tools like `base64.b32decode` can verify format.","message":"Secret keys are typically expected to be base32-encoded strings. While `oathtool` can often handle raw bytes or attempt decoding, providing an invalid base32 string will lead to errors.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always store secret keys securely. Use environment variables (as shown in quickstart), dedicated secret management services, or secure configuration files. For CLI, `oathtool` offers keyring integration.","message":"Hardcoding secret keys directly in your code is a significant security risk. Anyone with access to your code can compromise your accounts.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Implement a robust mechanism to store and increment the HOTP counter reliably. Both client and server must agree on the current counter value. If out of sync, a resynchronization process is usually required.","message":"When using HOTP, the 'counter' value must be meticulously synchronized between the client (your application) and the server. Desynchronization will lead to invalid codes.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Import TOTP from its specific submodule: `from oathtool.totp import TOTP`.","cause":"You are trying to import TOTP directly from the top-level `oathtool` module.","error":"AttributeError: module 'oathtool' has no attribute 'TOTP'"},{"fix":"Verify that your secret key is a correctly formatted base32 string. It should only contain A-Z, 2-7, and optionally padding '=' characters.","cause":"The secret string provided to `TOTP` or `HOTP` constructor is not a valid base32 encoding.","error":"ValueError: Invalid base32 secret"},{"fix":"Pass your base32-encoded secret key as the first argument to the constructor, e.g., `TOTP('YOUR_SECRET_KEY')`.","cause":"No secret key was provided when initializing the `TOTP` or `HOTP` object.","error":"TypeError: oathtool.totp.TOTP.__init__() missing 1 required positional argument: 'key'"}]}