mod_auth_token/token_auth_utils.lib.lua
author Matthew Wild <mwild1@gmail.com>
Sat, 24 Sep 2022 09:25:46 +0100
changeset 5062 39c2824c2880
parent 3697 0fb12a4b6106
permissions -rw-r--r--
mod_cloud_notify: README overhaul
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
}