Mercurial > prosody-modules
comparison mod_auth_token/token_auth_utils.lib.lua @ 2956:d0ca211e1b0e
New HMAC token authentication module for Prosody.
author | JC Brand <jc@opkode.com> |
---|---|
date | Tue, 27 Mar 2018 10:48:04 +0200 |
parents | |
children | ac1f63cdb6d6 |
comparison
equal
deleted
inserted
replaced
2938:f000ba14d531 | 2956:d0ca211e1b0e |
---|---|
1 local base64 = require "util.encodings".base64; | |
2 local digest = require "openssl.digest"; | |
3 local hmac = require "openssl.hmac"; | |
4 local luatz = require "luatz"; | |
5 local otp = require "otp"; | |
6 | |
7 local DIGEST_TYPE = "SHA256"; | |
8 local OTP_DEVIATION = 1; | |
9 local OTP_DIGITS = 8; | |
10 local OTP_INTERVAL = 30; | |
11 | |
12 local nonce_cache = {}; | |
13 | |
14 function check_nonce(jid, otp, nonce) | |
15 -- We cache all nonces used per OTP, to ensure that a token cannot be used | |
16 -- more than once. | |
17 -- | |
18 -- 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. | |
20 -- | |
21 -- We only store one OTP per JID, so if a new OTP comes in, we wipe the | |
22 -- previous OTP and its cached nonces. | |
23 if nonce_cache[jid] == nil or nonce_cache[jid][otp] == nil then | |
24 nonce_cache[jid] = {} | |
25 nonce_cache[jid][otp] = {} | |
26 nonce_cache[jid][otp][nonce] = true | |
27 return true; | |
28 end | |
29 if nonce_cache[jid][otp][nonce] == true then | |
30 return false; | |
31 else | |
32 nonce_cache[jid][otp][nonce] = true; | |
33 return true; | |
34 end | |
35 end | |
36 | |
37 | |
38 function verify_token(username, password, realm, otp_seed, token_secret, log) | |
39 local totp = otp.new_totp_from_key(otp_seed, OTP_DIGITS, OTP_INTERVAL) | |
40 local token = string.match(password, "(%d+) ") | |
41 local otp = token:sub(1,8) | |
42 local nonce = token:sub(9) | |
43 local signature = base64.decode(string.match(password, " (.+)")) | |
44 local jid = username.."@"..realm | |
45 | |
46 if totp:verify(otp, OTP_DEVIATION, luatz.gmtime(luatz.time())) then | |
47 -- log("debug", "**** THE OTP WAS VERIFIED ****** "); | |
48 local hmac_ctx = hmac.new(token_secret, DIGEST_TYPE) | |
49 if signature == hmac_ctx:final(otp..nonce..jid) then | |
50 -- log("debug", "**** THE KEY WAS VERIFIED ****** "); | |
51 if check_nonce(jid, otp, nonce) then | |
52 -- log("debug", "**** THE NONCE WAS VERIFIED ****** "); | |
53 return true; | |
54 end | |
55 end | |
56 end | |
57 -- log("debug", "**** VERIFICATION FAILED ****** "); | |
58 return false; | |
59 end | |
60 | |
61 return { | |
62 OTP_DEVIATION = OTP_DIGITS, | |
63 OTP_DIGITS = OTP_DIGITS, | |
64 OTP_INTERVAL = OTP_INTERVAL, | |
65 DIGEST_TYPE = DIGEST_TYPE, | |
66 verify_token = verify_token; | |
67 } |