annotate mod_auth_token/token_auth_utils.lib.lua @ 5193:2bb29ece216b

mod_http_oauth2: Implement stateless dynamic client registration Replaces previous explicit registration that required either the additional module mod_adhoc_oauth2_client or manually editing the database. That method was enough to have something to test with, but would not probably not scale easily. Dynamic client registration allows creating clients on the fly, which may be even easier in theory. In order to not allow basically unauthenticated writes to the database, we implement a stateless model here. per_host_key := HMAC(config -> oauth2_registration_key, hostname) client_id := JWT { client metadata } signed with per_host_key client_secret := HMAC(per_host_key, client_id) This should ensure everything we need to know is part of the client_id, allowing redirects etc to be validated, and the client_secret can be validated with only the client_id and the per_host_key. A nonce injected into the client_id JWT should ensure nobody can submit the same client metadata and retrieve the same client_secret
author Kim Alvefur <zash@zash.se>
date Fri, 03 Mar 2023 21:14:19 +0100
parents 0fb12a4b6106
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2956
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
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
13 local function check_nonce(jid, otp_value, nonce)
2956
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.
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
22 if nonce_cache[jid] == nil or nonce_cache[jid][otp_value] == nil then
2956
d0ca211e1b0e New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff changeset
23 nonce_cache[jid] = {}
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
24 nonce_cache[jid][otp_value] = {}
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
25 nonce_cache[jid][otp_value][nonce] = true
2956
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
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
28 if nonce_cache[jid][otp_value][nonce] == true then
2956
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
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
31 nonce_cache[jid][otp_value][nonce] = true;
2956
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
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
37 local function verify_token(username, password, otp_seed, token_secret, log)
2956
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+) ")
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
40 local otp_value = token:sub(1,8)
2956
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, " (.+)"))
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
43 local jid = username.."@"..module.host
2956
d0ca211e1b0e New HMAC token authentication module for Prosody.
JC Brand <jc@opkode.com>
parents:
diff changeset
44
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
45 if totp:verify(otp_value, OTP_DEVIATION, luatz.time()) then
3472
ac1f63cdb6d6 mod_auth_token: Check realm against module.host
JC Brand <jc@opkode.com>
parents: 2956
diff changeset
46 log("debug", "The TOTP was verified");
2956
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)
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
48 if signature == hmac_ctx:final(otp_value..nonce..jid) then
3472
ac1f63cdb6d6 mod_auth_token: Check realm against module.host
JC Brand <jc@opkode.com>
parents: 2956
diff changeset
49 log("debug", "The key was verified");
3693
0fb12a4b6106 auth_token: Various updates, see below.
JC Brand <jc@opkode.com>
parents: 3568
diff changeset
50 if check_nonce(jid, otp_value, nonce) then
3472
ac1f63cdb6d6 mod_auth_token: Check realm against module.host
JC Brand <jc@opkode.com>
parents: 2956
diff changeset
51 log("debug", "The nonce was verified");
2956
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
3472
ac1f63cdb6d6 mod_auth_token: Check realm against module.host
JC Brand <jc@opkode.com>
parents: 2956
diff changeset
56 log("debug", "Verification failed");
2956
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 }