Software /
code /
prosody
File
plugins/mod_tokenauth.lua @ 12649:86e1187f6274
mod_tokenauth: New API that better fits how modules are using token auth
This also updates the module to the new role API, and improves support for
scope/role selection (currently treated as the same thing, which they almost
are).
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Wed, 20 Jul 2022 10:52:17 +0100 |
parent | 10675:5efd6865486c |
child | 12662:07424992d7fc |
line wrap: on
line source
local id = require "util.id"; local jid = require "util.jid"; local base64 = require "util.encodings".base64; local usermanager = require "core.usermanager"; local generate_identifier = require "util.id".short; local token_store = module:open_store("auth_tokens", "map"); local function select_role(username, host, role) if role then return prosody.hosts[host].authz.get_role_by_name(role); end return usermanager.get_user_default_role(username, host); end function create_jid_token(actor_jid, token_jid, token_role, token_ttl) token_jid = jid.prep(token_jid); if not actor_jid or token_jid ~= actor_jid and not jid.compare(token_jid, actor_jid) then return nil, "not-authorized"; end local token_username, token_host, token_resource = jid.split(token_jid); if token_host ~= module.host then return nil, "invalid-host"; end local token_info = { owner = actor_jid; created = os.time(); expires = token_ttl and (os.time() + token_ttl) or nil; jid = token_jid; resource = token_resource; role = token_role; }; local token_id = id.long(); local token = base64.encode("1;"..jid.join(token_username, token_host)..";"..token_id); token_store:set(token_username, token_id, token_info); return token, token_info; end local function parse_token(encoded_token) local token = base64.decode(encoded_token); if not token then return nil; end local token_jid, token_id = token:match("^1;([^;]+);(.+)$"); if not token_jid then return nil; end local token_user, token_host = jid.split(token_jid); return token_id, token_user, token_host; end local function _get_parsed_token_info(token_id, token_user, token_host) if token_host ~= module.host then return nil, "invalid-host"; end local token_info, err = token_store:get(token_user, token_id); if not token_info then if err then return nil, "internal-error"; end return nil, "not-authorized"; end if token_info.expires and token_info.expires < os.time() then return nil, "not-authorized"; end return token_info end function get_token_info(token) local token_id, token_user, token_host = parse_token(token); if not token_id then return nil, "invalid-token-format"; end return _get_parsed_token_info(token_id, token_user, token_host); end function get_token_session(token, resource) local token_id, token_user, token_host = parse_token(token); if not token_id then return nil, "invalid-token-format"; end local token_info, err = _get_parsed_token_info(token_id, token_user, token_host); if not token_info then return nil, err; end return { username = token_user; host = token_host; resource = token_info.resource or resource or generate_identifier(); role = select_role(token_user, token_host, token_info.role); }; end function revoke_token(token) local token_id, token_user, token_host = parse_token(token); if not token_id then return nil, "invalid-token-format"; end if token_host ~= module.host then return nil, "invalid-host"; end return token_store:set(token_user, token_id, nil); end