NaviServer Built-in Commands – 5.0.1
ns_totp - Returns a decimal-coded time-based one-time password (TOTP)
The function returns a time-based one time password (TOTP) as described in RFC-6238. The function uses the HOTP function of RFC-4226 but adds the possibility to restrict the validity of the password to a time window.
RFC-6238 defines TOTP as:
TOTP = HOTP(K, T), where T is an integer K: key T: time slice (moving factor for one time passwd)
The implemented function ns_totp is a generalization by allowing to specify the message digest algorithm, the number of characters of the returned truncated value, a used_id and a time.
The listed command is available in installations when NaviServer is compiled with OpenSSL support and where the nsf package is installed.
Minimal example:
% ns_totp -key "tweedie123" 33888450
A common application for TOTP is integration with authenticator apps such as Google Authenticator, which expect a specially formatted URL:
otpauth://TYPE/LABEL?PARAMETERS
where TYPE is either hotp or totp. This URL is typically encoded in a QR code. Most authenticator apps can scan such codes directly, or provide means to enter the parameters manually.
The URL encodes several parameters relevant for TOTP generation:
secret: the Base32-encoded shared secret (mandatory)
period: validity interval in seconds, default 30
digits: number of digits in the OTP, default 6
algorithm: hash algorithm, default SHA1
Among these, the only mandatory parameter is the secret. When using ns_totp, it is usually necessary to extract at least secret and digits from the URL, and to provide -digest explicitly, since the defaults of ns_totp (sha256 and 8 digits) differ from those used by many authenticator apps.
# Decoded authenticator URL % set url otpauth://totp/IDENT?secret=XSECRETSECRETSECRETSECRETSECRETX&period=30&digits=6&issuer=WU%20Wien # Extract parameters from URL % set p [ns_set array [ns_parsequery [dict get [ns_parseurl $url] query]]] secret XSECRETSECRETSECRETSECRETSECRETX period 30 digits 6 issuer {WU Wien} # Generate TOTP % package require base32 % ns_totp -digest sha1 -digits [dict get $p digits] -key [base32::decode [dict get $p secret]] 259664
ns_section "ns/server/server1" { # ... ns_param serversecret "swordfish" # ... }