Mercurial > prosody-modules
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 |