File

util/sasl/oauthbearer.lua @ 13571:ca041359c045

net.server_epoll: Don't try to flush buffer on closed connections Attempt to fix a bug where connections are somehow closed twice, leading to bad things happening elsewhere. With LuaSec, closed connections are generally already too closed to write anything to anyway since it does not support unidirectional shutdown.
author Kim Alvefur <zash@zash.se>
date Tue, 19 Nov 2024 00:41:02 +0100
parent 13112:b6aaab0846fe
line wrap: on
line source

local json = require "prosody.util.json";
local _ENV = nil;


local function oauthbearer(self, message)
	if not message then
		return "failure", "malformed-request";
	end

	if message == "\001" then
		return "failure", "not-authorized";
	end

	-- gs2-header kvsep *kvpair kvsep
	local gs2_header, kvpairs = message:match("^(n,[^,]*,)\001(.+)\001$");
	if not gs2_header then
		return "failure", "malformed-request";
	end
	local gs2_authzid = gs2_header:match("^[^,]*,a=([^,]*),$");

	-- key "=" value kvsep
	local auth_header;
	for k, v in kvpairs:gmatch("([a-zA-Z]+)=([\033-\126 \009\r\n]*)\001") do
		if k == "auth" then
			auth_header = v;
			break;
		end
	end

	if not auth_header then
		return "failure", "malformed-request";
	end

	local token = auth_header:match("^Bearer (.+)$");

	local username, state, token_info = self.profile.oauthbearer(self, token, self.realm, gs2_authzid);

	if state == false then
		return "failure", "account-disabled";
	elseif state == nil or not username then
		-- For token-level errors, RFC 7628 demands use of a JSON-encoded
		-- challenge response upon failure. We relay additional info from
		-- the auth backend if available.
		return "challenge", json.encode({
			status = token_info and token_info.status or "invalid_token";
			scope = token_info and token_info.scope or nil;
			["openid-configuration"] = token_info and token_info.oidc_discovery_url or nil;
		});
	end
	self.username = username;
	self.token_info = token_info;

	return "success";
end

local function init(registerMechanism)
	registerMechanism("OAUTHBEARER", {"oauthbearer"}, oauthbearer);
end

return {
	init = init;
}