comparison mod_auth_token/token_auth_utils.lib.lua @ 3693:0fb12a4b6106

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.
author JC Brand <jc@opkode.com>
date Thu, 03 Oct 2019 12:13:44 +0200
parents 6b3181fe5617
children
comparison
equal deleted inserted replaced
3692:96c6d9b0969f 3693:0fb12a4b6106
1 local base64 = require "util.encodings".base64; 1 local base64 = require "util.encodings".base64;
2 local digest = require "openssl.digest";
3 local hmac = require "openssl.hmac"; 2 local hmac = require "openssl.hmac";
4 local luatz = require "luatz"; 3 local luatz = require "luatz";
5 local otp = require "otp"; 4 local otp = require "otp";
6 5
7 local DIGEST_TYPE = "SHA256"; 6 local DIGEST_TYPE = "SHA256";
9 local OTP_DIGITS = 8; 8 local OTP_DIGITS = 8;
10 local OTP_INTERVAL = 30; 9 local OTP_INTERVAL = 30;
11 10
12 local nonce_cache = {}; 11 local nonce_cache = {};
13 12
14 function check_nonce(jid, otp, nonce) 13 local function check_nonce(jid, otp_value, nonce)
15 -- We cache all nonces used per OTP, to ensure that a token cannot be used 14 -- We cache all nonces used per OTP, to ensure that a token cannot be used
16 -- more than once. 15 -- more than once.
17 -- 16 --
18 -- We assume that the OTP is valid in the current time window. This is the 17 -- We assume that the OTP is valid in the current time window. This is the
19 -- case because we only call check_nonce *after* the OTP has been verified. 18 -- case because we only call check_nonce *after* the OTP has been verified.
20 -- 19 --
21 -- We only store one OTP per JID, so if a new OTP comes in, we wipe the 20 -- We only store one OTP per JID, so if a new OTP comes in, we wipe the
22 -- previous OTP and its cached nonces. 21 -- previous OTP and its cached nonces.
23 if nonce_cache[jid] == nil or nonce_cache[jid][otp] == nil then 22 if nonce_cache[jid] == nil or nonce_cache[jid][otp_value] == nil then
24 nonce_cache[jid] = {} 23 nonce_cache[jid] = {}
25 nonce_cache[jid][otp] = {} 24 nonce_cache[jid][otp_value] = {}
26 nonce_cache[jid][otp][nonce] = true 25 nonce_cache[jid][otp_value][nonce] = true
27 return true; 26 return true;
28 end 27 end
29 if nonce_cache[jid][otp][nonce] == true then 28 if nonce_cache[jid][otp_value][nonce] == true then
30 return false; 29 return false;
31 else 30 else
32 nonce_cache[jid][otp][nonce] = true; 31 nonce_cache[jid][otp_value][nonce] = true;
33 return true; 32 return true;
34 end 33 end
35 end 34 end
36 35
37 36
38 function verify_token(username, password, realm, otp_seed, token_secret, log) 37 local function verify_token(username, password, otp_seed, token_secret, log)
39 if (realm ~= module.host) then
40 log("debug", "Verification failed: realm ~= module.host");
41 return false;
42 end
43
44 local totp = otp.new_totp_from_key(otp_seed, OTP_DIGITS, OTP_INTERVAL) 38 local totp = otp.new_totp_from_key(otp_seed, OTP_DIGITS, OTP_INTERVAL)
45 local token = string.match(password, "(%d+) ") 39 local token = string.match(password, "(%d+) ")
46 local otp = token:sub(1,8) 40 local otp_value = token:sub(1,8)
47 local nonce = token:sub(9) 41 local nonce = token:sub(9)
48 local signature = base64.decode(string.match(password, " (.+)")) 42 local signature = base64.decode(string.match(password, " (.+)"))
49 local jid = username.."@"..realm 43 local jid = username.."@"..module.host
50 44
51 if totp:verify(otp, OTP_DEVIATION, luatz.time()) then 45 if totp:verify(otp_value, OTP_DEVIATION, luatz.time()) then
52 log("debug", "The TOTP was verified"); 46 log("debug", "The TOTP was verified");
53 local hmac_ctx = hmac.new(token_secret, DIGEST_TYPE) 47 local hmac_ctx = hmac.new(token_secret, DIGEST_TYPE)
54 if signature == hmac_ctx:final(otp..nonce..jid) then 48 if signature == hmac_ctx:final(otp_value..nonce..jid) then
55 log("debug", "The key was verified"); 49 log("debug", "The key was verified");
56 if check_nonce(jid, otp, nonce) then 50 if check_nonce(jid, otp_value, nonce) then
57 log("debug", "The nonce was verified"); 51 log("debug", "The nonce was verified");
58 return true; 52 return true;
59 end 53 end
60 end 54 end
61 end 55 end