authentication

OTP Tokens

Manage one-time password tokens for two-factor authentication. OTP tokens provide TOTP (time-based) and HOTP (counter-based) authentication for users. Features include token creation and import, QR code generation for mobile authenticator apps, token synchronization, enable/disable controls, token removal, and support for hardware tokens and software authenticators.

7 commands
authentication

Overview

OTP (One-Time Password) tokens provide two-factor authentication (2FA) for FreeIPA users, significantly enhancing security beyond password-only authentication. When OTP authentication is enabled, users must provide both their password and a time-limited or counter-based code from their OTP token to authenticate successfully.

FreeIPA supports two OTP algorithms standardized by the IETF:

TOTP (Time-Based One-Time Password, RFC 6238): Generates codes that change every 30 seconds (default) based on synchronized time between the token and the IPA server. Most commonly used with mobile authenticator apps like Google Authenticator, FreeOTP, or Authy.

HOTP (HMAC-Based One-Time Password, RFC 4226): Generates codes based on an incrementing counter. Each code can be used only once, but codes don’t expire based on time. Commonly used with hardware tokens that have a button to generate the next code.

OTP tokens in IPA can be self-enrolled by users (via the web UI or API) or centrally provisioned by administrators. Tokens support metadata including vendor, model, and serial number for inventory management of hardware tokens, and can be temporarily or permanently disabled without deletion.

Token Types

TOTP (Time-Based)

TOTP tokens generate time-synchronized codes that expire after a fixed interval (default 30 seconds). This is the most common OTP type and works well with mobile authenticator applications.

Advantages:

  • No server state to maintain (stateless verification)
  • Widely supported by authenticator apps
  • Natural expiration prevents replay attacks

Challenges:

  • Requires time synchronization between token and server
  • Clock skew can cause authentication failures
  • Uses configurable time offset to accommodate minor clock differences

Default parameters:

  • Algorithm: SHA-1 (also supports SHA-256, SHA-512)
  • Digits: 6 (also supports 8)
  • Interval: 30 seconds
  • Offset: 0 seconds (auto-adjusted after first successful authentication)

HOTP (Counter-Based)

HOTP tokens generate codes based on an incrementing counter value. Each code is used once, and the token advances to the next counter value when the user generates a new code.

Advantages:

  • No time synchronization required
  • Works in environments with unreliable clocks
  • Hardware tokens often use HOTP

Challenges:

  • Server must track and store the current counter value
  • Counter can drift if user generates codes without using them
  • Synchronization window required (IPA checks 10 codes ahead by default)

Default parameters:

  • Algorithm: SHA-1
  • Digits: 6
  • Initial counter: 0

Token Lifecycle

Provisioning

Self-enrollment (users create their own tokens):

  • User initiates token creation via WebUI or CLI
  • IPA generates a random secret key
  • User scans QR code or manually enters key into authenticator app
  • User verifies token works by authenticating

Administrative provisioning (admins create tokens for users):

  • Administrator creates token with --owner=username
  • Admin provides QR code or secret key to user securely
  • User configures authenticator app
  • User verifies token works

Hardware token import:

  • Administrator creates token with pre-shared key from vendor
  • Token is assigned to user
  • User receives physical hardware token
  • Metadata (vendor, model, serial) tracks inventory

Active Use

  • User authenticates with password + OTP code
  • IPA validates OTP code against stored token secret
  • For TOTP: IPA checks current time window ± offset
  • For HOTP: IPA checks counter value + lookahead window
  • Successful authentication updates offset (TOTP) or counter (HOTP)

Temporary Disable

Tokens can be disabled without deletion:

  • Lost hardware token (pending replacement)
  • Compromised token (pending investigation)
  • User on leave (temporary access suspension)

Disabled tokens remain in the directory and can be re-enabled.

Permanent Removal

Deleting a token permanently removes it from the directory:

  • Revoke lost/stolen hardware tokens
  • Clean up after replacing user’s device/app
  • Remove tokens for departed users

Deletion is immediate and irreversible.

Token Management

Ownership and Self-Service

Each token has an owner (the user who authenticates with it). Owners can:

  • View their own tokens
  • Delete their own tokens (if self-service is enabled)
  • Cannot modify token parameters (algorithm, digits, interval)

Administrators can manage all tokens via CLI or WebUI.

Managed-By Delegation

Tokens support a managed-by relationship, allowing specific users to manage tokens on behalf of owners:

# Allow helpdesk staff to manage tokens for users
$ ipa otptoken-add-managedby <token-id> --users=helpdesk-user

Managers can:

  • Disable/enable the token
  • View token metadata
  • Delete the token
  • Cannot view the secret key (never retrievable after creation)

This enables helpdesk workflows where support staff assist users with token issues without requiring full administrative privileges.

Token Metadata

Tokens support informational metadata useful for inventory management:

Vendor (--vendor): Token manufacturer (e.g., “Yubico”, “RSA”, “Google”) Model (--model): Specific token model (e.g., “YubiKey 5”, “FreeOTP”) Serial (--serial): Hardware token serial number for tracking Description (--desc): Free-form notes (e.g., “iPhone 12 Pro”, “Backup hardware token”)

Time Validity Windows

Tokens can have enforced validity periods:

Not Before (--not-before): Token cannot be used before this date/time. Useful for pre-provisioned tokens that activate on a user’s start date.

Not After (--not-after): Token cannot be used after this date/time. Useful for temporary access (contractors, visitors) or enforcing token replacement schedules.

Format: YYYY-MM-DD HH:MM:SS or generalized time.

QR Code Generation

When creating TOTP tokens, IPA generates a QR code containing the secret key in otpauth:// URI format:

otpauth://totp/alice@EXAMPLE.COM?secret=JBSWY3DPEHPK3PXP&issuer=EXAMPLE.COM&algorithm=SHA1&digits=6&period=30

Users scan this QR code with mobile authenticator apps for automatic configuration. If QR code scanning isn’t available, the Base32-encoded secret can be manually entered.

The --no-qrcode option suppresses QR code display (useful for scripted token provisioning where the QR is delivered through another channel).

Token Synchronization

TOTP Time Offset

TOTP tokens can drift from server time due to clock skew on the user’s device. IPA automatically learns and compensates for this drift:

Initial offset: 0 seconds (assumes synchronized time) Auto-adjustment: After first successful authentication, IPA calculates the time difference Stored offset: Saved with the token to accommodate future authentications Tolerance window: IPA accepts codes within ±2 intervals (default: ±60 seconds)

Manual offset can be set with --offset=N if clock skew is known.

HOTP Counter Synchronization

HOTP tokens maintain a counter that must stay synchronized between the token and IPA:

Counter drift: Occurs when users generate codes without using them (e.g., testing, accidental button press) Lookahead window: IPA checks the expected counter plus the next 10 values Re-synchronization: If a code within the lookahead window succeeds, IPA updates the stored counter Manual reset: Administrators can reset counter to a known value if synchronization fails

Security Considerations

Secret Key Protection

The token secret key is the critical security component:

  • Generated randomly by IPA (or provided for hardware tokens)
  • Never displayed after initial token creation (even to administrators)
  • Stored encrypted in the LDAP directory
  • Cannot be retrieved; lost secrets require token replacement

Authentication Factor Requirements

OTP tokens provide the “something you have” factor. Combined with passwords (“something you know”), this achieves true two-factor authentication.

FreeIPA’s authentication configuration determines enforcement:

  • Password only: Traditional single-factor (default for new users)
  • OTP only: Unusual; requires token without password
  • Password + OTP: True two-factor (recommended for high-security environments)
  • Password or OTP: Either factor suffices (used during migration periods)

See otpconfig and user-mod --user-auth-type for authentication type configuration.

Token Disablement

Disable tokens immediately when:

  • User reports lost/stolen device or hardware token
  • Suspected token compromise
  • User employment terminates (before account deletion)
  • Device replacement (disable old token when provisioning new)

Disabled tokens fail authentication but remain in the directory for audit trails.

Multiple Tokens per User

Users can have multiple active tokens:

  • Primary token (daily use on phone)
  • Backup token (separate device or hardware token)
  • Emergency token (paper printout or secure storage)

During authentication, IPA tests all active tokens; any valid code succeeds. This provides resilience against lost devices without compromising security.

Examples

Create TOTP Token for User

# Admin creates token for a user
$ ipa otptoken-add --type=totp --owner=alice --desc="Alice's iPhone FreeOTP"
  Unique ID: 7b3a9c2e-4f1d-11ee-be56-0242ac120002
  Type: TOTP
  Owner: alice
  Description: Alice's iPhone FreeOTP
  Algorithm: SHA1
  Digits: 6
  Interval: 30

  [QR code displayed for scanning]
  Secret (Base32): JBSWY3DPEHPK3PXP

User Self-Enrollment (from WebUI or API)

# User creates their own token (must authenticate first)
$ kinit alice
$ ipa otptoken-add --type=totp --desc="Google Authenticator on Pixel"
  [QR code displayed]

Create HOTP Hardware Token

# Import hardware token with known secret from vendor
$ ipa otptoken-add --type=hotp \
  --owner=bob \
  --desc="YubiKey hardware token" \
  --vendor="Yubico" \
  --model="YubiKey 5" \
  --serial="5438291" \
  --key="GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ" \
  --digits=6 \
  --counter=0

Create Token with Time Validity

# Token valid only during contractor engagement
$ ipa otptoken-add --type=totp \
  --owner=contractor1 \
  --desc="Contractor access token" \
  --not-before="2024-01-01 00:00:00" \
  --not-after="2024-12-31 23:59:59"

Create Token Without QR Code

# For automated provisioning where QR is delivered separately
$ ipa otptoken-add --type=totp \
  --owner=charlie \
  --desc="Automated provisioning" \
  --no-qrcode

List All Tokens

# Show all OTP tokens in IPA
$ ipa otptoken-find
  3 tokens matched
  Unique ID: 7b3a9c2e-4f1d-11ee-be56-0242ac120002
  Owner: alice
  Type: TOTP
  Unique ID: 8c4b0d3f-4f1d-11ee-be56-0242ac120003
  Owner: bob
  Type: HOTP

List Tokens for Specific User

# Show all tokens owned by alice
$ ipa otptoken-find --owner=alice

Show Token Details

# View full token information
$ ipa otptoken-show 7b3a9c2e-4f1d-11ee-be56-0242ac120002
  Unique ID: 7b3a9c2e-4f1d-11ee-be56-0242ac120002
  Type: TOTP
  Owner: alice
  Description: Alice's iPhone FreeOTP
  Disabled: FALSE
  Algorithm: SHA1
  Digits: 6
  Interval: 30
  Offset: +5 seconds
  Managed by: helpdesk

Disable Token Temporarily

# User reports lost phone; disable token pending replacement
$ ipa otptoken-mod 7b3a9c2e-4f1d-11ee-be56-0242ac120002 \
  --disabled=TRUE

Re-enable Token

# User found their phone; re-enable the token
$ ipa otptoken-mod 7b3a9c2e-4f1d-11ee-be56-0242ac120002 \
  --disabled=FALSE

Update Token Description

# User upgraded phone
$ ipa otptoken-mod 7b3a9c2e-4f1d-11ee-be56-0242ac120002 \
  --desc="Alice's new iPhone 15 FreeOTP"

Delete Token

# Permanently remove token
$ ipa otptoken-del 7b3a9c2e-4f1d-11ee-be56-0242ac120002

Add Managed-By User

# Allow helpdesk to manage this token
$ ipa otptoken-add-managedby 7b3a9c2e-4f1d-11ee-be56-0242ac120002 \
  --users=helpdesk-staff

Remove Managed-By User

# Revoke helpdesk management rights
$ ipa otptoken-remove-managedby 7b3a9c2e-4f1d-11ee-be56-0242ac120002 \
  --users=helpdesk-staff

Search by Token Type

# Find all TOTP tokens
$ ipa otptoken-find --type=totp

# Find all HOTP tokens
$ ipa otptoken-find --type=hotp

Search by Vendor

# Find all Yubico hardware tokens
$ ipa otptoken-find --vendor=Yubico

Create Token with SHA-256

# Use SHA-256 instead of default SHA-1 (requires compatible authenticator app)
$ ipa otptoken-add --type=totp \
  --owner=diana \
  --desc="SHA-256 secure token" \
  --algo=sha256

Create 8-Digit Token

# Use 8 digits instead of default 6 (higher security, less user-friendly)
$ ipa otptoken-add --type=totp \
  --owner=edward \
  --desc="High-security 8-digit token" \
  --digits=8

Create Token with Custom Interval

# 60-second interval instead of default 30
$ ipa otptoken-add --type=totp \
  --owner=frank \
  --desc="Long-interval token" \
  --interval=60

Bulk Token Provisioning

# Provision tokens for multiple users
for user in alice bob charlie diana; do
  ipa otptoken-add --type=totp \
    --owner=$user \
    --desc="Bulk provisioned token for $user" \
    --no-qrcode
done

Pre-Provision Token (Future Activation)

# Create token that activates on user's start date
$ ipa otptoken-add --type=totp \
  --owner=newhire \
  --desc="New hire token" \
  --not-before="2024-06-01 09:00:00"

Token with Expiration

# Token expires after 90 days (policy enforcement)
$ ipa otptoken-add --type=totp \
  --owner=grace \
  --desc="90-day rotation token" \
  --not-after="2024-09-30 23:59:59"

Search Disabled Tokens

# Find all disabled tokens for cleanup
$ ipa otptoken-find --disabled=TRUE

Search Tokens by Serial Number

# Find hardware token by serial
$ ipa otptoken-find --serial=5438291

Export Token List for Inventory

# Generate hardware token inventory report
$ ipa otptoken-find --type=hotp --all | grep -E "(Unique ID|Owner|Vendor|Model|Serial)"

Best Practices

Token Provisioning

Self-enrollment preferred: Allow users to self-enroll TOTP tokens via WebUI. This ensures users control their own secret keys and reduces help desk burden.

Multiple tokens: Encourage users to provision backup tokens (e.g., primary on phone, backup on tablet or hardware token). This prevents account lockout when primary device is lost.

Secure delivery: When provisioning tokens for users, deliver QR codes or secrets through secure channels (encrypted email, secure messaging, in-person). Never send via unencrypted email or SMS.

Hardware token tracking: Use vendor, model, and serial fields to maintain accurate hardware token inventory. This aids in asset management and decommissioning.

Descriptive names: Use meaningful descriptions that identify the device or app (e.g., “iPhone 13 Google Authenticator”, “Yubikey backup token”). This helps users and administrators identify tokens.

Security Hardening

Immediate disablement: Disable tokens immediately when users report lost/stolen devices. Don’t wait for investigation—disable first, investigate later.

Regular audits: Periodically review active tokens and remove those for departed users or obsolete devices. Disabled tokens older than 90 days should be deleted.

Time validity windows: Use --not-after for contractor or temporary access to enforce automatic token expiration. Set calendar reminders to provision replacement tokens before expiration.

Strong algorithms: Consider SHA-256 or SHA-512 instead of SHA-1 for new tokens, if authenticator apps support it. SHA-1 is still secure for OTP but SHA-256 provides future-proofing.

No secret retrieval: Never attempt to retrieve or display token secrets after creation. If a secret is lost, create a new token—there’s no recovery mechanism by design.

User Experience

Simple defaults: Use default settings (6 digits, 30 seconds, SHA-1) for maximum compatibility with authenticator apps. Deviating from defaults increases user support burden.

QR code preferred: Always display QR codes for TOTP tokens unless there’s a specific reason not to. Manual entry of Base32 secrets is error-prone.

Clear instructions: Provide users with step-by-step instructions for scanning QR codes and verifying token functionality before they log out.

Backup token workflow: Establish a workflow where users provision a backup token immediately after their primary token. Test both tokens before concluding enrollment.

Graceful degradation: Don’t mandate OTP for all users simultaneously. Gradual rollout by department or role reduces support load.

Operational Practices

Helpdesk delegation: Use --add-managedby to grant helpdesk staff limited token management rights (disable/enable, view metadata) without full admin privileges.

Clock synchronization: Ensure IPA servers have accurate time via NTP. TOTP authentication fails if server clocks drift significantly.

Monitoring: Track OTP authentication failures. Spikes may indicate clock issues, token synchronization problems, or user confusion.

Documentation: Maintain internal documentation showing approved authenticator apps, provisioning procedures, and troubleshooting steps.

Decommissioning: When users leave, disable their tokens immediately (alongside account disablement). Delete tokens after the user account is deleted.

Token Lifecycle Management

Replacement cycles: Consider enforcing token replacement every 1-2 years for hardware tokens (physical wear) or organizational policy compliance.

Proactive renewal: Use --not-after to enforce expiration, but provision replacement tokens 30 days in advance to avoid user disruption.

Migration planning: When replacing tokens (e.g., migrating from hardware to software tokens), allow overlapping validity periods so users aren’t locked out during transition.

Audit trails: Retain logs showing token creation, disablement, and deletion for compliance and security investigations.

Integration Points

OTP Configuration

Global OTP settings are managed via otpconfig commands:

  • Default TOTP interval
  • Default HOTP lookahead window
  • Supported algorithms
  • Token window size

See otpconfig topic for configuration details.

User Authentication

Users must be configured to require OTP authentication:

# Require password + OTP for alice
$ ipa user-mod alice --user-auth-type=otp

# Require password + OTP for all users in a group
$ ipa group-mod secure-users --user-auth-type=otp

Authentication types: password, otp, password,otp (both), password|otp (either).

Kerberos Pre-Authentication

OTP authentication integrates with Kerberos via FAST (Flexible Authentication Secure Tunneling):

  • User initiates kinit
  • KDC requests OTP via FAST channel
  • User provides OTP code
  • KDC validates against token
  • TGT issued on success

Requires FAST armor ticket or anonymous PKINIT.

WebUI Self-Service

Users can manage their own tokens via the FreeIPA WebUI:

  • Navigate to Settings → OTP Tokens
  • Add new tokens (displays QR code)
  • View active tokens
  • Delete own tokens (if self-service enabled)

RADIUS Integration

IPA can act as a RADIUS server for OTP authentication, enabling integration with VPNs, network equipment, and other RADIUS clients.

See radiusproxy topic for RADIUS configuration.

Certmonger

Certmonger can use OTP authentication when requesting certificates on behalf of users.

SSSD

SSSD clients retrieve OTP configuration from IPA and prompt users for OTP codes during authentication. Supports both console and graphical logins.

Migration from Other Systems

When migrating from other OTP systems:

  • Export existing token secrets (if available)
  • Create IPA tokens with --key parameter (imported secrets)
  • Users continue using existing authenticator app configurations
  • Alternative: Provision new IPA tokens and migrate users gradually

Use Cases

1. Mandatory 2FA for Privileged Users

Require all administrators to use OTP authentication for enhanced security.

# Create sysadmin group requiring OTP
ipa group-add sysadmins-2fa --desc="System administrators with mandatory 2FA"

# Require password + OTP for this group
ipa group-mod sysadmins-2fa --user-auth-type=otp

# Add administrators to group
ipa group-add-member sysadmins-2fa --users=alice,bob,charlie

# Provision tokens for each admin
ipa otptoken-add --type=totp --owner=alice \
  --desc="Alice admin token - iPhone FreeOTP"

ipa otptoken-add --type=totp --owner=bob \
  --desc="Bob admin token - Google Authenticator"

ipa otptoken-add --type=totp --owner=charlie \
  --desc="Charlie admin token - Authy"

# Admins must now authenticate with password + OTP code
# Example: kinit alice
# Password + Token:  MyPassword123456  (password + 6-digit code concatenated)

2. User Self-Service Token Enrollment

Enable users to provision their own OTP tokens without administrator intervention.

# As user alice, self-enroll token
kinit alice
# Enter password

# Create personal TOTP token
ipa otptoken-add --type=totp --desc="My personal phone - FreeOTP"

# Output shows QR code:
# Scan with FreeOTP app on phone

# Base32 secret also displayed for manual entry if QR scan unavailable

# Test token works by logging out and back in
kdestroy
kinit alice
# Enter: password123456 (password + current OTP code)

# Verify TGT obtained
klist

3. Provisioning Backup Tokens for Account Recovery

Prevent account lockout by provisioning multiple tokens per user.

# User provisions primary token
ipa otptoken-add --type=totp \
  --desc="Primary - iPhone 14 FreeOTP"

# User provisions backup token on different device
ipa otptoken-add --type=totp \
  --desc="Backup - iPad Google Authenticator"

# Admin provisions emergency hardware token
ipa otptoken-add --type=hotp \
  --owner=alice \
  --desc="Emergency backup - YubiKey in safe" \
  --vendor="Yubico" \
  --model="YubiKey 5" \
  --serial="12345678" \
  --key="JBSWY3DPEHPK3PXP"

# User can authenticate with any token
# If phone lost, use iPad or hardware token
# List all tokens for user
ipa otptoken-find --owner=alice
# Shows: 3 tokens

4. Temporal Tokens for Contractors

Create time-limited tokens that automatically expire after contract period.

# Contractor starts June 1, 2024, contract ends August 31, 2024
ipa otptoken-add --type=totp \
  --owner=contractor-jane \
  --desc="Contract worker token Q2-Q3 2024" \
  --not-before="2024-06-01 00:00:00" \
  --not-after="2024-08-31 23:59:59"

# Token won't work before June 1
# Token automatically stops working after August 31
# No manual cleanup needed

# Set calendar reminder to provision new token if contract extended
# List tokens expiring soon
ipa otptoken-find --all | grep -B5 "Not After: 2024-08"

5. Hardware Token Inventory Management

Track physical hardware tokens with metadata for asset management.

# Provision 50 YubiKeys for distribution
# Record vendor, model, serial for each token

for i in {1..50}; do
  serial=$(printf "YK-%06d" $i)
  ipa otptoken-add --type=hotp \
    --vendor="Yubico" \
    --model="YubiKey 5 NFC" \
    --serial="$serial" \
    --desc="Hardware token batch 2024-Q1" \
    --key="$(cat /tmp/yubikey_secrets/${serial}.key)" \
    --no-qrcode
done

# Generate hardware token inventory report
echo "=== Hardware Token Inventory ===" > token-inventory.txt
ipa otptoken-find --vendor=Yubico --all | \
  grep -E "(Unique ID|Owner|Serial|Model|Disabled)" >> token-inventory.txt

# Find unassigned hardware tokens
ipa otptoken-find --vendor=Yubico | grep -A1 "Owner: $^"
# Returns tokens without owners - available for distribution

6. Helpdesk Token Management Delegation

Grant helpdesk staff limited token management without full admin rights.

# Create helpdesk group
ipa group-add helpdesk --desc="IT Help Desk staff"
ipa group-add-member helpdesk --users=helpdesk1,helpdesk2,helpdesk3

# User alice reports lost phone
# Helpdesk identifies alice's token
ipa otptoken-find --owner=alice

# Admin grants helpdesk management rights to alice's token
ipa otptoken-add-managedby a1b2c3d4-uuid-here --users=helpdesk1

# Helpdesk can now disable token without admin privileges
# As helpdesk1:
kinit helpdesk1
ipa otptoken-mod a1b2c3d4-uuid-here --disabled=TRUE

# Helpdesk provisions new token for alice
ipa otptoken-add --type=totp --owner=alice \
  --desc="Replacement token after phone loss"

# Admin can remove helpdesk management after issue resolved
ipa otptoken-remove-managedby a1b2c3d4-uuid-here --users=helpdesk1

7. Migrating Users from RADIUS to IPA OTP

Import existing token secrets when migrating from legacy OTP system.

# Export token secrets from old RADIUS server
# Format: username,token_secret_base32

# For each user, import token with existing secret
while IFS=, read -r username secret; do
  ipa otptoken-add --type=totp \
    --owner="$username" \
    --desc="Migrated from RADIUS server" \
    --key="$secret"
done < token_export.csv

# Users continue using existing authenticator app configurations
# No need to re-scan QR codes or reconfigure apps
# Transparent migration from user perspective

# Verify migration successful
ipa otptoken-find --all | grep "Migrated from RADIUS"

8. Gradual OTP Rollout by Department

Phase OTP deployment department by department to manage support load.

# Phase 1: IT department (week 1)
ipa group-mod IT-staff --user-auth-type=otp
# Provision tokens for IT staff
# IT validates process before broader rollout

# Phase 2: Finance department (week 2)
ipa group-mod finance-staff --user-auth-type=otp
# Provision tokens for finance staff

# Phase 3: Engineering (week 3)
ipa group-mod engineering-staff --user-auth-type=otp

# Phase 4: All remaining users (week 4)
ipa group-mod all-employees --user-auth-type=otp

# Monitor OTP authentication failures during each phase
# Adjust rollout pace based on support tickets generated

9. Auditing Token Usage and Cleanup

Identify and remove orphaned, disabled, or expired tokens.

# Find tokens for deleted users (orphaned tokens)
for token in $(ipa otptoken-find --pkey-only | grep "Unique ID:" | awk '{print $3}'); do
  owner=$(ipa otptoken-show "$token" | grep "Owner:" | awk '{print $2}')
  ipa user-show "$owner" &>/dev/null || echo "Orphaned token: $token (owner: $owner)"
done

# Find disabled tokens older than 90 days
ipa otptoken-find --disabled=TRUE --all | \
  grep -B10 "Modified on:" | \
  # Manual review for deletion

# Delete tokens for departed users
ipa otptoken-find --owner=departed-user
ipa otptoken-del token-uuid-here

# Find tokens expiring in next 30 days
# (requires parsing --not-after field)
ipa otptoken-find --all | grep -B10 "Not After: 2024-09"

10. Testing TOTP Clock Synchronization

Verify TOTP tokens properly handle clock skew between client and server.

# Create test token
ipa otptoken-add --type=totp \
  --owner=testuser \
  --desc="Clock sync test token"

# Record current server time
date

# Note OTP code from authenticator app
# Authenticate immediately
kinit testuser
# Enter: password + OTP code

# Check if offset was learned
ipa otptoken-show <token-uuid> | grep Offset
# Should show: Offset: +X seconds (where X is clock skew)

# Simulate clock drift by manually setting offset
ipa otptoken-mod <token-uuid> --offset=30

# Test authentication with 30-second offset
# Should still work if within tolerance window (±60 seconds default)

# Reset offset to auto-learn
ipa otptoken-mod <token-uuid> --offset=0

Additional Security Considerations

1. Token Secret Exposure During Provisioning

QR codes and Base32 secrets displayed during provisioning are the keys to the kingdom.

  • QR code visible on screen can be photographed by cameras or shoulder surfers
  • Base32 secret in terminal scrollback or logs exposes token completely
  • Provision tokens in private setting; clear terminal after QR display
  • Use --no-qrcode for automated provisioning; deliver QR through secure channel
  • Never log or screenshot QR codes; secrets are not retrievable after creation

2. Shared Device Token Risks

Tokens provisioned on shared devices enable unauthorized access.

  • Authenticator app on shared tablet allows anyone to generate codes
  • Lost/stolen device with token grants attacker the “something you have” factor
  • Only password compromise needed for full account access
  • Users should never provision tokens on shared devices
  • Mobile device management (MDM) policies should enforce device locks

3. Authentication Type Downgrade Attacks

User authentication types can be modified; attackers may disable OTP requirement.

  • User with --user-auth-type=otp can be modified to password if RBAC misconfigured
  • Compromised admin account could disable OTP for targets
  • Monitor authentication type changes with IPA audit logging
  • Restrict permission “System: Modify User” to minimal administrators
  • Group-level auth type enforcement more resilient than per-user

4. Token Synchronization Window Exploitation

HOTP lookahead window allows future codes; enables limited replay attacks.

  • Default 10-code lookahead means next 10 codes all valid
  • User generates 10 codes without using them; counter drifts
  • Attacker with old code can authenticate if within lookahead window
  • Reduce lookahead window if HOTP required; use TOTP when possible
  • TOTP time window is fixed (±60 seconds default) and less exploitable

5. Multiple Active Tokens Per User

Multiple tokens provide resilience but multiply attack surface.

  • Each additional token is another secret to protect
  • Compromise of any user token grants access to account
  • 5 tokens means 5x attack surface compared to single token
  • Balance resilience (backup tokens) against security (fewer secrets)
  • Maximum 2-3 tokens per user recommended: primary, backup, emergency

6. Disabled Token Retention

Disabled tokens remain in directory and retain secrets; could be re-enabled.

  • Disabled token not deleted; could be re-enabled by attacker with access
  • Token metadata visible even when disabled; leaks device information
  • Delete tokens promptly rather than indefinite disablement
  • Exception: temporarily lost devices where recovery expected within days
  • Audit disabled tokens older than 30 days for deletion

7. OTP Brute Force Attacks

Six-digit OTP codes provide only 1,000,000 combinations; theoretically brute-forceable.

  • 6-digit TOTP has 1 million possibilities; 8-digit has 100 million
  • 30-second window means attacker has brief time to test codes
  • IPA rate limiting protects against online brute force
  • Offline attacks not possible (server-side verification required)
  • 8-digit codes recommended for highest-security accounts

8. Time-Based Attacks Against TOTP

TOTP security depends on accurate time synchronization; time manipulation bypasses.

  • Attacker controlling NTP could manipulate server time to accept old codes
  • Compromised NTP server could enable replay attacks
  • Use authenticated NTP (NTS) or multiple independent time sources
  • Monitor server time drift; alert on significant changes
  • Physical server access could enable time manipulation

9. Token Export and Backup Risks

Backing up authenticator app data exports token secrets to backup storage.

  • Phone backup (iCloud, Google Backup) may include authenticator app data
  • Backup compromise exposes all token secrets
  • Encrypted backups protect secrets but key management critical
  • Users should understand backup implications of authenticator apps
  • Organizational policy may prohibit authenticator app cloud backups

10. Helpdesk Social Engineering

Helpdesk token management privileges enable social engineering attacks.

  • Attacker impersonates user calling helpdesk for token reset
  • Helpdesk provisions new token; attacker receives QR code
  • Weak identity verification process allows attacker access
  • Require strong identity verification before token provisioning
  • Out-of-band confirmation: email/SMS to registered contact before token reset

Troubleshooting

1. TOTP Code Always Invalid - Clock Skew

Symptom: User’s TOTP codes always rejected; “Invalid credentials” error.

Diagnosis:

# Check server time
date

# Ask user to check phone time
# Often user's phone clock is wrong

# Check token offset
ipa otptoken-show <token-uuid> | grep Offset

# Verify token type
ipa otptoken-show <token-uuid> | grep Type

Resolution:

  • Correct device time on user’s phone/tablet
  • If phone time correct, check IPA server time synchronization
  • Force time sync on IPA server: sudo ntpdate -u pool.ntp.org
  • Configure chrony/NTP for continuous time sync
  • After time correction, user’s next authentication should succeed and learn offset
  • Manual offset: ipa otptoken-mod <uuid> --offset=30 (if 30 seconds skew)

2. User Locked Out - Lost All Tokens

Symptom: User lost phone with primary token; backup token not provisioned.

Diagnosis:

# Verify user requires OTP
ipa user-show username | grep "User authentication"

# Check if any active tokens remain
ipa otptoken-find --owner=username

# All tokens lost or disabled

Resolution:

  • Admin temporarily changes user auth type to password-only:
  ipa user-mod username --user-auth-type=password
  • User can now authenticate with password alone
  • Provision new OTP token:
  ipa otptoken-add --type=totp --owner=username --desc="Replacement token"
  • Deliver QR code to user through secure channel
  • After user configures new token, restore OTP requirement:
  ipa user-mod username --user-auth-type=otp
  • Delete old lost token(s)

3. HOTP Token Synchronized Counter Drift

Symptom: HOTP hardware token codes rejected; was working previously.

Diagnosis:

# Show token to see current counter
ipa otptoken-show <token-uuid> --all | grep "Counter"

# User may have pressed button multiple times without authenticating
# Counter on token advanced beyond server's lookahead window (10 codes)

Resolution:

  • Ask user to generate one code from hardware token
  • Record the code number (user counts how many times they’ve pressed button)
  • Manually advance server counter to approximately match:
  ipa otptoken-mod <token-uuid> --counter=150
  • User attempts authentication
  • If still failing, increment counter further and retry
  • Once successful, counter automatically synchronizes
  • Prevention: Educate users not to “test” HOTP tokens unnecessarily

4. Cannot Create Token - Owner Not Found

Symptom: otptoken-add --owner=username fails with “user not found” error.

Diagnosis:

# Verify user exists
ipa user-show username

# Check exact username spelling
ipa user-find username

Resolution:

  • Use correct username (uid) as shown in ipa user-show
  • Create user first if doesn’t exist: ipa user-add username
  • For self-enrollment (no --owner specified), user must be authenticated:
  kinit username
  ipa otptoken-add --type=totp

5. QR Code Not Displaying in Terminal

Symptom: otptoken-add completes but no QR code shown.

Diagnosis:

# Check terminal type
echo $TERM

# Try again with explicit QR generation
ipa otptoken-add --type=totp --owner=testuser

# If over SSH, check SSH client settings

Resolution:

  • Some terminals (PuTTY, minimal SSH) don’t support UTF-8 QR code display
  • Use modern terminal: iTerm2 (Mac), Windows Terminal, GNOME Terminal
  • Alternative: Use WebUI for token provisioning (QR always displays in browser)
  • Or use --no-qrcode and extract Base32 secret manually:
  # Base32 secret displayed in output; user manually enters in authenticator app
  • For remote provisioning, use WebUI or securely transmit QR image

6. User Enters Password and OTP Separately - Authentication Fails

Symptom: User prompted for password, then separately for OTP; authentication fails.

Diagnosis:

# User may be using `kinit` without FAST support
# Or SSSD not configured for OTP properly

# Check if FAST armor available
klist

Resolution:

  • For CLI kinit, user must concatenate password and OTP:
  kinit username
  # Prompt: Password for username@REALM:
  # Enter: MyPassword123456 (password + OTP code, no space)
  • For SSSD graphical login, OTP should be prompted separately (expected behavior)
  • For command-line SSSD, may need FAST armor:
  # Obtain anonymous PKINIT ticket for FAST armor
  kinit -n
  # Then authenticate
  kinit username
  • Ensure /etc/krb5.conf has FAST configuration

7. Token Shows Disabled But Admin Didn’t Disable It

Symptom: Token unexpectedly disabled; user cannot authenticate.

Diagnosis:

# Show token status
ipa otptoken-show <token-uuid> | grep Disabled
# Shows: Disabled: TRUE

# Check token modification history
ipa otptoken-show <token-uuid> --all | grep "Modified"

# Review IPA audit logs
journalctl -u ipa -n 1000 | grep otptoken

Resolution:

  • Check if user or managed-by user disabled token
  • Verify no automated process disabling tokens
  • Re-enable token:
  ipa otptoken-mod <token-uuid> --disabled=FALSE
  • Investigate who/what disabled token from audit logs
  • Review otptoken-add-managedby memberships; revoke if suspicious

8. Cannot Delete Token - Permission Denied

Symptom: otptoken-del fails with permission error.

Diagnosis:

# Check who owns the token
ipa otptoken-show <token-uuid> | grep Owner

# Check if self-service token deletion allowed
ipa config-show | grep "Self-service"

# Verify current user permissions
ipa user-show --all | grep role

Resolution:

  • Only token owner (if self-service enabled) or admins can delete tokens
  • User trying to delete another user’s token: requires admin privileges
  • Request admin to delete token:
  # As admin:
  ipa otptoken-del <token-uuid>
  • Or grant user admin privileges temporarily

9. Authenticator App Shows Wrong Account Name

Symptom: User scanned QR code but app displays wrong username or realm.

Diagnosis:

# QR code contains otpauth:// URI with username and issuer
# Check token owner
ipa otptoken-show <token-uuid>

# URI format: otpauth://totp/USER@REALM?...&issuer=REALM

Resolution:

  • Account name in authenticator app is informational only; doesn’t affect functionality
  • App displays: REALM: USER@REALM or similar
  • User can rename entry in authenticator app for clarity
  • OTP codes will work regardless of displayed name
  • If wrong user, delete token and recreate for correct user

10. Token Works from WebUI But Not CLI

Symptom: User can authenticate to WebUI with OTP but kinit fails.

Diagnosis:

# WebUI and CLI use different authentication methods
# kinit requires FAST for OTP

# Check if FAST configured
grep -i fast /etc/krb5.conf

# Verify armor ticket
klist

Resolution:

  • WebUI uses HTTPS; OTP sent via HTTPS POST
  • CLI kinit requires FAST (Flexible Authentication Secure Tunneling)
  • Configure FAST in /etc/krb5.conf:
  [libdefaults]
    default_realm = EXAMPLE.COM
    fast_armor = true
  • Obtain FAST armor ticket:
  kinit -n  # Anonymous PKINIT
  • Then authenticate with OTP:
  kinit username
  # Enter: password123456

11. Multiple Tokens - Don’t Know Which Code to Use

Symptom: User has 3 tokens; unclear which generates correct code.

Diagnosis:

# List all user's tokens
ipa otptoken-find --owner=username

# Shows: 3 tokens with different descriptions

Resolution:

  • All active tokens valid; any code works
  • User can try codes from all tokens; first valid code succeeds
  • Encourage descriptive token names to identify devices:
    • “iPhone 13 - FreeOTP”
    • “iPad - Google Authenticator”
    • “YubiKey backup”
  • User should use primary token normally; backups for emergencies only
  • If confusion persists, disable/delete unused tokens:
  ipa otptoken-mod <old-token-uuid> --disabled=TRUE
  ipa otptoken-del <old-token-uuid>

12. Token Secret Accidentally Displayed in Logs

Symptom: Token Base32 secret appears in command history or system logs.

Diagnosis:

# Check shell history
history | grep otptoken-add

# Check system logs
journalctl -u ipa | grep otptoken

# Token secret visible if captured during creation

Resolution:

  • Token secret cannot be hidden during creation (by design)
  • Immediately delete compromised token:
  ipa otptoken-del <compromised-token-uuid>
  • Provision new token for user:
  ipa otptoken-add --type=totp --owner=username --desc="Replacement after secret exposure"
  • Clear shell history:
  history -c
  • Educate users/admins: Clear terminal after QR display
  • For automated provisioning, use --no-qrcode and secure secret delivery

13. Cannot Import Hardware Token Secret - Invalid Key Format

Symptom: otptoken-add --key=... fails with “invalid key” error.

Diagnosis:

# Check key format - must be Base32
echo "JBSWY3DPEHPK3PXP" | base32 -d | hexdump -C

# Verify no special characters or whitespace
echo -n "$SECRET" | wc -c

Resolution:

  • Key must be Base32 encoded (A-Z, 2-7, no padding or lowercase)
  • Remove whitespace and newlines:
  SECRET=$(echo "$SECRET" | tr -d ' \n')
  ipa otptoken-add --type=hotp --key="$SECRET"
  • If vendor provides hex secret, convert to Base32:
  # Example conversion (requires base32 utility)
  echo "48656c6c6f" | xxd -r -p | base32
  • Verify token secret length appropriate (typically 20-40 characters)

14. Token Works Initially Then Stops Working Days Later

Symptom: Token authenticated successfully for days; suddenly all codes rejected.

Diagnosis:

# Check if token has expiration date
ipa otptoken-show <token-uuid> --all | grep "Not After"

# Check if token disabled
ipa otptoken-show <token-uuid> | grep Disabled

# Verify user authentication type unchanged
ipa user-show username | grep "User authentication"

Resolution:

  • Token may have passed --not-after expiration date:
    • Provision new token if expiration intentional
    • Extend expiration: ipa otptoken-mod <uuid> --not-after="2025-12-31 23:59:59"
  • Token may have been disabled:
    • Re-enable: ipa otptoken-mod <uuid> --disabled=FALSE
  • User authentication type may have changed:
    • Restore OTP requirement: ipa user-mod username --user-auth-type=otp
  • Check server time synchronization (TOTP specific)

15. Want to Retrieve Token Secret After Creation - Not Possible

Symptom: User lost phone; wants admin to retrieve token secret to restore in new app.

Diagnosis:

# Attempt to show token secret
ipa otptoken-show <token-uuid> --all | grep -i secret

# Secret field not present or shows empty
# By design, secrets never retrievable after creation

Resolution:

  • Token secrets cannot be retrieved after creation (security feature)
  • Lost token secret means token must be replaced:
  # Delete old token
  ipa otptoken-del <old-token-uuid>

  # Create new token
  ipa otptoken-add --type=totp --owner=username \
    --desc="Replacement token after device loss"
  • User must configure new authenticator app with new secret
  • Prevention: Provision backup tokens on separate devices
  • Some authenticator apps support encrypted cloud backup (e.g., Authy)
  • Organizational policy may prohibit authenticator app backups

Commands

otptoken-add

Usage: ipa [global-options] otptoken-add [ID] [options]

Add a new OTP token.

Arguments

Argument Required Description


ID no Unique ID

Options

OptionDescription
--type TYPEType of the token
--desc DESCToken description (informational only)
--owner OWNERAssigned user of the token (default: self)
--disabled DISABLEDMark the token as disabled (default: false)
--not-before NOT-BEFOREFirst date/time the token can be used
--not-after NOT-AFTERLast date/time the token can be used
--vendor VENDORToken vendor name (informational only)
--model MODELToken model (informational only)
--serial SERIALToken serial (informational only)
--key KEYToken secret (Base32; default: random)
--algo ALGOToken hash algorithm
--digits DIGITSNumber of digits each token code will have
--offset OFFSETTOTP token / IPA server time difference
--interval INTERVALLength of TOTP token code validity
--counter COUNTERInitial counter for the HOTP token
--setattr SETATTRSet an attribute to a name/value pair. Format is attr=value.
--addattr ADDATTRAdd an attribute/value pair. Format is attr=value. The attribute
--no-qrcodeDo not display QR code
--allRetrieve and print all attributes from the server. Affects command output.
--rawPrint entries as stored on the server. Only affects output format.
--no-membersSuppress processing of membership attributes.

otptoken-add-managedby

Usage: ipa [global-options] otptoken-add-managedby ID [options]

Add users that can manage this token.

Arguments

ArgumentRequiredDescription
IDyesUnique ID

Options

OptionDescription
--allRetrieve and print all attributes from the server. Affects command output.
--rawPrint entries as stored on the server. Only affects output format.
--no-membersSuppress processing of membership attributes.
--users USERSusers to add

otptoken-del

Usage: ipa [global-options] otptoken-del ID [options]

Delete an OTP token.

Arguments

ArgumentRequiredDescription
IDyesUnique ID

Options

OptionDescription
--continueContinuous mode: Don’t stop on errors.

otptoken-find

Usage: ipa [global-options] otptoken-find [CRITERIA] [options]

Search for OTP token.

Arguments

Argument Required Description


CRITERIA no A string searched in all relevant object attributes

Options

OptionDescription
--id IDUnique ID
--type TYPEType of the token
--desc DESCToken description (informational only)
--owner OWNERAssigned user of the token (default: self)
--disabled DISABLEDMark the token as disabled (default: false)
--not-before NOT-BEFOREFirst date/time the token can be used
--not-after NOT-AFTERLast date/time the token can be used
--vendor VENDORToken vendor name (informational only)
--model MODELToken model (informational only)
--serial SERIALToken serial (informational only)
--algo ALGOToken hash algorithm
--digits DIGITSNumber of digits each token code will have
--offset OFFSETTOTP token / IPA server time difference
--interval INTERVALLength of TOTP token code validity
--counter COUNTERInitial counter for the HOTP token
--timelimit TIMELIMITTime limit of search in seconds (0 is unlimited)
--sizelimit SIZELIMITMaximum number of entries returned (0 is unlimited)
--allRetrieve and print all attributes from the server. Affects command output.
--rawPrint entries as stored on the server. Only affects output format.
--pkey-onlyResults should contain primary key attribute only (“id”)

otptoken-mod

Usage: ipa [global-options] otptoken-mod ID [options]

Modify a OTP token.

Arguments

ArgumentRequiredDescription
IDyesUnique ID

Options

OptionDescription
--desc DESCToken description (informational only)
--owner OWNERAssigned user of the token (default: self)
--disabled DISABLEDMark the token as disabled (default: false)
--not-before NOT-BEFOREFirst date/time the token can be used
--not-after NOT-AFTERLast date/time the token can be used
--vendor VENDORToken vendor name (informational only)
--model MODELToken model (informational only)
--serial SERIALToken serial (informational only)
--setattr SETATTRSet an attribute to a name/value pair. Format is attr=value.
--addattr ADDATTRAdd an attribute/value pair. Format is attr=value. The attribute
--delattr DELATTRDelete an attribute/value pair. The option will be evaluated
--rightsDisplay the access rights of this entry (requires —all). See ipa man page for details.
--allRetrieve and print all attributes from the server. Affects command output.
--rawPrint entries as stored on the server. Only affects output format.
--no-membersSuppress processing of membership attributes.
--rename RENAMERename the OTP token object

otptoken-remove-managedby

Usage: ipa [global-options] otptoken-remove-managedby ID [options]

Remove users that can manage this token.

Arguments

ArgumentRequiredDescription
IDyesUnique ID

Options

OptionDescription
--allRetrieve and print all attributes from the server. Affects command output.
--rawPrint entries as stored on the server. Only affects output format.
--no-membersSuppress processing of membership attributes.
--users USERSusers to remove

otptoken-show

Usage: ipa [global-options] otptoken-show ID [options]

Display information about an OTP token.

Arguments

ArgumentRequiredDescription
IDyesUnique ID

Options

OptionDescription
--rightsDisplay the access rights of this entry (requires —all). See ipa man page for details.
--allRetrieve and print all attributes from the server. Affects command output.
--rawPrint entries as stored on the server. Only affects output format.
--no-membersSuppress processing of membership attributes.

Related Topics