# HG changeset patch # User JC Brand # Date 1570097624 -7200 # Node ID 0fb12a4b6106439edbdf1e4bc143082797973e1a # Parent 96c6d9b0969f33b21ff406db6577e957288cc5d6 auth_token: Various updates, see below. * Defer to usermanager when testing the password * Because of this, don't assume the realm is available when verifying the token * Fix linting errors By using the `usermanager`, other modules can now ask the user manager to verify token credentials. diff -r 96c6d9b0969f -r 0fb12a4b6106 mod_auth_token/mod_auth_token.lua --- a/mod_auth_token/mod_auth_token.lua Mon Sep 30 00:51:05 2019 +0200 +++ b/mod_auth_token/mod_auth_token.lua Thu Oct 03 12:13:44 2019 +0200 @@ -6,17 +6,17 @@ local host = module.host; local log = module._log; local new_sasl = require "util.sasl".new; +local usermanager = require "core.usermanager"; local verify_token = module:require "token_auth_utils".verify_token; local provider = {}; -function provider.test_password(username, password, realm) +function provider.test_password(username, password) log("debug", "Testing signed OTP for user %s at host %s", username, host); return verify_token( username, password, - realm, module:get_option_string("otp_seed"), module:get_option_string("token_secret"), log @@ -50,7 +50,7 @@ supported_mechanisms["X-TOKEN"] = true; return new_sasl(host, { token = function(sasl, username, password, realm) - return provider.test_password(username, password, realm), true; + return usermanager.test_password(username, realm, password), true; end, mechanisms = supported_mechanisms }); diff -r 96c6d9b0969f -r 0fb12a4b6106 mod_auth_token/token_auth_utils.lib.lua --- a/mod_auth_token/token_auth_utils.lib.lua Mon Sep 30 00:51:05 2019 +0200 +++ b/mod_auth_token/token_auth_utils.lib.lua Thu Oct 03 12:13:44 2019 +0200 @@ -1,5 +1,4 @@ local base64 = require "util.encodings".base64; -local digest = require "openssl.digest"; local hmac = require "openssl.hmac"; local luatz = require "luatz"; local otp = require "otp"; @@ -11,7 +10,7 @@ local nonce_cache = {}; -function check_nonce(jid, otp, nonce) +local function check_nonce(jid, otp_value, nonce) -- We cache all nonces used per OTP, to ensure that a token cannot be used -- more than once. -- @@ -20,40 +19,35 @@ -- -- We only store one OTP per JID, so if a new OTP comes in, we wipe the -- previous OTP and its cached nonces. - if nonce_cache[jid] == nil or nonce_cache[jid][otp] == nil then + if nonce_cache[jid] == nil or nonce_cache[jid][otp_value] == nil then nonce_cache[jid] = {} - nonce_cache[jid][otp] = {} - nonce_cache[jid][otp][nonce] = true + nonce_cache[jid][otp_value] = {} + nonce_cache[jid][otp_value][nonce] = true return true; end - if nonce_cache[jid][otp][nonce] == true then + if nonce_cache[jid][otp_value][nonce] == true then return false; else - nonce_cache[jid][otp][nonce] = true; + nonce_cache[jid][otp_value][nonce] = true; return true; end end -function verify_token(username, password, realm, otp_seed, token_secret, log) - if (realm ~= module.host) then - log("debug", "Verification failed: realm ~= module.host"); - return false; - end - +local function verify_token(username, password, otp_seed, token_secret, log) local totp = otp.new_totp_from_key(otp_seed, OTP_DIGITS, OTP_INTERVAL) local token = string.match(password, "(%d+) ") - local otp = token:sub(1,8) + local otp_value = token:sub(1,8) local nonce = token:sub(9) local signature = base64.decode(string.match(password, " (.+)")) - local jid = username.."@"..realm + local jid = username.."@"..module.host - if totp:verify(otp, OTP_DEVIATION, luatz.time()) then + if totp:verify(otp_value, OTP_DEVIATION, luatz.time()) then log("debug", "The TOTP was verified"); local hmac_ctx = hmac.new(token_secret, DIGEST_TYPE) - if signature == hmac_ctx:final(otp..nonce..jid) then + if signature == hmac_ctx:final(otp_value..nonce..jid) then log("debug", "The key was verified"); - if check_nonce(jid, otp, nonce) then + if check_nonce(jid, otp_value, nonce) then log("debug", "The nonce was verified"); return true; end