File

mod_oidc_userinfo_vcard4/mod_oidc_userinfo_vcard4.lua @ 5536:96dec7681af8

mod_firewall: Update user marks to store instantly via map store The original approach was to keep marks in memory only, and persist them at shutdown. That saves I/O, at the cost of potentially losing marks on an unclean shutdown. This change persists marks instantly, which may have some performance overhead but should be more "correct". It also splits the marking/unmarking into an event which may be watched or even fired by other modules.
author Matthew Wild <mwild1@gmail.com>
date Thu, 08 Jun 2023 16:20:42 +0100
parent 5503:320593cf7d90
child 5555:34b63d0144c3
line wrap: on
line source

-- Provide OpenID UserInfo data to mod_http_oauth2
-- Alternatively, separate module for the whole HTTP endpoint?
--
local nodeprep = require "util.encodings".stringprep.nodeprep;

module:add_item("openid-claim", "address");
module:add_item("openid-claim", "email");
module:add_item("openid-claim", "phone");
module:add_item("openid-claim", "profile");

local mod_pep = module:depends "pep";

local gender_map = { M = "male"; F = "female"; O = "other"; N = "nnot applicable"; U = "unknown" }

module:hook("token/userinfo", function(event)
	local pep_service = mod_pep.get_pep_service(event.username);

	local vcard4 = select(3, pep_service:get_last_item("urn:xmpp:vcard4", true));

	local userinfo = event.userinfo;
	vcard4 = vcard4 and vcard4:get_child("vcard", "urn:ietf:params:xml:ns:vcard-4.0");
	if vcard4 and event.claims:contains("profile") then
		userinfo.name = vcard4:find("fn/text#");
		userinfo.family_name = vcard4:find("n/surname#");
		userinfo.given_name = vcard4:find("n/given#");
		userinfo.middle_name = vcard4:find("n/additional#");

		userinfo.nickname = vcard4:find("nickname/text#");
		if not userinfo.nickname then
			local ok, _, nick_item = pep_service:get_last_item("http://jabber.org/protocol/nick", true);
			if ok and nick_item then
				userinfo.nickname = nick_item:get_child_text("nick", "http://jabber.org/protocol/nick");
			end
		end

		userinfo.preferred_username = event.username;

		-- profile -- page? not their website
		-- picture -- mod_http_pep_avatar?
		userinfo.website = vcard4:find("url/uri#");
		userinfo.birthdate = vcard4:find("bday/date#");
		userinfo.zoneinfo = vcard4:find("tz/text#");
		userinfo.locale = vcard4:find("lang/language-tag#");

		userinfo.gender = gender_map[vcard4:find("gender/sex#")] or vcard4:find("gender/text#");

		-- updated_at -- we don't keep a vcard change timestamp?
	end

	if not userinfo.nickname and event.claims:contains("profile") then
		local ok, _, nick_item = pep_service:get_last_item("http://jabber.org/protocol/nick", true);
		if ok and nick_item then
			userinfo.nickname = nick_item:get_child_text("nick", "http://jabber.org/protocol/nick");
		end
	end

	if vcard4 and event.claims:contains("email") then
		userinfo.email = vcard4:find("email/text#")
		if userinfo.email then
			userinfo.email_verified = false;
		end
	end

	if vcard4 and event.claims:contains("address") then
		local adr = vcard4:get_child("adr");
		if adr then
			userinfo.address = {
				formatted = nil;
				street_address = adr:get_child_text("street");
				locality = adr:get_child_text("locality");
				region = adr:get_child_text("region");
				postal_code = adr:get_child_text("code");
				country = adr:get_child_text("country");
			}
		end
	end

	if vcard4 and event.claims:contains("phone") then
		userinfo.phone = vcard4:find("tel/text#")
		if userinfo.phone then
			userinfo.phone_number_verified = false;
		end
	end


end, 10);