author | Kim Alvefur <zash@zash.se> |
Wed, 03 Mar 2021 11:43:38 +0100 | |
changeset 4494 | cf2bdb2aaa57 |
parent 3697 | 0fb12a4b6106 |
permissions | -rw-r--r-- |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
1 |
local base64 = require "util.encodings".base64; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
2 |
local hmac = require "openssl.hmac"; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
3 |
local luatz = require "luatz"; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
4 |
local otp = require "otp"; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
5 |
|
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
6 |
local DIGEST_TYPE = "SHA256"; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
7 |
local OTP_DEVIATION = 1; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
8 |
local OTP_DIGITS = 8; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
9 |
local OTP_INTERVAL = 30; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
10 |
|
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
11 |
local nonce_cache = {}; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
12 |
|
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
13 |
local function check_nonce(jid, otp_value, nonce) |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
14 |
-- We cache all nonces used per OTP, to ensure that a token cannot be used |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
15 |
-- more than once. |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
16 |
-- |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
17 |
-- We assume that the OTP is valid in the current time window. This is the |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
18 |
-- case because we only call check_nonce *after* the OTP has been verified. |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
19 |
-- |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
20 |
-- We only store one OTP per JID, so if a new OTP comes in, we wipe the |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
21 |
-- previous OTP and its cached nonces. |
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
22 |
if nonce_cache[jid] == nil or nonce_cache[jid][otp_value] == nil then |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
23 |
nonce_cache[jid] = {} |
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
24 |
nonce_cache[jid][otp_value] = {} |
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
25 |
nonce_cache[jid][otp_value][nonce] = true |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
26 |
return true; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
27 |
end |
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
28 |
if nonce_cache[jid][otp_value][nonce] == true then |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
29 |
return false; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
30 |
else |
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
31 |
nonce_cache[jid][otp_value][nonce] = true; |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
32 |
return true; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
33 |
end |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
34 |
end |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
35 |
|
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
36 |
|
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
37 |
local function verify_token(username, password, otp_seed, token_secret, log) |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
38 |
local totp = otp.new_totp_from_key(otp_seed, OTP_DIGITS, OTP_INTERVAL) |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
39 |
local token = string.match(password, "(%d+) ") |
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
40 |
local otp_value = token:sub(1,8) |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
41 |
local nonce = token:sub(9) |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
42 |
local signature = base64.decode(string.match(password, " (.+)")) |
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
43 |
local jid = username.."@"..module.host |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
44 |
|
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
45 |
if totp:verify(otp_value, OTP_DEVIATION, luatz.time()) then |
3476
ac1f63cdb6d6
mod_auth_token: Check realm against module.host
JC Brand <jc@opkode.com>
parents:
2960
diff
changeset
|
46 |
log("debug", "The TOTP was verified"); |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
47 |
local hmac_ctx = hmac.new(token_secret, DIGEST_TYPE) |
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
48 |
if signature == hmac_ctx:final(otp_value..nonce..jid) then |
3476
ac1f63cdb6d6
mod_auth_token: Check realm against module.host
JC Brand <jc@opkode.com>
parents:
2960
diff
changeset
|
49 |
log("debug", "The key was verified"); |
3697
0fb12a4b6106
auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents:
3572
diff
changeset
|
50 |
if check_nonce(jid, otp_value, nonce) then |
3476
ac1f63cdb6d6
mod_auth_token: Check realm against module.host
JC Brand <jc@opkode.com>
parents:
2960
diff
changeset
|
51 |
log("debug", "The nonce was verified"); |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
52 |
return true; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
53 |
end |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
54 |
end |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
55 |
end |
3476
ac1f63cdb6d6
mod_auth_token: Check realm against module.host
JC Brand <jc@opkode.com>
parents:
2960
diff
changeset
|
56 |
log("debug", "Verification failed"); |
2960
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
57 |
return false; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
58 |
end |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
59 |
|
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
60 |
return { |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
61 |
OTP_DEVIATION = OTP_DIGITS, |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
62 |
OTP_DIGITS = OTP_DIGITS, |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
63 |
OTP_INTERVAL = OTP_INTERVAL, |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
64 |
DIGEST_TYPE = DIGEST_TYPE, |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
65 |
verify_token = verify_token; |
d0ca211e1b0e
New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff
changeset
|
66 |
} |