util/sasl/oauthbearer.lua
author Kim Alvefur <zash@zash.se>
Fri, 17 Mar 2023 16:23:16 +0100
changeset 12979 d10957394a3c
parent 12955 4cc0785f960e
child 13116 b6aaab0846fe
permissions -rw-r--r--
util: Prefix module imports with prosody namespace
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12979
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12955
diff changeset
     1
local json = require "prosody.util.json";
12915
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
local _ENV = nil;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
local function oauthbearer(self, message)
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
	if not message then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
		return "failure", "malformed-request";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
	end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     9
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
	if message == "\001" then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
		return "failure", "not-authorized";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
	end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
12955
4cc0785f960e util.sasl.oauthbearer: Fix gs2-header parsing
Matthew Wild <mwild1@gmail.com>
parents: 12944
diff changeset
    14
	local gs2_header, kvpairs = message:match("^(n,[^,]*,)(.+)$");
12944
2aebd9bf02fc util.sasl.oauthbearer: Adjust parsing of GS2 to allow lack of authzid
Kim Alvefur <zash@zash.se>
parents: 12942
diff changeset
    15
	if not gs2_header then
12915
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
		return "failure", "malformed-request";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
	end
12944
2aebd9bf02fc util.sasl.oauthbearer: Adjust parsing of GS2 to allow lack of authzid
Kim Alvefur <zash@zash.se>
parents: 12942
diff changeset
    18
	local gs2_authzid = gs2_header:match("^[^,]*,a=([^,]*),$");
12915
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    19
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
	local auth_header;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
	for k, v in kvpairs:gmatch("([a-zA-Z]+)=([\033-\126 \009\r\n]*)\001") do
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
		if k == "auth" then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
			auth_header = v;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
			break;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    25
		end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
	end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
	if not auth_header then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
		return "failure", "malformed-request";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
	end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    31
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
	local token = auth_header:match("^Bearer (.+)$");
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12941
diff changeset
    34
	local username, state, token_info = self.profile.oauthbearer(self, token, self.realm, gs2_authzid);
12915
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    35
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    36
	if state == false then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    37
		return "failure", "account-disabled";
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12941
diff changeset
    38
	elseif state == nil or not username then
12915
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    39
		-- For token-level errors, RFC 7628 demands use of a JSON-encoded
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    40
		-- challenge response upon failure. We relay additional info from
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
		-- the auth backend if available.
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    42
		return "challenge", json.encode({
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    43
			status = token_info and token_info.status or "invalid_token";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
			scope = token_info and token_info.scope or nil;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    45
			["openid-configuration"] = token_info and token_info.oidc_discovery_url or nil;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    46
		});
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    47
	end
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12941
diff changeset
    48
	self.username = username;
12941
23b20ede9c34 util.sasl.oauthbearer: Fix syntax error in b796e08e6376
Matthew Wild <mwild1@gmail.com>
parents: 12940
diff changeset
    49
	self.token_info = token_info;
12940
b796e08e6376 util.sasl.oauthbearer: Attach token_info to sasl handler
Matthew Wild <mwild1@gmail.com>
parents: 12922
diff changeset
    50
12915
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    51
	return "success";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    52
end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
local function init(registerMechanism)
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    55
	registerMechanism("OAUTHBEARER", {"oauthbearer"}, oauthbearer);
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    58
return {
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
	init = init;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
}