author | Kim Alvefur <zash@zash.se> |
Sat, 11 Mar 2023 22:30:58 +0100 | |
changeset 5243 | 8620a635106e |
parent 5241 | 3354f943c1fa |
child 5244 | 001908044d0d |
permissions | -rw-r--r-- |
4267
d3af5f94d6df
mod_http_oauth2: Improve storage of client secret
Kim Alvefur <zash@zash.se>
parents:
4264
diff
changeset
|
1 |
local hashes = require "util.hashes"; |
4275
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4274
diff
changeset
|
2 |
local cache = require "util.cache"; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
3 |
local http = require "util.http"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
4 |
local jid = require "util.jid"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
5 |
local json = require "util.json"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
6 |
local usermanager = require "core.usermanager"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
7 |
local errors = require "util.error"; |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
8 |
local url = require "socket.url"; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
9 |
local uuid = require "util.uuid"; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
10 |
local encodings = require "util.encodings"; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
11 |
local base64 = encodings.base64; |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
12 |
local random = require "util.random"; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
13 |
local schema = require "util.jsonschema"; |
5213
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5212
diff
changeset
|
14 |
local set = require "util.set"; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
15 |
local jwt = require"util.jwt"; |
5207
c60cff787d6a
mod_http_oauth2: Return actually enabled response types in discovery
Kim Alvefur <zash@zash.se>
parents:
5206
diff
changeset
|
16 |
local it = require "util.iterators"; |
c60cff787d6a
mod_http_oauth2: Return actually enabled response types in discovery
Kim Alvefur <zash@zash.se>
parents:
5206
diff
changeset
|
17 |
local array = require "util.array"; |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
18 |
local st = require "util.stanza"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
19 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
20 |
local function read_file(base_path, fn, required) |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
21 |
local f, err = io.open(base_path .. "/" .. fn); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
22 |
if not f then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
23 |
module:log(required and "error" or "debug", "Unable to load template file: %s", err); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
24 |
if required then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
25 |
return error("Failed to load templates"); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
26 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
27 |
return nil; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
28 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
29 |
local data = assert(f:read("*a")); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
30 |
assert(f:close()); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
31 |
return data; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
32 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
33 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
34 |
local template_path = module:get_option_path("oauth2_template_path", "html"); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
35 |
local templates = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
36 |
login = read_file(template_path, "login.html", true); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
37 |
consent = read_file(template_path, "consent.html", true); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
38 |
error = read_file(template_path, "error.html", true); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
39 |
css = read_file(template_path, "style.css"); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
40 |
js = read_file(template_path, "script.js"); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
41 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
42 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
43 |
local site_name = module:get_option_string("site_name", module.host); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
44 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
45 |
local _render_html = require"util.interpolation".new("%b{}", st.xml_escape); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
46 |
local function render_page(template, data, sensitive) |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
47 |
data = data or {}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
48 |
data.site_name = site_name; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
49 |
local resp = { |
5222
1f4b768c831a
mod_http_oauth2: Correct field name for HTTP response status code
Kim Alvefur <zash@zash.se>
parents:
5221
diff
changeset
|
50 |
status_code = 200; |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
51 |
headers = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
52 |
["Content-Type"] = "text/html; charset=utf-8"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
53 |
["Content-Security-Policy"] = "default-src 'self'"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
54 |
["X-Frame-Options"] = "DENY"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
55 |
["Cache-Control"] = (sensitive and "no-store" or "no-cache")..", private"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
56 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
57 |
body = _render_html(template, data); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
58 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
59 |
return resp; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
60 |
end |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 |
|
3919
80dffbbd056b
mod_rest, mod_http_oauth2: Switch from mod_authtokens to mod_tokenauth per Prosody bf81523e2ff4
Matthew Wild <mwild1@gmail.com>
parents:
3912
diff
changeset
|
62 |
local tokens = module:depends("tokenauth"); |
3912
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3907
diff
changeset
|
63 |
|
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
64 |
-- Used to derive client_secret from client_id, set to enable stateless dynamic registration. |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
65 |
local registration_key = module:get_option_string("oauth2_registration_key"); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
66 |
local registration_algo = module:get_option_string("oauth2_registration_algorithm", "HS256"); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
67 |
local registration_options = module:get_option("oauth2_registration_options", { default_ttl = 60 * 60 * 24 * 90 }); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
68 |
|
5203
f48628dc83f1
mod_http_oauth2: Separate client_secret verification key from JWT key
Kim Alvefur <zash@zash.se>
parents:
5202
diff
changeset
|
69 |
local verification_key; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
70 |
local jwt_sign, jwt_verify; |
5200
6b63af56c8ac
mod_http_oauth2: Remove error message
Kim Alvefur <zash@zash.se>
parents:
5199
diff
changeset
|
71 |
if registration_key then |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
72 |
-- Tie it to the host if global |
5203
f48628dc83f1
mod_http_oauth2: Separate client_secret verification key from JWT key
Kim Alvefur <zash@zash.se>
parents:
5202
diff
changeset
|
73 |
verification_key = hashes.hmac_sha256(registration_key, module.host); |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
74 |
jwt_sign, jwt_verify = jwt.init(registration_algo, registration_key, registration_key, registration_options); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
75 |
end |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
76 |
|
5002
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
77 |
local function filter_scopes(username, host, requested_scope_string) |
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
78 |
if host ~= module.host then |
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
79 |
return usermanager.get_jid_role(username.."@"..host, module.host).name; |
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
80 |
end |
5002
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
81 |
|
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
82 |
if requested_scope_string then -- Specific role requested |
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
83 |
-- TODO: The requested scope string is technically a space-delimited list |
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
84 |
-- of scopes, but for simplicity we're mapping this slot to role names. |
5010
5dadbe0718f1
mod_http_oauth2: Update for new new role API
Matthew Wild <mwild1@gmail.com>
parents:
5002
diff
changeset
|
85 |
if usermanager.user_can_assume_role(username, module.host, requested_scope_string) then |
5002
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
86 |
return requested_scope_string; |
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
87 |
end |
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
88 |
end |
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
89 |
|
5010
5dadbe0718f1
mod_http_oauth2: Update for new new role API
Matthew Wild <mwild1@gmail.com>
parents:
5002
diff
changeset
|
90 |
return usermanager.get_user_role(username, module.host).name; |
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
91 |
end |
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
92 |
|
5217
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5214
diff
changeset
|
93 |
local function code_expires_in(code) --> number, seconds until code expires |
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5214
diff
changeset
|
94 |
return os.difftime(code.expires, os.time()); |
4673
d3434fd151b5
mod_http_oauth2: Optimize cleanup timer
Kim Alvefur <zash@zash.se>
parents:
4374
diff
changeset
|
95 |
end |
d3434fd151b5
mod_http_oauth2: Optimize cleanup timer
Kim Alvefur <zash@zash.se>
parents:
4374
diff
changeset
|
96 |
|
5217
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5214
diff
changeset
|
97 |
local function code_expired(code) --> boolean, true: has expired, false: still valid |
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5214
diff
changeset
|
98 |
return code_expires_in(code) < 0; |
4273
143515d0b212
mod_http_oauth2: Factor out authorization code validity decision
Kim Alvefur <zash@zash.se>
parents:
4269
diff
changeset
|
99 |
end |
143515d0b212
mod_http_oauth2: Factor out authorization code validity decision
Kim Alvefur <zash@zash.se>
parents:
4269
diff
changeset
|
100 |
|
4275
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4274
diff
changeset
|
101 |
local codes = cache.new(10000, function (_, code) |
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4274
diff
changeset
|
102 |
return code_expired(code) |
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4274
diff
changeset
|
103 |
end); |
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4274
diff
changeset
|
104 |
|
5217
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5214
diff
changeset
|
105 |
-- Periodically clear out unredeemed codes. Does not need to be exact, expired |
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5214
diff
changeset
|
106 |
-- codes are rejected if tried. Mostly just to keep memory usage in check. |
4276
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4275
diff
changeset
|
107 |
module:add_timer(900, function() |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4275
diff
changeset
|
108 |
local k, code = codes:tail(); |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4275
diff
changeset
|
109 |
while code and code_expired(code) do |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4275
diff
changeset
|
110 |
codes:set(k, nil); |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4275
diff
changeset
|
111 |
k, code = codes:tail(); |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4275
diff
changeset
|
112 |
end |
4673
d3434fd151b5
mod_http_oauth2: Optimize cleanup timer
Kim Alvefur <zash@zash.se>
parents:
4374
diff
changeset
|
113 |
return code and code_expires_in(code) + 1 or 900; |
4276
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4275
diff
changeset
|
114 |
end) |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4275
diff
changeset
|
115 |
|
5211
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5210
diff
changeset
|
116 |
local function get_issuer() |
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5210
diff
changeset
|
117 |
return (module:http_url(nil, "/"):gsub("/$", "")); |
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5210
diff
changeset
|
118 |
end |
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5210
diff
changeset
|
119 |
|
5213
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5212
diff
changeset
|
120 |
local loopbacks = set.new({ "localhost", "127.0.0.1", "::1" }); |
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5212
diff
changeset
|
121 |
local function is_secure_redirect(uri) |
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5212
diff
changeset
|
122 |
local u = url.parse(uri); |
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5212
diff
changeset
|
123 |
return u.scheme ~= "http" or loopbacks:contains(u.host); |
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5212
diff
changeset
|
124 |
end |
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5212
diff
changeset
|
125 |
|
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
126 |
local function oauth_error(err_name, err_desc) |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
127 |
return errors.new({ |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
128 |
type = "modify"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
129 |
condition = "bad-request"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
130 |
code = err_name == "invalid_client" and 401 or 400; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
131 |
text = err_desc and (err_name..": "..err_desc) or err_name; |
4280
ec33b3b1136c
mod_http_oauth2: Fix passing OAuth-specific error details
Kim Alvefur <zash@zash.se>
parents:
4276
diff
changeset
|
132 |
extra = { oauth2_response = { error = err_name, error_description = err_desc } }; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
133 |
}); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
134 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
135 |
|
3922
dea6bea2ddd3
mod_http_oauth2: Refactor re-joining of JID out of token constructor
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
136 |
local function new_access_token(token_jid, scope, ttl) |
5186
20ba6340f524
mod_http_oauth2: Issue tokens for the purpose of 'oauth2'
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
137 |
local token = tokens.create_jid_token(token_jid, token_jid, scope, ttl, nil, "oauth2"); |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
138 |
return { |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
139 |
token_type = "bearer"; |
3912
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3907
diff
changeset
|
140 |
access_token = token; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
141 |
expires_in = ttl; |
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
142 |
scope = scope; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
143 |
-- TODO: include refresh_token when implemented |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
144 |
}; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
145 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
146 |
|
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
147 |
local function get_redirect_uri(client, query_redirect_uri) -- record client, string : string |
5223
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
148 |
if not query_redirect_uri then |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
149 |
if #client.redirect_uris ~= 1 then |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
150 |
-- Client registered multiple URIs, it needs specify which one to use |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
151 |
return; |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
152 |
end |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
153 |
-- When only a single URI is registered, that's the default |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
154 |
return client.redirect_uris[1]; |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
155 |
end |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
156 |
-- Verify the client-provided URI matches one previously registered |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
157 |
for _, redirect_uri in ipairs(client.redirect_uris) do |
5223
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
158 |
if query_redirect_uri == redirect_uri then |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
159 |
return redirect_uri |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
160 |
end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
161 |
end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
162 |
end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
163 |
|
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
164 |
local grant_type_handlers = {}; |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
165 |
local response_type_handlers = {}; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
166 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
167 |
function grant_type_handlers.password(params) |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
168 |
local request_jid = assert(params.username, oauth_error("invalid_request", "missing 'username' (JID)")); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
169 |
local request_password = assert(params.password, oauth_error("invalid_request", "missing 'password'")); |
3923
8ed261a08a9c
mod_http_oauth2: Allow creation of full JID tokens
Kim Alvefur <zash@zash.se>
parents:
3922
diff
changeset
|
170 |
local request_username, request_host, request_resource = jid.prepped_split(request_jid); |
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
171 |
|
3912
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3907
diff
changeset
|
172 |
if not (request_username and request_host) or request_host ~= module.host then |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
173 |
return oauth_error("invalid_request", "invalid JID"); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
174 |
end |
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
175 |
if not usermanager.test_password(request_username, request_host, request_password) then |
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
176 |
return oauth_error("invalid_grant", "incorrect credentials"); |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
177 |
end |
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
178 |
|
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
179 |
local granted_jid = jid.join(request_username, request_host, request_resource); |
5002
5ab134b7e510
mod_http_oauth2: Updates for Prosody's new role API (backwards-compatible)
Matthew Wild <mwild1@gmail.com>
parents:
4674
diff
changeset
|
180 |
local granted_scopes = filter_scopes(request_username, request_host, params.scope); |
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
181 |
return json.encode(new_access_token(granted_jid, granted_scopes, nil)); |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
182 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
183 |
|
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
184 |
function response_type_handlers.code(client, params, granted_jid) |
5195
f5a58cbe86e4
mod_http_oauth2: Derive scope from correct user details
Kim Alvefur <zash@zash.se>
parents:
5194
diff
changeset
|
185 |
local request_username, request_host = jid.split(granted_jid); |
f5a58cbe86e4
mod_http_oauth2: Derive scope from correct user details
Kim Alvefur <zash@zash.se>
parents:
5194
diff
changeset
|
186 |
local granted_scopes = filter_scopes(request_username, request_host, params.scope); |
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
187 |
|
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
188 |
local code = uuid.generate(); |
4674
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4673
diff
changeset
|
189 |
local ok = codes:set(params.client_id .. "#" .. code, { |
5217
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5214
diff
changeset
|
190 |
expires = os.time() + 600; |
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
191 |
granted_jid = granted_jid; |
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
192 |
granted_scopes = granted_scopes; |
4674
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4673
diff
changeset
|
193 |
}); |
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4673
diff
changeset
|
194 |
if not ok then |
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4673
diff
changeset
|
195 |
return {status_code = 429}; |
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4673
diff
changeset
|
196 |
end |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
197 |
|
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
198 |
local redirect_uri = get_redirect_uri(client, params.redirect_uri); |
5192
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
199 |
if redirect_uri == "urn:ietf:wg:oauth:2.0:oob" then |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
200 |
-- TODO some nicer template page |
5210
31c62df82aa8
mod_http_oauth2: Clarify comment referencing mod_http_errors (thanks MattJ)
Kim Alvefur <zash@zash.se>
parents:
5209
diff
changeset
|
201 |
-- mod_http_errors will set content-type to text/html if it catches this |
31c62df82aa8
mod_http_oauth2: Clarify comment referencing mod_http_errors (thanks MattJ)
Kim Alvefur <zash@zash.se>
parents:
5209
diff
changeset
|
202 |
-- event, if not text/plain is kept for the fallback text. |
5192
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
203 |
local response = { status_code = 200; headers = { content_type = "text/plain" } } |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
204 |
response.body = module:context("*"):fire_event("http-message", { |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
205 |
response = response; |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
206 |
title = "Your authorization code"; |
5199
b4932915e773
mod_http_oauth2: Mention name of client when giving out OOB authorization code
Kim Alvefur <zash@zash.se>
parents:
5198
diff
changeset
|
207 |
message = "Here's your authorization code, copy and paste it into " .. (client.client_name or "your client"); |
5192
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
208 |
extra = code; |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
209 |
}) or ("Here's your authorization code:\n%s\n"):format(code); |
5194
1733f184e2bb
mod_http_oauth2: Fix to actually return OOB response
Kim Alvefur <zash@zash.se>
parents:
5193
diff
changeset
|
210 |
return response; |
5223
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
211 |
elseif not redirect_uri then |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
212 |
return {status_code = 400}; |
5192
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
213 |
end |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
214 |
|
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
215 |
local redirect = url.parse(redirect_uri); |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5191
diff
changeset
|
216 |
|
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
217 |
local query = http.formdecode(redirect.query or ""); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
218 |
if type(query) ~= "table" then query = {}; end |
5196
03aa9baa9ac3
mod_http_oauth2: Add support for 'iss' authz response parameter (RFC 9207)
Matthew Wild <mwild1@gmail.com>
parents:
5195
diff
changeset
|
219 |
table.insert(query, { name = "code", value = code }); |
5211
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5210
diff
changeset
|
220 |
table.insert(query, { name = "iss", value = get_issuer() }); |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
221 |
if params.state then |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
222 |
table.insert(query, { name = "state", value = params.state }); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
223 |
end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
224 |
redirect.query = http.formencode(query); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
225 |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
226 |
return { |
5214
898575a0c6f3
mod_http_oauth2: Switch to '303 See Other' redirects
Matthew Wild <mwild1@gmail.com>
parents:
5213
diff
changeset
|
227 |
status_code = 303; |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
228 |
headers = { |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
229 |
location = url.build(redirect); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
230 |
}; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
231 |
} |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
232 |
end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
233 |
|
5190
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
234 |
-- Implicit flow |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
235 |
function response_type_handlers.token(client, params, granted_jid) |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
236 |
local request_username, request_host = jid.split(granted_jid); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
237 |
local granted_scopes = filter_scopes(request_username, request_host, params.scope); |
5190
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
238 |
local token_info = new_access_token(granted_jid, granted_scopes, nil); |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
239 |
|
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
240 |
local redirect = url.parse(get_redirect_uri(client, params.redirect_uri)); |
5190
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
241 |
token_info.state = params.state; |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
242 |
redirect.fragment = http.formencode(token_info); |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
243 |
|
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
244 |
return { |
5214
898575a0c6f3
mod_http_oauth2: Switch to '303 See Other' redirects
Matthew Wild <mwild1@gmail.com>
parents:
5213
diff
changeset
|
245 |
status_code = 303; |
5190
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
246 |
headers = { |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
247 |
location = url.build(redirect); |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
248 |
}; |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
249 |
} |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
250 |
end |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
251 |
|
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
252 |
local function make_secret(client_id) --> client_secret |
5203
f48628dc83f1
mod_http_oauth2: Separate client_secret verification key from JWT key
Kim Alvefur <zash@zash.se>
parents:
5202
diff
changeset
|
253 |
return hashes.hmac_sha256(verification_key, client_id, true); |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
254 |
end |
4267
d3af5f94d6df
mod_http_oauth2: Improve storage of client secret
Kim Alvefur <zash@zash.se>
parents:
4264
diff
changeset
|
255 |
|
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
256 |
local function verify_secret(client_id, client_secret) |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
257 |
return hashes.equals(make_secret(client_id), client_secret); |
4267
d3af5f94d6df
mod_http_oauth2: Improve storage of client secret
Kim Alvefur <zash@zash.se>
parents:
4264
diff
changeset
|
258 |
end |
d3af5f94d6df
mod_http_oauth2: Improve storage of client secret
Kim Alvefur <zash@zash.se>
parents:
4264
diff
changeset
|
259 |
|
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
260 |
function grant_type_handlers.authorization_code(params) |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
261 |
if not params.client_id then return oauth_error("invalid_request", "missing 'client_id'"); end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
262 |
if not params.client_secret then return oauth_error("invalid_request", "missing 'client_secret'"); end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
263 |
if not params.code then return oauth_error("invalid_request", "missing 'code'"); end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
264 |
if params.scope and params.scope ~= "" then |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
265 |
return oauth_error("invalid_scope", "unknown scope requested"); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
266 |
end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
267 |
|
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
268 |
local client = jwt_verify(params.client_id); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
269 |
if not client then |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
270 |
return oauth_error("invalid_client", "incorrect credentials"); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
271 |
end |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
272 |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
273 |
if not verify_secret(params.client_id, params.client_secret) then |
4264
c539334dd01a
mod_http_oauth2: Rescope oauth client config into users' storage
Kim Alvefur <zash@zash.se>
parents:
4263
diff
changeset
|
274 |
module:log("debug", "client_secret mismatch"); |
c539334dd01a
mod_http_oauth2: Rescope oauth client config into users' storage
Kim Alvefur <zash@zash.se>
parents:
4263
diff
changeset
|
275 |
return oauth_error("invalid_client", "incorrect credentials"); |
c539334dd01a
mod_http_oauth2: Rescope oauth client config into users' storage
Kim Alvefur <zash@zash.se>
parents:
4263
diff
changeset
|
276 |
end |
4275
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4274
diff
changeset
|
277 |
local code, err = codes:get(params.client_id .. "#" .. params.code); |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
278 |
if err then error(err); end |
5218
d5492bc861f6
mod_http_oauth2: Remove authorization codes after use
Kim Alvefur <zash@zash.se>
parents:
5217
diff
changeset
|
279 |
-- MUST NOT use the authorization code more than once, so remove it to |
d5492bc861f6
mod_http_oauth2: Remove authorization codes after use
Kim Alvefur <zash@zash.se>
parents:
5217
diff
changeset
|
280 |
-- prevent a second attempted use |
d5492bc861f6
mod_http_oauth2: Remove authorization codes after use
Kim Alvefur <zash@zash.se>
parents:
5217
diff
changeset
|
281 |
codes:set(params.client_id .. "#" .. params.code, nil); |
4273
143515d0b212
mod_http_oauth2: Factor out authorization code validity decision
Kim Alvefur <zash@zash.se>
parents:
4269
diff
changeset
|
282 |
if not code or type(code) ~= "table" or code_expired(code) then |
4264
c539334dd01a
mod_http_oauth2: Rescope oauth client config into users' storage
Kim Alvefur <zash@zash.se>
parents:
4263
diff
changeset
|
283 |
module:log("debug", "authorization_code invalid or expired: %q", code); |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
284 |
return oauth_error("invalid_client", "incorrect credentials"); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
285 |
end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
286 |
|
4344
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4280
diff
changeset
|
287 |
return json.encode(new_access_token(code.granted_jid, code.granted_scopes, nil)); |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
288 |
end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
289 |
|
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
290 |
-- Used to issue/verify short-lived tokens for the authorization process below |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
291 |
local new_user_token, verify_user_token = jwt.init("HS256", random.bytes(32), nil, { default_ttl = 600 }); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
292 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
293 |
-- From the given request, figure out if the user is authenticated and has granted consent yet |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
294 |
-- As this requires multiple steps (seek credentials, seek consent), we have a lot of state to |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
295 |
-- carry around across requests. We also need to protect against CSRF and session mix-up attacks |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
296 |
-- (e.g. the user may have multiple concurrent flows in progress, session cookies aren't unique |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
297 |
-- to one of them). |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
298 |
-- Our strategy here is to preserve the original query string (containing the authz request), and |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
299 |
-- encode the rest of the flow in form POSTs. |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
300 |
local function get_auth_state(request) |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
301 |
local form = request.method == "POST" |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
302 |
and request.body |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
303 |
and #request.body > 0 |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
304 |
and request.headers.content_type == "application/x-www-form-urlencoded" |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
305 |
and http.formdecode(request.body); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
306 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
307 |
if not form then return {}; end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
308 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
309 |
if not form.user_token then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
310 |
-- First step: login |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
311 |
local username = encodings.stringprep.nodeprep(form.username); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
312 |
local password = encodings.stringprep.saslprep(form.password); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
313 |
if not (username and password) or not usermanager.test_password(username, module.host, password) then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
314 |
return { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
315 |
error = "Invalid username/password"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
316 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
317 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
318 |
return { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
319 |
user = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
320 |
username = username; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
321 |
host = module.host; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
322 |
token = new_user_token({ username = username, host = module.host }); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
323 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
324 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
325 |
elseif form.user_token and form.consent then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
326 |
-- Second step: consent |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
327 |
local ok, user = verify_user_token(form.user_token); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
328 |
if not ok then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
329 |
return { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
330 |
error = user == "token-expired" and "Session expired - try again" or nil; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
331 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
332 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
333 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
334 |
user.token = form.user_token; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
335 |
return { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
336 |
user = user; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
337 |
consent = form.consent == "granted"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
338 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
339 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
340 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
341 |
return {}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
342 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
343 |
|
5226
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
344 |
local function get_request_credentials(request) |
5228
cd5cf4cc6304
mod_http_oauth2: Fail early when no authorization header present
Matthew Wild <mwild1@gmail.com>
parents:
5227
diff
changeset
|
345 |
if not request.headers.authorization then return; end |
cd5cf4cc6304
mod_http_oauth2: Fail early when no authorization header present
Matthew Wild <mwild1@gmail.com>
parents:
5227
diff
changeset
|
346 |
|
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
347 |
local auth_type, auth_data = string.match(request.headers.authorization, "^(%S+)%s(.+)$"); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
348 |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
349 |
if auth_type == "Basic" then |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
350 |
local creds = base64.decode(auth_data); |
5226
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
351 |
if not creds then return; end |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
352 |
local username, password = string.match(creds, "^([^:]+):(.*)$"); |
5226
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
353 |
if not username then return; end |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
354 |
return { |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
355 |
type = "basic"; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
356 |
username = username; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
357 |
password = password; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
358 |
}; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
359 |
elseif auth_type == "Bearer" then |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
360 |
return { |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
361 |
type = "bearer"; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
362 |
bearer_token = auth_data; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
363 |
}; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
364 |
end |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
365 |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
366 |
return nil; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
367 |
end |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
368 |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
369 |
local function check_credentials(request, allow_token) |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
370 |
local credentials = get_request_credentials(request); |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
371 |
if not credentials then return nil; end |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
372 |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
373 |
if credentials.username and credentials.password then |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
374 |
local username = encodings.stringprep.nodeprep(credentials.username); |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
375 |
local password = encodings.stringprep.saslprep(credentials.password); |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
376 |
if not (username and password) then return false; end |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
377 |
if not usermanager.test_password(username, module.host, password) then |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
378 |
return false; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
379 |
end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
380 |
return username; |
5226
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
381 |
elseif allow_token and credentials.bearer_token then |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5225
diff
changeset
|
382 |
local token_info = tokens.get_token_info(credentials.bearer_token); |
4374
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
383 |
if not token_info or not token_info.session or token_info.session.host ~= module.host then |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
384 |
return false; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
385 |
end |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
386 |
return token_info.session.username; |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
387 |
end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
388 |
return nil; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
389 |
end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
390 |
|
3924
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
391 |
if module:get_host_type() == "component" then |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
392 |
local component_secret = assert(module:get_option_string("component_secret"), "'component_secret' is a required setting when loaded on a Component"); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
393 |
|
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
394 |
function grant_type_handlers.password(params) |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
395 |
local request_jid = assert(params.username, oauth_error("invalid_request", "missing 'username' (JID)")); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
396 |
local request_password = assert(params.password, oauth_error("invalid_request", "missing 'password'")); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
397 |
local request_username, request_host, request_resource = jid.prepped_split(request_jid); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
398 |
if params.scope then |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
399 |
return oauth_error("invalid_scope", "unknown scope requested"); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
400 |
end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
401 |
if not request_host or request_host ~= module.host then |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
402 |
return oauth_error("invalid_request", "invalid JID"); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
403 |
end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
404 |
if request_password == component_secret then |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
405 |
local granted_jid = jid.join(request_username, request_host, request_resource); |
4261
145e8e8a247a
mod_http_oauth2: Fix incomplete function arity change in dea6bea2ddd3
Kim Alvefur <zash@zash.se>
parents:
4260
diff
changeset
|
406 |
return json.encode(new_access_token(granted_jid, nil, nil)); |
3924
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
407 |
end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
408 |
return oauth_error("invalid_grant", "incorrect credentials"); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
409 |
end |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
410 |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
411 |
-- TODO How would this make sense with components? |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
412 |
-- Have an admin authenticate maybe? |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
413 |
response_type_handlers.code = nil; |
5190
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5189
diff
changeset
|
414 |
response_type_handlers.token = nil; |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
415 |
grant_type_handlers.authorization_code = nil; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
416 |
check_credentials = function () return false end |
3924
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
417 |
end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
418 |
|
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
419 |
-- OAuth errors should be returned to the client if possible, i.e. by |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
420 |
-- appending the error information to the redirect_uri and sending the |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
421 |
-- redirect to the user-agent. In some cases we can't do this, e.g. if |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
422 |
-- the redirect_uri is missing or invalid. In those cases, we render an |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
423 |
-- error directly to the user-agent. |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
424 |
local function error_response(request, err) |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
425 |
local q = request.url.query and http.formdecode(request.url.query); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
426 |
local redirect_uri = q and q.redirect_uri; |
5221
6a27effb3ef0
mod_http_oauth2: Fix incorrect function name (thanks Zash/luacheck)
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
427 |
if not redirect_uri or not is_secure_redirect(redirect_uri) then |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
428 |
module:log("warn", "Missing or invalid redirect_uri <%s>, rendering error to user-agent", redirect_uri or ""); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
429 |
return render_page(templates.error, { error = err }); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
430 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
431 |
local redirect_query = url.parse(redirect_uri); |
5233
c24a622a7b85
mod_http_oauth2: Fix appending of query parts in error redirects
Kim Alvefur <zash@zash.se>
parents:
5232
diff
changeset
|
432 |
local sep = redirect_query.query and "&" or "?"; |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
433 |
redirect_uri = redirect_uri |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
434 |
.. sep .. http.formencode(err.extra.oauth2_response) |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
435 |
.. "&" .. http.formencode({ state = q.state, iss = get_issuer() }); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
436 |
module:log("warn", "Sending error response to client via redirect to %s", redirect_uri); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
437 |
return { |
5214
898575a0c6f3
mod_http_oauth2: Switch to '303 See Other' redirects
Matthew Wild <mwild1@gmail.com>
parents:
5213
diff
changeset
|
438 |
status_code = 303; |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
439 |
headers = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
440 |
location = redirect_uri; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
441 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
442 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
443 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
444 |
|
5191
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
445 |
local allowed_grant_type_handlers = module:get_option_set("allowed_oauth2_grant_types", {"authorization_code", "password"}) |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
446 |
for handler_type in pairs(grant_type_handlers) do |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
447 |
if not allowed_grant_type_handlers:contains(handler_type) then |
5234
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5233
diff
changeset
|
448 |
module:log("debug", "Grant type %q disabled", handler_type); |
5191
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
449 |
grant_type_handlers[handler_type] = nil; |
5234
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5233
diff
changeset
|
450 |
else |
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5233
diff
changeset
|
451 |
module:log("debug", "Grant type %q enabled", handler_type); |
5191
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
452 |
end |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
453 |
end |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
454 |
|
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
455 |
-- "token" aka implicit flow is considered insecure |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
456 |
local allowed_response_type_handlers = module:get_option_set("allowed_oauth2_response_types", {"code"}) |
5202
2e8a7a0f932d
mod_http_oauth2: Fix response type config
Kim Alvefur <zash@zash.se>
parents:
5200
diff
changeset
|
457 |
for handler_type in pairs(response_type_handlers) do |
2e8a7a0f932d
mod_http_oauth2: Fix response type config
Kim Alvefur <zash@zash.se>
parents:
5200
diff
changeset
|
458 |
if not allowed_response_type_handlers:contains(handler_type) then |
5234
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5233
diff
changeset
|
459 |
module:log("debug", "Response type %q disabled", handler_type); |
5235
bef543068077
mod_http_oauth2: Fix to disable disabled response handlers correctly
Kim Alvefur <zash@zash.se>
parents:
5234
diff
changeset
|
460 |
response_type_handlers[handler_type] = nil; |
5234
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5233
diff
changeset
|
461 |
else |
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5233
diff
changeset
|
462 |
module:log("debug", "Response type %q enabled", handler_type); |
5191
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
463 |
end |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
464 |
end |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
465 |
|
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
466 |
function handle_token_grant(event) |
5227
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5226
diff
changeset
|
467 |
local credentials = get_request_credentials(event.request); |
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5226
diff
changeset
|
468 |
|
3938
469408682152
mod_http_oauth2: Set content type on successful repsponses (fixes #1501)
Kim Alvefur <zash@zash.se>
parents:
3924
diff
changeset
|
469 |
event.response.headers.content_type = "application/json"; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
470 |
local params = http.formdecode(event.request.body); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
471 |
if not params then |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
472 |
return error_response(event.request, oauth_error("invalid_request")); |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
473 |
end |
5227
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5226
diff
changeset
|
474 |
|
5229
3439eb37f23b
mod_http_oauth2: token endpoint: handle missing credentials
Matthew Wild <mwild1@gmail.com>
parents:
5228
diff
changeset
|
475 |
if credentials and credentials.type == "basic" then |
5227
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5226
diff
changeset
|
476 |
params.client_id = http.urldecode(credentials.username); |
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5226
diff
changeset
|
477 |
params.client_secret = http.urldecode(credentials.password); |
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5226
diff
changeset
|
478 |
end |
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5226
diff
changeset
|
479 |
|
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
480 |
local grant_type = params.grant_type |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
481 |
local grant_handler = grant_type_handlers[grant_type]; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
482 |
if not grant_handler then |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
483 |
return error_response(event.request, oauth_error("unsupported_grant_type")); |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
484 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
485 |
return grant_handler(params); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
486 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
487 |
|
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
488 |
local function handle_authorization_request(event) |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
489 |
local request = event.request; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
490 |
|
4262
cc712899becd
mod_http_oauth2: Unpack event object to improve readability
Kim Alvefur <zash@zash.se>
parents:
4261
diff
changeset
|
491 |
if not request.url.query then |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
492 |
return error_response(request, oauth_error("invalid_request")); |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
493 |
end |
4262
cc712899becd
mod_http_oauth2: Unpack event object to improve readability
Kim Alvefur <zash@zash.se>
parents:
4261
diff
changeset
|
494 |
local params = http.formdecode(request.url.query); |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
495 |
if not params then |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
496 |
return error_response(request, oauth_error("invalid_request")); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
497 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
498 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
499 |
if not params.client_id then return oauth_error("invalid_request", "missing 'client_id'"); end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
500 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
501 |
local ok, client = jwt_verify(params.client_id); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
502 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
503 |
if not ok then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
504 |
return oauth_error("invalid_client", "incorrect credentials"); |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
505 |
end |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
506 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
507 |
local auth_state = get_auth_state(request); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
508 |
if not auth_state.user then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
509 |
-- Render login page |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
510 |
return render_page(templates.login, { state = auth_state, client = client }); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
511 |
elseif auth_state.consent == nil then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
512 |
-- Render consent page |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
513 |
return render_page(templates.consent, { state = auth_state, client = client }, true); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
514 |
elseif not auth_state.consent then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
515 |
-- Notify client of rejection |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
516 |
return error_response(request, oauth_error("access_denied")); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
517 |
end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
518 |
|
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
519 |
local response_type = params.response_type; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
520 |
local response_handler = response_type_handlers[response_type]; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
521 |
if not response_handler then |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
522 |
return error_response(request, oauth_error("unsupported_response_type")); |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
523 |
end |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
524 |
return response_handler(client, params, jid.join(auth_state.user.username, module.host)); |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
525 |
end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
526 |
|
4374
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
527 |
local function handle_revocation_request(event) |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
528 |
local request, response = event.request, event.response; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
529 |
if not request.headers.authorization then |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
530 |
response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
531 |
return 401; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
532 |
elseif request.headers.content_type ~= "application/x-www-form-urlencoded" |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
533 |
or not request.body or request.body == "" then |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
534 |
return 400; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
535 |
end |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
536 |
local user = check_credentials(request, true); |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
537 |
if not user then |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
538 |
return 401; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
539 |
end |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
540 |
|
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
541 |
local form_data = http.formdecode(event.request.body); |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
542 |
if not form_data or not form_data.token then |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
543 |
return 400; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
544 |
end |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
545 |
local ok, err = tokens.revoke_token(form_data.token); |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
546 |
if not ok then |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
547 |
module:log("warn", "Unable to revoke token: %s", tostring(err)); |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
548 |
return 500; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
549 |
end |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
550 |
return 200; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
551 |
end |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
552 |
|
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
553 |
local registration_schema = { |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
554 |
type = "object"; |
5241
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5240
diff
changeset
|
555 |
required = { |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5240
diff
changeset
|
556 |
-- These are shown to users in the template |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5240
diff
changeset
|
557 |
"client_name"; |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5240
diff
changeset
|
558 |
"client_uri"; |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5240
diff
changeset
|
559 |
-- We need at least one redirect URI for things to work |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5240
diff
changeset
|
560 |
"redirect_uris"; |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5240
diff
changeset
|
561 |
}; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
562 |
properties = { |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
563 |
redirect_uris = { type = "array"; minLength = 1; items = { type = "string"; format = "uri" } }; |
5240
ff8623e2f9d9
mod_http_oauth2: Reorder client metadata validation schema
Kim Alvefur <zash@zash.se>
parents:
5235
diff
changeset
|
564 |
token_endpoint_auth_method = { type = "string"; enum = { "none"; "client_secret_post"; "client_secret_basic" } }; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
565 |
grant_types = { |
5240
ff8623e2f9d9
mod_http_oauth2: Reorder client metadata validation schema
Kim Alvefur <zash@zash.se>
parents:
5235
diff
changeset
|
566 |
type = "array"; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
567 |
items = { |
5240
ff8623e2f9d9
mod_http_oauth2: Reorder client metadata validation schema
Kim Alvefur <zash@zash.se>
parents:
5235
diff
changeset
|
568 |
type = "string"; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
569 |
enum = { |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
570 |
"authorization_code"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
571 |
"implicit"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
572 |
"password"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
573 |
"client_credentials"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
574 |
"refresh_token"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
575 |
"urn:ietf:params:oauth:grant-type:jwt-bearer"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
576 |
"urn:ietf:params:oauth:grant-type:saml2-bearer"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
577 |
}; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
578 |
}; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
579 |
}; |
5240
ff8623e2f9d9
mod_http_oauth2: Reorder client metadata validation schema
Kim Alvefur <zash@zash.se>
parents:
5235
diff
changeset
|
580 |
response_types = { type = "array"; items = { type = "string"; enum = { "code"; "token" } } }; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
581 |
client_name = { type = "string" }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
582 |
client_uri = { type = "string"; format = "uri" }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
583 |
logo_uri = { type = "string"; format = "uri" }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
584 |
scope = { type = "string" }; |
5240
ff8623e2f9d9
mod_http_oauth2: Reorder client metadata validation schema
Kim Alvefur <zash@zash.se>
parents:
5235
diff
changeset
|
585 |
contacts = { type = "array"; items = { type = "string" } }; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
586 |
tos_uri = { type = "string" }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
587 |
policy_uri = { type = "string"; format = "uri" }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
588 |
jwks_uri = { type = "string"; format = "uri" }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
589 |
jwks = { type = "object"; description = "JSON Web Key Set, RFC 7517" }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
590 |
software_id = { type = "string"; format = "uuid" }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
591 |
software_version = { type = "string" }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
592 |
}; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
593 |
} |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
594 |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
595 |
local function handle_register_request(event) |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
596 |
local request = event.request; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
597 |
local client_metadata = json.decode(request.body); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
598 |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
599 |
if not schema.validate(registration_schema, client_metadata) then |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
600 |
return oauth_error("invalid_request", "Failed schema validation."); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
601 |
end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
602 |
|
5243
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
603 |
for _, redirect_uri in ipairs(client_metadata.redirect_uris) do |
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
604 |
local components = url.parse(redirect_uri); |
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
605 |
if not components then |
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
606 |
return oauth_error("invalid_request", "Invalid redirect URI."); |
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
607 |
end |
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
608 |
end |
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
609 |
|
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
610 |
-- Ensure each signed client_id JWT is unique |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
611 |
client_metadata.nonce = uuid.generate(); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
612 |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
613 |
-- Do we want to keep everything? |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
614 |
local client_id = jwt_sign(client_metadata); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
615 |
local client_secret = make_secret(client_id); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
616 |
|
5225
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
617 |
client_metadata.client_id = client_id; |
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
618 |
client_metadata.client_secret = client_secret; |
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
619 |
client_metadata.client_id_issued_at = os.time(); |
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
620 |
client_metadata.client_secret_expires_at = 0; |
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
621 |
|
5206
b81fd0d22c66
mod_http_oauth2: Calculate client secret expiry in registration response
Kim Alvefur <zash@zash.se>
parents:
5205
diff
changeset
|
622 |
if not registration_options.accept_expired then |
5225
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
623 |
client_metadata.client_secret_expires_at = client_metadata.client_id_issued_at + (registration_options.default_ttl or 3600); |
5206
b81fd0d22c66
mod_http_oauth2: Calculate client secret expiry in registration response
Kim Alvefur <zash@zash.se>
parents:
5205
diff
changeset
|
624 |
end |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
625 |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
626 |
return { |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
627 |
status_code = 201; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
628 |
headers = { content_type = "application/json" }; |
5225
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
629 |
body = json.encode(client_metadata); |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
630 |
}; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
631 |
end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
632 |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
633 |
if not registration_key then |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
634 |
module:log("info", "No 'oauth2_registration_key', dynamic client registration disabled") |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
635 |
handle_authorization_request = nil |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
636 |
handle_register_request = nil |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
637 |
end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
638 |
|
5232
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
639 |
local function handle_userinfo_request(event) |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
640 |
local request = event.request; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
641 |
local credentials = get_request_credentials(request); |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
642 |
if not credentials or not credentials.bearer_token then |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
643 |
return 400; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
644 |
end |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
645 |
local token_info = tokens.get_token_info(credentials.bearer_token); |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
646 |
if not token_info then |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
647 |
return 403; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
648 |
end |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
649 |
-- TODO check that they actually have access to the userinfo endpoint, aka |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
650 |
-- the 'openid' scope. Tokens currently contain the JID in plain text so |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
651 |
-- we're not really returning anything they did not know already. |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
652 |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
653 |
local user_info = { |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
654 |
iss = get_issuer(); |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
655 |
sub = url.build({ scheme = "xmpp"; path = token_info.jid }); |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
656 |
-- Additional UserInfo fields could be pulled from vcard4, depending on |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
657 |
-- permissions and scopes granted. |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
658 |
} |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
659 |
return { |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
660 |
status_code = 201; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
661 |
headers = { content_type = "application/json" }; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
662 |
body = json.encode(user_info); |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
663 |
}; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
664 |
end |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
665 |
|
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
666 |
module:depends("http"); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
667 |
module:provides("http", { |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
668 |
route = { |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
669 |
["POST /token"] = handle_token_grant; |
4260
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4241
diff
changeset
|
670 |
["GET /authorize"] = handle_authorization_request; |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
671 |
["POST /authorize"] = handle_authorization_request; |
4374
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4344
diff
changeset
|
672 |
["POST /revoke"] = handle_revocation_request; |
5197
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
673 |
["POST /register"] = handle_register_request; |
5232
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
674 |
["GET /userinfo"] = handle_userinfo_request; |
5212
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
675 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
676 |
-- Optional static content for templates |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
677 |
["GET /style.css"] = templates.css and { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
678 |
headers = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
679 |
["Content-Type"] = "text/css"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
680 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
681 |
body = _render_html(templates.css, module:get_option("oauth2_template_style")); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
682 |
} or nil; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
683 |
["GET /script.js"] = templates.js and { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
684 |
headers = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
685 |
["Content-Type"] = "text/javascript"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
686 |
}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
687 |
body = templates.js; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5211
diff
changeset
|
688 |
} or nil; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
689 |
}; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
690 |
}); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
691 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
692 |
local http_server = require "net.http.server"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
693 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
694 |
module:hook_object_event(http_server, "http-error", function (event) |
4280
ec33b3b1136c
mod_http_oauth2: Fix passing OAuth-specific error details
Kim Alvefur <zash@zash.se>
parents:
4276
diff
changeset
|
695 |
local oauth2_response = event.error and event.error.extra and event.error.extra.oauth2_response; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
696 |
if not oauth2_response then |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
697 |
return; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
698 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
699 |
event.response.headers.content_type = "application/json"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
700 |
event.response.status_code = event.error.code or 400; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
701 |
return json.encode(oauth2_response); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
702 |
end, 5); |
5193
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
703 |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
704 |
-- OIDC Discovery |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
705 |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
706 |
module:provides("http", { |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
707 |
name = "oauth2-discovery"; |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
708 |
default_path = "/.well-known/oauth-authorization-server"; |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
709 |
route = { |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
710 |
["GET"] = { |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
711 |
headers = { content_type = "application/json" }; |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
712 |
body = json.encode { |
5211
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5210
diff
changeset
|
713 |
issuer = get_issuer(); |
5204
afed7d5bd65c
mod_http_oauth2: Advertise endpoints that are enabled
Kim Alvefur <zash@zash.se>
parents:
5203
diff
changeset
|
714 |
authorization_endpoint = handle_authorization_request and module:http_url() .. "/authorize" or nil; |
afed7d5bd65c
mod_http_oauth2: Advertise endpoints that are enabled
Kim Alvefur <zash@zash.se>
parents:
5203
diff
changeset
|
715 |
token_endpoint = handle_token_grant and module:http_url() .. "/token" or nil; |
5193
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
716 |
jwks_uri = nil; -- TODO? |
5232
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
717 |
userinfo_endpoint = handle_register_request and module:http_url() .. "/userinfo" or nil; |
5204
afed7d5bd65c
mod_http_oauth2: Advertise endpoints that are enabled
Kim Alvefur <zash@zash.se>
parents:
5203
diff
changeset
|
718 |
registration_endpoint = handle_register_request and module:http_url() .. "/register" or nil; |
5209
b6f41f0b5f58
mod_http_oauth2: Specify host for which to retrieve list of roles
Kim Alvefur <zash@zash.se>
parents:
5208
diff
changeset
|
719 |
scopes_supported = usermanager.get_all_roles and array(it.keys(usermanager.get_all_roles(module.host))) |
5208
eb8b3a068ecc
mod_http_oauth2: Return list of active roles in discovery
Kim Alvefur <zash@zash.se>
parents:
5207
diff
changeset
|
720 |
or { "prosody:restricted"; "prosody:user"; "prosody:admin"; "prosody:operator" }; |
5207
c60cff787d6a
mod_http_oauth2: Return actually enabled response types in discovery
Kim Alvefur <zash@zash.se>
parents:
5206
diff
changeset
|
721 |
response_types_supported = array(it.keys(response_type_handlers)); |
5196
03aa9baa9ac3
mod_http_oauth2: Add support for 'iss' authz response parameter (RFC 9207)
Matthew Wild <mwild1@gmail.com>
parents:
5195
diff
changeset
|
722 |
authorization_response_iss_parameter_supported = true; |
5193
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
723 |
}; |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
724 |
}; |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
725 |
}; |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
726 |
}); |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
727 |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5192
diff
changeset
|
728 |
module:shared("tokenauth/oauthbearer_config").oidc_discovery_url = module:http_url("oauth2-discovery", "/.well-known/oauth-authorization-server"); |