Annotate

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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12911
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 local saslprep = require "util.encodings".stringprep.saslprep;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2 local nodeprep = require "util.encodings".stringprep.nodeprep;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 local jid = require "util.jid";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 local json = require "util.json";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 local log = require "util.logger".init("sasl");
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 local _ENV = nil;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 local function oauthbearer(self, message)
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 if not message then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 return "failure", "malformed-request";
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
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 if message == "\001" then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 return "failure", "not-authorized";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 local gs2_authzid, kvpairs = message:match("n,a=([^,]+),(.+)$");
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 if not gs2_authzid then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 return "failure", "malformed-request";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 local auth_header;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 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
25 if k == "auth" then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 auth_header = v;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 break;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 if not auth_header then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 return "failure", "malformed-request";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 local username = jid.prepped_split(gs2_authzid);
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 -- SASLprep username
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 username = saslprep(username);
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 if not username or username == "" then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 log("debug", "Username violates SASLprep.");
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 return "failure", "malformed-request", "Invalid username.";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 local _nodeprep = self.profile.nodeprep;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 if _nodeprep ~= false then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 username = (_nodeprep or nodeprep)(username);
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 if not username or username == "" then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 return "failure", "malformed-request", "Invalid username or password."
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 self.username = username;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 local token = auth_header:match("^Bearer (.+)$");
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 local correct, state, token_info = self.profile.oauthbearer(self, username, token, self.realm);
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 if state == false then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 return "failure", "account-disabled";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 elseif state == nil or not correct then
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62 -- 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
63 -- 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
64 -- the auth backend if available.
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 return "challenge", json.encode({
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 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
67 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
68 ["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
69 });
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 self.resource = token_info.resource;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 self.role = token_info.role;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 return "success";
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 local function init(registerMechanism)
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 registerMechanism("OAUTHBEARER", {"oauthbearer"}, oauthbearer);
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 end
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 return {
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 init = init;
ab1164eda011 util.sasl: Add SASL OAUTHBEARER mechanism (RFC 7628)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 }