Software /
code /
prosody
File
util/sasl/oauthbearer.lua @ 12911:ab1164eda011
util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Wed, 01 Mar 2023 12:55:00 +0000 |
child | 12918:ed20555f163a |
line wrap: on
line source
local saslprep = require "util.encodings".stringprep.saslprep; local nodeprep = require "util.encodings".stringprep.nodeprep; local jid = require "util.jid"; local json = require "util.json"; local log = require "util.logger".init("sasl"); 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 local gs2_authzid, kvpairs = message:match("n,a=([^,]+),(.+)$"); if not gs2_authzid then return "failure", "malformed-request"; end 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 username = jid.prepped_split(gs2_authzid); -- SASLprep username username = saslprep(username); if not username or username == "" then log("debug", "Username violates SASLprep."); return "failure", "malformed-request", "Invalid username."; end local _nodeprep = self.profile.nodeprep; if _nodeprep ~= false then username = (_nodeprep or nodeprep)(username); if not username or username == "" then return "failure", "malformed-request", "Invalid username or password." end end self.username = username; local token = auth_header:match("^Bearer (.+)$"); local correct, state, token_info = self.profile.oauthbearer(self, username, token, self.realm); if state == false then return "failure", "account-disabled"; elseif state == nil or not correct 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.resource = token_info.resource; self.role = token_info.role; return "success"; end local function init(registerMechanism) registerMechanism("OAUTHBEARER", {"oauthbearer"}, oauthbearer); end return { init = init; }