plugins/mod_tokenauth.lua
author Matthew Wild <mwild1@gmail.com>
Sun, 17 Mar 2024 10:10:24 +0000
changeset 13464 a688947fab1e
parent 13360 bbbda8819331
permissions -rw-r--r--
mod_bosh: Set base_type on session This fixes a traceback with mod_saslauth. Ideally we move this to util.session at some point, though.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12981
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     1
local base64 = require "prosody.util.encodings".base64;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     2
local hashes = require "prosody.util.hashes";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     3
local id = require "prosody.util.id";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     4
local jid = require "prosody.util.jid";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     5
local random = require "prosody.util.random";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     6
local usermanager = require "prosody.core.usermanager";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     7
local generate_identifier = require "prosody.util.id".short;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
     9
local token_store = module:open_store("auth_tokens", "keyval+");
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
13213
c8d949cf6b09 plugins: Switch to :get_option_period() for time range options
Kim Alvefur <zash@zash.se>
parents: 13103
diff changeset
    11
local access_time_granularity = module:get_option_period("token_auth_access_time_granularity", 60);
13277
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
    12
local empty_grant_lifetime = module:get_option_period("tokenless_grant_ttl", "2w");
12984
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    13
13103
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    14
local function select_role(username, host, role_name)
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    15
	if not role_name then return end
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    16
	local role = usermanager.get_role_by_name(role_name, host);
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    17
	if not role then return end
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    18
	if not usermanager.user_can_assume_role(username, host, role.name) then return end
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    19
	return role;
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    20
end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    21
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    22
function create_grant(actor_jid, grant_jid, grant_ttl, grant_data)
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    23
	grant_jid = jid.prep(grant_jid);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    24
	if not actor_jid or actor_jid ~= grant_jid and not jid.compare(grant_jid, actor_jid) then
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    25
		module:log("debug", "Actor <%s> is not permitted to create a token granting access to JID <%s>", actor_jid, grant_jid);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
		return nil, "not-authorized";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    29
	local grant_username, grant_host, grant_resource = jid.split(grant_jid);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    31
	if grant_host ~= module.host then
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
		return nil, "invalid-host";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    35
	local grant_id = id.short();
12984
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    36
	local now = os.time();
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    37
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    38
	local grant = {
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    39
		id = grant_id;
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
    40
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
		owner = actor_jid;
12984
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    42
		created = now;
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    43
		expires = grant_ttl and (now + grant_ttl) or nil;
12984
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    44
		accessed = now;
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    45
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    46
		jid = grant_jid;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    47
		resource = grant_resource;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    49
		data = grant_data;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    50
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    51
		-- tokens[<hash-name>..":"..<secret>] = token_info
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    52
		tokens = {};
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
	};
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    55
	local ok, err = token_store:set_key(grant_username, grant_id, grant);
13000
e8716515405e mod_tokenauth: return error if storage of new token fails
Matthew Wild <mwild1@gmail.com>
parents: 12984
diff changeset
    56
	if not ok then
e8716515405e mod_tokenauth: return error if storage of new token fails
Matthew Wild <mwild1@gmail.com>
parents: 12984
diff changeset
    57
		return nil, err;
e8716515405e mod_tokenauth: return error if storage of new token fails
Matthew Wild <mwild1@gmail.com>
parents: 12984
diff changeset
    58
	end
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
13007
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    60
	module:fire_event("token-grant-created", {
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    61
		id = grant_id;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    62
		grant = grant;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    63
		username = grant_username;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    64
		host = grant_host;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    65
	});
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    66
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    67
	return grant;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    70
function create_token(grant_jid, grant, token_role, token_ttl, token_purpose, token_data)
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    71
	if (token_data and type(token_data) ~= "table") or (token_purpose and type(token_purpose) ~= "string") then
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    72
		return nil, "bad-request";
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    73
	end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    74
	local grant_username, grant_host = jid.split(grant_jid);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    75
	if grant_host ~= module.host then
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    76
		return nil, "invalid-host";
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    77
	end
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    78
	if type(grant) == "string" then -- lookup by id
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    79
		grant = token_store:get_key(grant_username, grant);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    80
		if not grant then return nil; end
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    81
	end
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    82
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    83
	if not grant.tokens then return nil, "internal-server-error"; end -- old-style token?
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    84
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    85
	local now = os.time();
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    86
	local expires = grant.expires; -- Default to same expiry as grant
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    87
	if token_ttl then -- explicit lifetime requested
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    88
		if expires then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    89
			-- Grant has an expiry, so limit to that or shorter
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    90
			expires = math.min(now + token_ttl, expires);
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    91
		else
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    92
			-- Grant never expires, just use whatever expiry is requested for the token
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    93
			expires = now + token_ttl;
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    94
		end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    95
	end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    96
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    97
	local token_info = {
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    98
		role = token_role;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    99
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   100
		created = now;
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   101
		expires = expires;
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   102
		purpose = token_purpose;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   103
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   104
		data = token_data;
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   105
	};
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   106
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   107
	local token_secret = random.bytes(18);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   108
	grant.tokens["sha256:"..hashes.sha256(token_secret, true)] = token_info;
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   109
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   110
	local ok, err = token_store:set_key(grant_username, grant.id, grant);
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   111
	if not ok then
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   112
		return nil, err;
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   113
	end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   114
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   115
	local token_string = "secret-token:"..base64.encode("2;"..grant.id..";"..token_secret..";"..grant.jid);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   116
	return token_string, token_info;
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   117
end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   118
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   119
local function parse_token(encoded_token)
12921
e4de42495fb7 mod_tokenauth: Gracefully handle missing tokens
Matthew Wild <mwild1@gmail.com>
parents: 12919
diff changeset
   120
	if not encoded_token then return nil; end
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   121
	local encoded_data = encoded_token:match("^secret%-token:(.+)$");
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   122
	if not encoded_data then return nil; end
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   123
	local token = base64.decode(encoded_data);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   124
	if not token then return nil; end
13078
794a5ad5495e mod_tokenauth: Fix parsing binary part of tokens
Kim Alvefur <zash@zash.se>
parents: 13077
diff changeset
   125
	local token_id, token_secret, token_jid = token:match("^2;([^;]+);(..................);(.+)$");
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   126
	if not token_id then return nil; end
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   127
	local token_user, token_host = jid.split(token_jid);
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   128
	return token_id, token_user, token_host, token_secret;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   129
end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   130
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   131
local function clear_expired_grant_tokens(grant, now)
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   132
	local updated;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   133
	now = now or os.time();
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   134
	for secret, token_info in pairs(grant.tokens) do
13003
c87ac7d1967f mod_tokenauth: Fix traceback when checking expiry of tokens with no expiry
Matthew Wild <mwild1@gmail.com>
parents: 13002
diff changeset
   135
		local expires = token_info.expires;
c87ac7d1967f mod_tokenauth: Fix traceback when checking expiry of tokens with no expiry
Matthew Wild <mwild1@gmail.com>
parents: 13002
diff changeset
   136
		if expires and expires < now then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   137
			grant.tokens[secret] = nil;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   138
			updated = true;
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   139
		end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   140
	end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   141
	return updated;
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   142
end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   143
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   144
local function _get_validated_grant_info(username, grant)
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   145
	if type(grant) == "string" then
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   146
		grant = token_store:get_key(username, grant);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   147
	end
13360
bbbda8819331 mod_tokenauth: Ignore invalid grants in storage that have no id
Matthew Wild <mwild1@gmail.com>
parents: 13325
diff changeset
   148
	if not grant or not grant.created or not grant.id then return nil; end
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   149
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   150
	-- Invalidate grants from before last password change
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   151
	local account_info = usermanager.get_account_info(username, module.host);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   152
	local password_updated_at = account_info and account_info.password_updated;
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   153
	local now = os.time();
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   154
	if password_updated_at and grant.created < password_updated_at then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   155
		module:log("debug", "Token grant %s of %s issued before last password change, invalidating it now", grant.id, username);
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   156
		token_store:set_key(username, grant.id, nil);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   157
		return nil, "not-authorized";
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   158
	elseif grant.expires and grant.expires < now then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   159
		module:log("debug", "Token grant %s of %s expired, cleaning up", grant.id, username);
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   160
		token_store:set_key(username, grant.id, nil);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   161
		return nil, "expired";
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   162
	end
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   163
13275
56c1d2498d66 mod_tokenauth: Delete grants in the wrong formats on retrieval
Kim Alvefur <zash@zash.se>
parents: 13250
diff changeset
   164
	if not grant.tokens then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   165
		module:log("debug", "Token grant %s of %s without tokens, cleaning up", grant.id, username);
13275
56c1d2498d66 mod_tokenauth: Delete grants in the wrong formats on retrieval
Kim Alvefur <zash@zash.se>
parents: 13250
diff changeset
   166
		token_store:set_key(username, grant.id, nil);
56c1d2498d66 mod_tokenauth: Delete grants in the wrong formats on retrieval
Kim Alvefur <zash@zash.se>
parents: 13250
diff changeset
   167
		return nil, "invalid";
56c1d2498d66 mod_tokenauth: Delete grants in the wrong formats on retrieval
Kim Alvefur <zash@zash.se>
parents: 13250
diff changeset
   168
	end
13309
852a61c720d0 mod_tokenauth: Fix saving grants after clearing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13280
diff changeset
   169
852a61c720d0 mod_tokenauth: Fix saving grants after clearing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13280
diff changeset
   170
	local found_expired = false
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   171
	for secret_hash, token_info in pairs(grant.tokens) do
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   172
		if token_info.expires and token_info.expires < now then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   173
			module:log("debug", "Token %s of grant %s of %s has expired, cleaning it up", secret_hash:sub(-8), grant.id, username);
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   174
			grant.tokens[secret_hash] = nil;
13279
5db61e0dfc62 mod_tokenauth: Save grant after removing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13278
diff changeset
   175
			found_expired = true;
5db61e0dfc62 mod_tokenauth: Save grant after removing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13278
diff changeset
   176
		end
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   177
	end
13277
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   178
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   179
	if not grant.expires and next(grant.tokens) == nil and grant.accessed + empty_grant_lifetime < now then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   180
		module:log("debug", "Token %s of %s grant has no tokens, discarding", grant.id, username);
13277
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   181
		token_store:set_key(username, grant.id, nil);
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   182
		return nil, "expired";
13309
852a61c720d0 mod_tokenauth: Fix saving grants after clearing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13280
diff changeset
   183
	elseif found_expired then
852a61c720d0 mod_tokenauth: Fix saving grants after clearing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13280
diff changeset
   184
		token_store:set_key(username, grant.id, grant);
13277
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   185
	end
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   186
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   187
	return grant;
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   188
end
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   189
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   190
local function _get_validated_token_info(token_id, token_user, token_host, token_secret)
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   191
	if token_host ~= module.host then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   192
		return nil, "invalid-host";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   193
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   194
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   195
	local grant, err = token_store:get_key(token_user, token_id);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   196
	if not grant or not grant.tokens then
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   197
		if err then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   198
			module:log("error", "Unable to read from token storage: %s", err);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   199
			return nil, "internal-error";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   200
		end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   201
		module:log("warn", "Invalid token in storage (%s / %s)", token_user, token_id);
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   202
		return nil, "not-authorized";
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   203
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   204
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   205
	-- Check provided secret
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   206
	local secret_hash = "sha256:"..hashes.sha256(token_secret, true);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   207
	local token_info = grant.tokens[secret_hash];
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   208
	if not token_info then
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   209
		module:log("debug", "No tokens matched the given secret");
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   210
		return nil, "not-authorized";
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   211
	end
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   212
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   213
	-- Check expiry
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   214
	local now = os.time();
13077
9e5802b45b9e mod_tokenauth: Only check if expiry of expiring tokens
Kim Alvefur <zash@zash.se>
parents: 13028
diff changeset
   215
	if token_info.expires and token_info.expires < now then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   216
		module:log("debug", "Token has expired, cleaning it up");
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   217
		grant.tokens[secret_hash] = nil;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   218
		token_store:set_key(token_user, token_id, grant);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   219
		return nil, "not-authorized";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   220
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   221
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   222
	-- Verify grant validity (expiry, etc.)
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   223
	grant = _get_validated_grant_info(token_user, grant);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   224
	if not grant then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   225
		return nil, "not-authorized";
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   226
	end
12746
126aefd2c4c6 mod_tokenauth: Invalidate tokens issued before most recent password change
Matthew Wild <mwild1@gmail.com>
parents: 12666
diff changeset
   227
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   228
	-- Update last access time if necessary
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   229
	local last_accessed = grant.accessed;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   230
	if not last_accessed or (now - last_accessed) > access_time_granularity then
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   231
		grant.accessed = now;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   232
		clear_expired_grant_tokens(grant); -- Clear expired tokens while we're here
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   233
		token_store:set_key(token_user, token_id, grant);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   234
	end
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   235
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   236
	token_info.id = token_id;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   237
	token_info.grant = grant;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   238
	token_info.jid = grant.jid;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   239
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   240
	return token_info;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   241
end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   242
13014
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   243
function get_grant_info(username, grant_id)
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   244
	local grant = _get_validated_grant_info(username, grant_id);
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   245
	if not grant then return nil; end
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   246
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   247
	-- Caller is only interested in the grant, no need to expose token stuff to them
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   248
	grant.tokens = nil;
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   249
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   250
	return grant;
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   251
end
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   252
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   253
function get_user_grants(username)
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   254
	local grants = token_store:get(username);
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   255
	if not grants then return nil; end
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   256
	for grant_id, grant in pairs(grants) do
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   257
		grants[grant_id] = _get_validated_grant_info(username, grant);
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   258
	end
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   259
	return grants;
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   260
end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   261
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   262
function get_token_info(token)
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   263
	local token_id, token_user, token_host, token_secret = parse_token(token);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   264
	if not token_id then
12956
a668bc1aa39d mod_tokenauth: Log error when token validation fails
Matthew Wild <mwild1@gmail.com>
parents: 12942
diff changeset
   265
		module:log("warn", "Failed to verify access token: %s", token_user);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   266
		return nil, "invalid-token-format";
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   267
	end
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   268
	return _get_validated_token_info(token_id, token_user, token_host, token_secret);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   269
end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   270
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   271
function get_token_session(token, resource)
12963
e331210beeb2 mod_tokenauth: Fix traceback in get_token_session()
Kim Alvefur <zash@zash.se>
parents: 12957
diff changeset
   272
	local token_id, token_user, token_host, token_secret = parse_token(token);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   273
	if not token_id then
12956
a668bc1aa39d mod_tokenauth: Log error when token validation fails
Matthew Wild <mwild1@gmail.com>
parents: 12942
diff changeset
   274
		module:log("warn", "Failed to verify access token: %s", token_user);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   275
		return nil, "invalid-token-format";
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   276
	end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   277
12963
e331210beeb2 mod_tokenauth: Fix traceback in get_token_session()
Kim Alvefur <zash@zash.se>
parents: 12957
diff changeset
   278
	local token_info, err = _get_validated_token_info(token_id, token_user, token_host, token_secret);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   279
	if not token_info then return nil, err; end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   280
13102
65d2ff6e674e mod_tokenauth: Return error instead of session for token without role
Kim Alvefur <zash@zash.se>
parents: 13078
diff changeset
   281
	local role = select_role(token_user, token_host, token_info.role);
65d2ff6e674e mod_tokenauth: Return error instead of session for token without role
Kim Alvefur <zash@zash.se>
parents: 13078
diff changeset
   282
	if not role then return nil, "not-authorized"; end
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   283
	return {
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   284
		username = token_user;
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   285
		host = token_host;
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   286
		resource = token_info.resource or resource or generate_identifier();
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   287
13102
65d2ff6e674e mod_tokenauth: Return error instead of session for token without role
Kim Alvefur <zash@zash.se>
parents: 13078
diff changeset
   288
		role = role;
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   289
	};
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   290
end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   291
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   292
function revoke_token(token)
13250
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   293
	local grant_id, token_user, token_host, token_secret = parse_token(token);
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   294
	if not grant_id then
12956
a668bc1aa39d mod_tokenauth: Log error when token validation fails
Matthew Wild <mwild1@gmail.com>
parents: 12942
diff changeset
   295
		module:log("warn", "Failed to verify access token: %s", token_user);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   296
		return nil, "invalid-token-format";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   297
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   298
	if token_host ~= module.host then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   299
		return nil, "invalid-host";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   300
	end
13250
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   301
	local grant, err = _get_validated_grant_info(token_user, grant_id);
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   302
	if not grant then return grant, err; end
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   303
	local secret_hash = "sha256:"..hashes.sha256(token_secret, true);
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   304
	local token_info = grant.tokens[secret_hash];
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   305
	if not grant or not token_info then
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   306
		return nil, "item-not-found";
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   307
	end
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   308
	grant.tokens[secret_hash] = nil;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   309
	local ok, err = token_store:set_key(token_user, grant_id, grant);
13007
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
   310
	if not ok then
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
   311
		return nil, err;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
   312
	end
13250
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   313
	module:fire_event("token-revoked", {
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   314
		grant_id = grant_id;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   315
		grant = grant;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   316
		info = token_info;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   317
		username = token_user;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   318
		host = token_host;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   319
	});
13007
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
   320
	return true;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   321
end
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   322
13028
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   323
function revoke_grant(username, grant_id)
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   324
	local ok, err = token_store:set_key(username, grant_id, nil);
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   325
	if not ok then return nil, err; end
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   326
	module:fire_event("token-grant-revoked", { id = grant_id, username = username, host = module.host });
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   327
	return true;
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   328
end
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   329
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   330
function sasl_handler(auth_provider, purpose, extra)
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   331
	return function (sasl, token, realm, _authzid)
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   332
		local token_info, err = get_token_info(token);
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   333
		if not token_info then
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   334
			module:log("debug", "SASL handler failed to verify token: %s", err);
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   335
			return nil, nil, extra;
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   336
		end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   337
		local token_user, token_host, resource = jid.split(token_info.grant.jid);
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   338
		if realm ~= token_host or (purpose and token_info.purpose ~= purpose) then
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   339
			return nil, nil, extra;
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   340
		end
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   341
		if auth_provider.is_enabled and not auth_provider.is_enabled(token_user) then
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   342
			return true, false, token_info;
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   343
		end
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   344
		sasl.resource = resource;
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   345
		sasl.token_info = token_info;
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   346
		return token_user, true, token_info;
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   347
	end;
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   348
end
13278
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   349
13280
c34266c061c9 mod_tokenauth: Set name/description on cleanup job
Kim Alvefur <zash@zash.se>
parents: 13279
diff changeset
   350
module:daily("clear expired grants", function()
13278
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   351
	for username in token_store:items() do
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   352
		get_user_grants(username); -- clears out expired grants
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   353
	end
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   354
end)