Mercurial > prosody-modules
annotate mod_http_oauth2/mod_http_oauth2.lua @ 6556:7477e97a9045
mod_firewall: Apply pre-reload state before re-reading config
This change makes load/reload a bit more robust. module.load() runs before
module.restore() and it reads from the config and updates the state (if
needed).
However, after this, module.restore() could run and apply the old state again.
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Sun, 24 May 2026 20:03:20 +0100 |
| parents | 3b69df385f66 |
| children |
| rev | line source |
|---|---|
| 5501 | 1 local usermanager = require "core.usermanager"; |
| 2 local url = require "socket.url"; | |
| 3 local array = require "util.array"; | |
|
4271
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
4 local cache = require "util.cache"; |
| 5501 | 5 local encodings = require "util.encodings"; |
| 6 local errors = require "util.error"; | |
| 7 local hashes = require "util.hashes"; | |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
8 local http = require "util.http"; |
| 5501 | 9 local id = require "util.id"; |
| 10 local it = require "util.iterators"; | |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
11 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
|
12 local json = require "util.json"; |
| 5501 | 13 local schema = require "util.jsonschema"; |
| 14 local jwt = require "util.jwt"; | |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
15 local random = require "util.random"; |
|
5209
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5208
diff
changeset
|
16 local set = require "util.set"; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
17 local st = require "util.stanza"; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
18 |
| 5501 | 19 local base64 = encodings.base64; |
| 20 | |
|
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
21 local function b64url(s) |
|
5392
c0a6f39caf47
mod_http_oauth2: Fix missing base64 part of base64url (Thanks KeyCloak)
Kim Alvefur <zash@zash.se>
parents:
5391
diff
changeset
|
22 return (base64.encode(s):gsub("[+/=]", { ["+"] = "-", ["/"] = "_", ["="] = "" })) |
|
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
23 end |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
24 |
|
5400
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
25 local function tmap(t) |
|
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
26 return function(k) |
|
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
27 return t[k]; |
|
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
28 end |
|
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
29 end |
|
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
30 |
|
6272
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
31 local function array_contains(haystack, needle) |
|
6276
e174e12549e1
mod_http_oauth2: Handle absent array argument in array member check
Kim Alvefur <zash@zash.se>
parents:
6275
diff
changeset
|
32 if not haystack then |
|
e174e12549e1
mod_http_oauth2: Handle absent array argument in array member check
Kim Alvefur <zash@zash.se>
parents:
6275
diff
changeset
|
33 return false |
|
e174e12549e1
mod_http_oauth2: Handle absent array argument in array member check
Kim Alvefur <zash@zash.se>
parents:
6275
diff
changeset
|
34 end |
|
6275
ebcf612da2b1
mod_http_oauth2: Use numeric for loop instead of ipairs
Kim Alvefur <zash@zash.se>
parents:
6274
diff
changeset
|
35 for i = 1, #haystack do |
|
ebcf612da2b1
mod_http_oauth2: Use numeric for loop instead of ipairs
Kim Alvefur <zash@zash.se>
parents:
6274
diff
changeset
|
36 if haystack[i] == needle then |
|
6272
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
37 return true |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
38 end |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
39 end |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
40 return false |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
41 end |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
42 |
|
5956
97375a78d2b5
mod_http_oauth2: Reject URLs with 'userinfo' part (thanks mimi89999)
Kim Alvefur <zash@zash.se>
parents:
5935
diff
changeset
|
43 local function strict_url_parse(urlstr) |
|
97375a78d2b5
mod_http_oauth2: Reject URLs with 'userinfo' part (thanks mimi89999)
Kim Alvefur <zash@zash.se>
parents:
5935
diff
changeset
|
44 local url_parts = url.parse(urlstr); |
|
97375a78d2b5
mod_http_oauth2: Reject URLs with 'userinfo' part (thanks mimi89999)
Kim Alvefur <zash@zash.se>
parents:
5935
diff
changeset
|
45 if not url_parts then return url_parts; end |
|
97375a78d2b5
mod_http_oauth2: Reject URLs with 'userinfo' part (thanks mimi89999)
Kim Alvefur <zash@zash.se>
parents:
5935
diff
changeset
|
46 if url_parts.userinfo then return false; end |
|
5957
e8bf46a7bb27
mod_http_oauth2: Ensure URL ports are integer in correct range
Kim Alvefur <zash@zash.se>
parents:
5956
diff
changeset
|
47 if url_parts.port then |
|
e8bf46a7bb27
mod_http_oauth2: Ensure URL ports are integer in correct range
Kim Alvefur <zash@zash.se>
parents:
5956
diff
changeset
|
48 local port = tonumber(url_parts.port); |
|
e8bf46a7bb27
mod_http_oauth2: Ensure URL ports are integer in correct range
Kim Alvefur <zash@zash.se>
parents:
5956
diff
changeset
|
49 if not port then return false; end |
|
5960
538f468f9a65
mod_http_oauth2: Simplify negation in condition
Kim Alvefur <zash@zash.se>
parents:
5958
diff
changeset
|
50 if port <= 0 or port > 0xffff then return false; end |
|
5957
e8bf46a7bb27
mod_http_oauth2: Ensure URL ports are integer in correct range
Kim Alvefur <zash@zash.se>
parents:
5956
diff
changeset
|
51 if port ~= math.floor(port) then return false; end |
|
e8bf46a7bb27
mod_http_oauth2: Ensure URL ports are integer in correct range
Kim Alvefur <zash@zash.se>
parents:
5956
diff
changeset
|
52 end |
|
5958
5f8a306c8306
mod_http_oauth2: Require a stringprepped host part of URLs
Kim Alvefur <zash@zash.se>
parents:
5957
diff
changeset
|
53 if url_parts.host then |
|
5f8a306c8306
mod_http_oauth2: Require a stringprepped host part of URLs
Kim Alvefur <zash@zash.se>
parents:
5957
diff
changeset
|
54 if encodings.stringprep.nameprep(url_parts.host) ~= url_parts.host then |
|
5f8a306c8306
mod_http_oauth2: Require a stringprepped host part of URLs
Kim Alvefur <zash@zash.se>
parents:
5957
diff
changeset
|
55 return false; |
|
5f8a306c8306
mod_http_oauth2: Require a stringprepped host part of URLs
Kim Alvefur <zash@zash.se>
parents:
5957
diff
changeset
|
56 end |
|
5961
7308ec4aaad1
mod_http_oauth2: Fix error due to mistake in 5f8a306c8306
Kim Alvefur <zash@zash.se>
parents:
5960
diff
changeset
|
57 if not encodings.idna.to_ascii(url_parts.host) then |
|
5958
5f8a306c8306
mod_http_oauth2: Require a stringprepped host part of URLs
Kim Alvefur <zash@zash.se>
parents:
5957
diff
changeset
|
58 return false; |
|
5f8a306c8306
mod_http_oauth2: Require a stringprepped host part of URLs
Kim Alvefur <zash@zash.se>
parents:
5957
diff
changeset
|
59 end |
|
5f8a306c8306
mod_http_oauth2: Require a stringprepped host part of URLs
Kim Alvefur <zash@zash.se>
parents:
5957
diff
changeset
|
60 end |
|
5956
97375a78d2b5
mod_http_oauth2: Reject URLs with 'userinfo' part (thanks mimi89999)
Kim Alvefur <zash@zash.se>
parents:
5935
diff
changeset
|
61 return url_parts; |
|
97375a78d2b5
mod_http_oauth2: Reject URLs with 'userinfo' part (thanks mimi89999)
Kim Alvefur <zash@zash.se>
parents:
5935
diff
changeset
|
62 end |
|
97375a78d2b5
mod_http_oauth2: Reject URLs with 'userinfo' part (thanks mimi89999)
Kim Alvefur <zash@zash.se>
parents:
5935
diff
changeset
|
63 |
|
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
64 local function strict_formdecode(query) |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
65 if not query then |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
66 return nil; |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
67 end |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
68 local params = http.formdecode(query); |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
69 if type(params) ~= "table" then |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
70 return nil, "no-pairs"; |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
71 end |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
72 local dups = {}; |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
73 for _, pair in ipairs(params) do |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
74 if dups[pair.name] then |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
75 return nil, "duplicate"; |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
76 end |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
77 dups[pair.name] = true; |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
78 end |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
79 return params; |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
80 end |
|
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
81 |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
82 local function read_file(base_path, fn, required) |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
83 local f, err = io.open(base_path .. "/" .. fn); |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
84 if not f then |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
85 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:
5207
diff
changeset
|
86 if required then |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
87 return error("Failed to load templates"); |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
88 end |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
89 return nil; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
90 end |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
91 local data = assert(f:read("*a")); |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
92 assert(f:close()); |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
93 return data; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
94 end |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
95 |
|
5554
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
96 local allowed_locales = module:get_option_array("allowed_oauth2_locales", {}); |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
97 -- TODO Allow translations or per-locale templates somehow. |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
98 |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
99 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:
5207
diff
changeset
|
100 local templates = { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
101 login = read_file(template_path, "login.html", true); |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
102 consent = read_file(template_path, "consent.html", true); |
|
5495
7998b49d6512
mod_http_oauth2: Create proper template for OOB code delivery
Kim Alvefur <zash@zash.se>
parents:
5480
diff
changeset
|
103 oob = read_file(template_path, "oob.html", true); |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
104 device = read_file(template_path, "device.html", true); |
|
6408
7fe484e7b574
mod_http_oauth2: Make error template optional
Kim Alvefur <zash@zash.se>
parents:
6296
diff
changeset
|
105 error = read_file(template_path, "error.html"); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
106 css = read_file(template_path, "style.css"); |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
107 js = read_file(template_path, "script.js"); |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
108 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
109 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
110 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:
5207
diff
changeset
|
111 |
|
5547
d4a2997deae9
mod_http_oauth2: Make CSP configurable
Kim Alvefur <zash@zash.se>
parents:
5544
diff
changeset
|
112 local security_policy = module:get_option_string("oauth2_security_policy", "default-src 'self'"); |
|
d4a2997deae9
mod_http_oauth2: Make CSP configurable
Kim Alvefur <zash@zash.se>
parents:
5544
diff
changeset
|
113 |
|
5544
cb141088eff0
mod_http_oauth2: Remove underscore prefix
Kim Alvefur <zash@zash.se>
parents:
5526
diff
changeset
|
114 local render_html = require"util.interpolation".new("%b{}", st.xml_escape); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
115 local function render_page(template, data, sensitive) |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
116 data = data or {}; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
117 data.site_name = site_name; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
118 local resp = { |
|
5470
40c990159006
mod_http_oauth2: Use error status code when rendering error page
Kim Alvefur <zash@zash.se>
parents:
5469
diff
changeset
|
119 status_code = data.error and data.error.code or 200; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
120 headers = { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
121 ["Content-Type"] = "text/html; charset=utf-8"; |
|
5547
d4a2997deae9
mod_http_oauth2: Make CSP configurable
Kim Alvefur <zash@zash.se>
parents:
5544
diff
changeset
|
122 ["Content-Security-Policy"] = security_policy; |
|
5479
30e2722c9fa3
mod_http_oauth2: Disable Referrer via header
Kim Alvefur <zash@zash.se>
parents:
5478
diff
changeset
|
123 ["Referrer-Policy"] = "no-referrer"; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
124 ["X-Frame-Options"] = "DENY"; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
125 ["Cache-Control"] = (sensitive and "no-store" or "no-cache")..", private"; |
|
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
126 ["Pragma"] = "no-cache"; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
127 }; |
|
5544
cb141088eff0
mod_http_oauth2: Remove underscore prefix
Kim Alvefur <zash@zash.se>
parents:
5526
diff
changeset
|
128 body = render_html(template, data); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
129 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
130 return resp; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
131 end |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
132 |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
133 local authorization_server_metadata = nil; |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
134 |
|
3915
80dffbbd056b
mod_rest, mod_http_oauth2: Switch from mod_authtokens to mod_tokenauth per Prosody bf81523e2ff4
Matthew Wild <mwild1@gmail.com>
parents:
3908
diff
changeset
|
135 local tokens = module:depends("tokenauth"); |
|
3908
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3903
diff
changeset
|
136 |
|
5617
d8622797e315
mod_http_oauth2: Shorten default token validity periods
Kim Alvefur <zash@zash.se>
parents:
5616
diff
changeset
|
137 local default_access_ttl = module:get_option_number("oauth2_access_token_ttl", 3600); |
|
5619
81042c2a235a
mod_http_oauth2: Don't use new time period API just yet
Kim Alvefur <zash@zash.se>
parents:
5618
diff
changeset
|
138 local default_refresh_ttl = module:get_option_number("oauth2_refresh_token_ttl", 604800); |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
139 |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
140 -- 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:
5192
diff
changeset
|
141 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:
5192
diff
changeset
|
142 local registration_algo = module:get_option_string("oauth2_registration_algorithm", "HS256"); |
|
5416
2393dbae51ed
mod_http_oauth2: Add option for specifying TTL of registered clients
Kim Alvefur <zash@zash.se>
parents:
5409
diff
changeset
|
143 local registration_ttl = module:get_option("oauth2_registration_ttl", nil); |
|
2393dbae51ed
mod_http_oauth2: Add option for specifying TTL of registered clients
Kim Alvefur <zash@zash.se>
parents:
5409
diff
changeset
|
144 local registration_options = module:get_option("oauth2_registration_options", |
|
2393dbae51ed
mod_http_oauth2: Add option for specifying TTL of registered clients
Kim Alvefur <zash@zash.se>
parents:
5409
diff
changeset
|
145 { default_ttl = registration_ttl; accept_expired = not registration_ttl }); |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
146 |
|
5716
426c42c11f89
mod_http_oauth2: Make defaults more secure
Kim Alvefur <zash@zash.se>
parents:
5715
diff
changeset
|
147 local pkce_required = module:get_option_boolean("oauth2_require_code_challenge", true); |
|
426c42c11f89
mod_http_oauth2: Make defaults more secure
Kim Alvefur <zash@zash.se>
parents:
5715
diff
changeset
|
148 local respect_prompt = module:get_option_boolean("oauth2_respect_oidc_prompt", false); |
|
6207
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
149 local expect_username_jid = module:get_option_boolean("oauth2_expect_username_jid", false); |
|
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
150 |
|
5199
f48628dc83f1
mod_http_oauth2: Separate client_secret verification key from JWT key
Kim Alvefur <zash@zash.se>
parents:
5198
diff
changeset
|
151 local verification_key; |
|
5459
260a859be86a
mod_http_oauth2: Rename variables to improve clarity
Kim Alvefur <zash@zash.se>
parents:
5458
diff
changeset
|
152 local sign_client, verify_client; |
|
5196
6b63af56c8ac
mod_http_oauth2: Remove error message
Kim Alvefur <zash@zash.se>
parents:
5195
diff
changeset
|
153 if registration_key then |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
154 -- Tie it to the host if global |
|
5199
f48628dc83f1
mod_http_oauth2: Separate client_secret verification key from JWT key
Kim Alvefur <zash@zash.se>
parents:
5198
diff
changeset
|
155 verification_key = hashes.hmac_sha256(registration_key, module.host); |
|
5459
260a859be86a
mod_http_oauth2: Rename variables to improve clarity
Kim Alvefur <zash@zash.se>
parents:
5458
diff
changeset
|
156 sign_client, verify_client = jwt.init(registration_algo, registration_key, registration_key, registration_options); |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
157 end |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
158 |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
159 local new_device_token, verify_device_token = jwt.init("HS256", random.bytes(32), nil, { default_ttl = 600 }); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
160 |
|
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
161 -- verify and prepare client structure |
|
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
162 local function check_client(client_id) |
|
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
163 if not verify_client then |
|
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
164 return nil, "client-registration-not-enabled"; |
|
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
165 end |
|
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
166 |
|
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
167 local ok, client = verify_client(client_id); |
|
5511
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
168 if not ok then |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
169 return ok, client; |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
170 end |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
171 |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
172 client.client_hash = b64url(hashes.sha256(client_id)); |
|
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
173 return client; |
|
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
174 end |
|
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
175 |
|
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
176 local purpose_map = { ["oauth2-refresh"] = "refresh_token"; ["oauth"] = "access_token" }; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
177 |
|
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
178 -- scope : string | array | set |
|
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
179 -- |
|
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
180 -- at each step, allow the same or a subset of scopes |
|
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
181 -- (all ( client ( grant ( token ) ) )) |
|
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
182 -- preserve order since it determines role if more than one granted |
|
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
183 |
|
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
184 -- string -> array |
|
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
185 local function parse_scopes(scope_string) |
|
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
186 return array(scope_string:gmatch("%S+")); |
|
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
187 end |
|
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
188 |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
189 local openid_claims = set.new(); |
|
6272
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
190 |
|
6291
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
191 module:add_item("openid-claim", { claim = "openid"; title = "OpenID"; |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
192 description = "Tells the application your JID and when you authenticated."; }); |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
193 |
|
6272
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
194 -- https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
195 -- The "offline_access" scope grants access to refresh tokens |
|
6291
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
196 module:add_item("openid-claim", { claim = "offline_access"; title = "Offline Access"; |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
197 description = "Application may renew access without interaction."; }); |
|
6272
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
198 |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
199 module:handle_items("openid-claim", function(event) |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
200 authorization_server_metadata = nil; |
|
6291
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
201 openid_claims:add(event.item.claim or event.item); |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
202 end, function() |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
203 authorization_server_metadata = nil; |
|
6291
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
204 openid_claims = set.new(array.new(module:get_host_items("openid-claim")):map(function(item) |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
205 return item.claim or item; |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
206 end)); |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
207 end, true); |
|
5337
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
208 |
|
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
209 -- array -> array, array, array |
|
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
210 local function split_scopes(scope_list) |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
211 local claims, roles, unknown = array(), array(), array(); |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
212 local all_roles = usermanager.get_all_roles(module.host); |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
213 for _, scope in ipairs(scope_list) do |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
214 if openid_claims:contains(scope) then |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
215 claims:push(scope); |
|
5467
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
216 elseif scope == "xmpp" or all_roles[scope] then |
|
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
217 roles:push(scope); |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
218 else |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
219 unknown:push(scope); |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
220 end |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
221 end |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
222 return claims, roles, unknown; |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
223 end |
|
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
224 |
|
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
225 local function can_assume_role(username, requested_role) |
|
5467
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
226 return requested_role == "xmpp" or usermanager.user_can_assume_role(username, module.host, requested_role); |
|
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
227 end |
|
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
228 |
|
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
229 -- function (string) : function(string) : boolean |
|
5427
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
230 local function role_assumable_by(username) |
|
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
231 return function(role) |
|
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
232 return can_assume_role(username, role); |
|
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
233 end |
|
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
234 end |
|
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
235 |
|
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
236 -- string, array --> array |
|
5426
f75d95f27da7
mod_http_oauth2: Add function for filtering roles
Kim Alvefur <zash@zash.se>
parents:
5425
diff
changeset
|
237 local function user_assumable_roles(username, requested_roles) |
|
5427
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
238 return array.filter(requested_roles, role_assumable_by(username)); |
|
5426
f75d95f27da7
mod_http_oauth2: Add function for filtering roles
Kim Alvefur <zash@zash.se>
parents:
5425
diff
changeset
|
239 end |
|
f75d95f27da7
mod_http_oauth2: Add function for filtering roles
Kim Alvefur <zash@zash.se>
parents:
5425
diff
changeset
|
240 |
|
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
241 -- string, string|nil --> string, string |
|
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
242 local function filter_scopes(username, requested_scope_string) |
|
5428
07e166b34c4c
mod_http_oauth2: Simplify code with the power of first class functions
Kim Alvefur <zash@zash.se>
parents:
5427
diff
changeset
|
243 local requested_scopes, requested_roles = split_scopes(parse_scopes(requested_scope_string or "")); |
|
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
244 |
|
5428
07e166b34c4c
mod_http_oauth2: Simplify code with the power of first class functions
Kim Alvefur <zash@zash.se>
parents:
5427
diff
changeset
|
245 local granted_roles = user_assumable_roles(username, requested_roles); |
|
07e166b34c4c
mod_http_oauth2: Simplify code with the power of first class functions
Kim Alvefur <zash@zash.se>
parents:
5427
diff
changeset
|
246 local granted_scopes = requested_scopes + granted_roles; |
|
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
247 |
|
5428
07e166b34c4c
mod_http_oauth2: Simplify code with the power of first class functions
Kim Alvefur <zash@zash.se>
parents:
5427
diff
changeset
|
248 local selected_role = granted_roles[1]; |
|
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
249 |
|
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
250 return granted_scopes:concat(" "), selected_role; |
|
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
251 end |
|
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
252 |
|
5213
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5210
diff
changeset
|
253 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:
5210
diff
changeset
|
254 return os.difftime(code.expires, os.time()); |
|
4669
d3434fd151b5
mod_http_oauth2: Optimize cleanup timer
Kim Alvefur <zash@zash.se>
parents:
4370
diff
changeset
|
255 end |
|
d3434fd151b5
mod_http_oauth2: Optimize cleanup timer
Kim Alvefur <zash@zash.se>
parents:
4370
diff
changeset
|
256 |
|
5213
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5210
diff
changeset
|
257 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:
5210
diff
changeset
|
258 return code_expires_in(code) < 0; |
|
4269
143515d0b212
mod_http_oauth2: Factor out authorization code validity decision
Kim Alvefur <zash@zash.se>
parents:
4265
diff
changeset
|
259 end |
|
143515d0b212
mod_http_oauth2: Factor out authorization code validity decision
Kim Alvefur <zash@zash.se>
parents:
4265
diff
changeset
|
260 |
|
5751
d563a6b0dfb7
mod_http_oauth2: Comment on authorization code storage
Kim Alvefur <zash@zash.se>
parents:
5716
diff
changeset
|
261 -- LRU cache for short-term storage of authorization codes and device codes |
|
4271
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
262 local codes = cache.new(10000, function (_, code) |
|
5751
d563a6b0dfb7
mod_http_oauth2: Comment on authorization code storage
Kim Alvefur <zash@zash.se>
parents:
5716
diff
changeset
|
263 -- If the cache is full and the oldest item hasn't expired yet then we |
|
d563a6b0dfb7
mod_http_oauth2: Comment on authorization code storage
Kim Alvefur <zash@zash.se>
parents:
5716
diff
changeset
|
264 -- might be under some kind of DoS attack, so might as well reject further |
|
d563a6b0dfb7
mod_http_oauth2: Comment on authorization code storage
Kim Alvefur <zash@zash.se>
parents:
5716
diff
changeset
|
265 -- entries for a bit. |
|
4271
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
266 return code_expired(code) |
|
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
267 end); |
|
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
268 |
|
5618
869c01d91aea
mod_http_oauth2: Clean cache less frequently
Kim Alvefur <zash@zash.se>
parents:
5617
diff
changeset
|
269 -- Clear out unredeemed codes so they don't linger in memory. |
|
869c01d91aea
mod_http_oauth2: Clean cache less frequently
Kim Alvefur <zash@zash.se>
parents:
5617
diff
changeset
|
270 module:daily("Clear expired authorization codes", function() |
|
5751
d563a6b0dfb7
mod_http_oauth2: Comment on authorization code storage
Kim Alvefur <zash@zash.se>
parents:
5716
diff
changeset
|
271 -- The tail should be the least recently touched item, and most likely to |
|
d563a6b0dfb7
mod_http_oauth2: Comment on authorization code storage
Kim Alvefur <zash@zash.se>
parents:
5716
diff
changeset
|
272 -- have expired already, so check and remove that one until encountering |
|
d563a6b0dfb7
mod_http_oauth2: Comment on authorization code storage
Kim Alvefur <zash@zash.se>
parents:
5716
diff
changeset
|
273 -- one that has not expired. |
|
4272
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
274 local k, code = codes:tail(); |
|
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
275 while code and code_expired(code) do |
|
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
276 codes:set(k, nil); |
|
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
277 k, code = codes:tail(); |
|
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
278 end |
|
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
279 end) |
|
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
280 |
|
5207
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5206
diff
changeset
|
281 local function get_issuer() |
|
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5206
diff
changeset
|
282 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:
5206
diff
changeset
|
283 end |
|
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5206
diff
changeset
|
284 |
|
5458
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
285 -- Non-standard special redirect URI that has the AS show the authorization |
|
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
286 -- code to the user for them to copy-paste into the client, which can then |
|
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
287 -- continue as if it received it via redirect. |
|
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
288 local oob_uri = "urn:ietf:wg:oauth:2.0:oob"; |
|
6279
5dc4ec836ce2
mod_http_oauth2: Comment on origin of a constant URI
Kim Alvefur <zash@zash.se>
parents:
6278
diff
changeset
|
289 |
|
5dc4ec836ce2
mod_http_oauth2: Comment on origin of a constant URI
Kim Alvefur <zash@zash.se>
parents:
6278
diff
changeset
|
290 -- RFC 8628 OAuth 2.0 Device Authorization Grant |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
291 local device_uri = "urn:ietf:params:oauth:grant-type:device_code"; |
|
5458
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
292 |
|
5209
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5208
diff
changeset
|
293 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:
5208
diff
changeset
|
294 |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
295 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
|
296 return errors.new({ |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
297 type = "modify"; |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
298 condition = "bad-request"; |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
299 code = err_name == "invalid_client" and 401 or 400; |
|
5798
fdf3056021dc
mod_http_oauth2: Tweak fallback error text
Kim Alvefur <zash@zash.se>
parents:
5797
diff
changeset
|
300 text = err_desc or err_name:gsub("^.", string.upper):gsub("_", " "); |
|
4276
ec33b3b1136c
mod_http_oauth2: Fix passing OAuth-specific error details
Kim Alvefur <zash@zash.se>
parents:
4272
diff
changeset
|
301 extra = { oauth2_response = { error = err_name, error_description = err_desc } }; |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
302 }); |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
303 end |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
304 |
|
5248
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
305 -- client_id / client_metadata are pretty large, filter out a subset of |
|
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
306 -- properties that are deemed useful e.g. in case tokens issued to a certain |
|
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
307 -- client needs to be revoked |
|
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
308 local function client_subset(client) |
|
5511
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
309 return { |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
310 name = client.client_name; |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
311 uri = client.client_uri; |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
312 id = client.software_id; |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
313 version = client.software_version; |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
314 hash = client.client_hash; |
|
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
315 }; |
|
5248
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
316 end |
|
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
317 |
|
6278
4f9b42c53d0f
mod_http_oauth2: Check grant type before issuing refresh token
Kim Alvefur <zash@zash.se>
parents:
6277
diff
changeset
|
318 local function may_issue_refresh_token(client, scope_string) |
|
4f9b42c53d0f
mod_http_oauth2: Check grant type before issuing refresh token
Kim Alvefur <zash@zash.se>
parents:
6277
diff
changeset
|
319 return array_contains(client.grant_types, "refresh_token") and array_contains(parse_scopes(scope_string), "offline_access"); |
|
4f9b42c53d0f
mod_http_oauth2: Check grant type before issuing refresh token
Kim Alvefur <zash@zash.se>
parents:
6277
diff
changeset
|
320 end |
|
4f9b42c53d0f
mod_http_oauth2: Check grant type before issuing refresh token
Kim Alvefur <zash@zash.se>
parents:
6277
diff
changeset
|
321 |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
322 local function new_access_token(token_jid, role, scope_string, client, id_token, refresh_token_info) |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
323 local token_data = { oauth2_scopes = scope_string, oauth2_client = nil }; |
|
5248
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
324 if client then |
|
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
325 token_data.oauth2_client = client_subset(client); |
|
5248
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
326 end |
|
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
327 if next(token_data) == nil then |
|
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
328 token_data = nil; |
|
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
329 end |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
330 |
|
5280
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
331 local grant = refresh_token_info and refresh_token_info.grant; |
|
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
332 if not grant then |
|
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
333 -- No existing grant, create one |
|
5646
d67980d9e12d
mod_http_oauth2: Apply refresh token ttl to refresh token instead of grant
Kim Alvefur <zash@zash.se>
parents:
5643
diff
changeset
|
334 grant = tokens.create_grant(token_jid, token_jid, nil, token_data); |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
335 end |
|
5280
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
336 |
|
5616
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
337 if refresh_token_info then |
|
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
338 -- out with the old refresh tokens |
|
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
339 local ok, err = tokens.revoke_token(refresh_token_info.token); |
|
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
340 if not ok then |
|
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
341 module:log("error", "Could not revoke refresh token: %s", err); |
|
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
342 return 500; |
|
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
343 end |
|
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
344 end |
|
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
345 -- in with the new refresh token |
|
6272
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
346 local refresh_token; |
|
6278
4f9b42c53d0f
mod_http_oauth2: Check grant type before issuing refresh token
Kim Alvefur <zash@zash.se>
parents:
6277
diff
changeset
|
347 if refresh_token_info ~= false and may_issue_refresh_token(client, scope_string) then |
|
6272
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
348 refresh_token = tokens.create_token(token_jid, grant.id, nil, default_refresh_ttl, "oauth2-refresh"); |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
349 end |
|
5616
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
350 |
|
5467
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
351 if role == "xmpp" then |
|
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
352 -- Special scope meaning the users default role. |
|
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
353 local user_default_role = usermanager.get_user_role(jid.node(token_jid), module.host); |
|
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
354 role = user_default_role and user_default_role.name; |
|
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
355 end |
|
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
356 |
|
5451
6705f2a09702
mod_http_oauth2: Reference grant by id instead of value
Kim Alvefur <zash@zash.se>
parents:
5450
diff
changeset
|
357 local access_token, access_token_info = tokens.create_token(token_jid, grant.id, role, default_access_ttl, "oauth2"); |
|
5280
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
358 |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
359 local expires_at = access_token_info.expires; |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
360 return { |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
361 token_type = "bearer"; |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
362 access_token = access_token; |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
363 expires_in = expires_at and (expires_at - os.time()) or nil; |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
364 scope = scope_string; |
|
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
365 id_token = id_token; |
|
5280
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
366 refresh_token = refresh_token or nil; |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
367 }; |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
368 end |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
369 |
|
5461
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
370 local function normalize_loopback(uri) |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
371 local u = url.parse(uri); |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
372 if u.scheme == "http" and loopbacks:contains(u.host) then |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
373 u.authority = nil; |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
374 u.host = "::1"; |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
375 u.port = nil; |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
376 return url.build(u); |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
377 end |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
378 -- else, not a valid loopback uri |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
379 end |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
380 |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
381 local function get_redirect_uri(client, query_redirect_uri) -- record client, string : string |
|
6280
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
382 if query_redirect_uri == device_uri and client.grant_types then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
383 if array_contains(client.grant_types, device_uri) then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
384 return query_redirect_uri; |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
385 end |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
386 -- Tried to use device authorization flow without registering it. |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
387 return; |
|
6282
578fa5d97daa
mod_http_oauth2: Avoid tripping on redirect URIs when omitted
Kim Alvefur <zash@zash.se>
parents:
6281
diff
changeset
|
388 elseif not client.redirect_uris then |
|
578fa5d97daa
mod_http_oauth2: Avoid tripping on redirect URIs when omitted
Kim Alvefur <zash@zash.se>
parents:
6281
diff
changeset
|
389 return; |
|
578fa5d97daa
mod_http_oauth2: Avoid tripping on redirect URIs when omitted
Kim Alvefur <zash@zash.se>
parents:
6281
diff
changeset
|
390 elseif not query_redirect_uri then |
|
5219
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
391 if #client.redirect_uris ~= 1 then |
|
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
392 -- 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:
5218
diff
changeset
|
393 return; |
|
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
394 end |
|
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
395 -- 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:
5218
diff
changeset
|
396 return client.redirect_uris[1]; |
|
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
397 end |
|
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
398 -- Verify the client-provided URI matches one previously registered |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
399 for _, redirect_uri in ipairs(client.redirect_uris) do |
|
5219
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
400 if query_redirect_uri == redirect_uri then |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
401 return redirect_uri |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
402 end |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
403 end |
|
5461
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
404 -- The authorization server MUST allow any port to be specified at the time |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
405 -- of the request for loopback IP redirect URIs, to accommodate clients that |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
406 -- obtain an available ephemeral port from the operating system at the time |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
407 -- of the request. |
|
5460
c0d62c1b4424
mod_http_oauth2: Add FIXME about loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5459
diff
changeset
|
408 -- https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-08.html#section-8.4.2 |
|
5461
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
409 local loopback_redirect_uri = normalize_loopback(query_redirect_uri); |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
410 if loopback_redirect_uri then |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
411 for _, redirect_uri in ipairs(client.redirect_uris) do |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
412 if loopback_redirect_uri == normalize_loopback(redirect_uri) then |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
413 return query_redirect_uri; |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
414 end |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
415 end |
|
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
416 end |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
417 end |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
418 |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
419 local grant_type_handlers = {}; |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
420 local response_type_handlers = {}; |
|
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
421 local verifier_transforms = {}; |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
422 |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
423 function grant_type_handlers.implicit() |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
424 -- Placeholder to make discovery work correctly. |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
425 -- Access tokens are delivered via redirect when using the implict flow, not |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
426 -- via the token endpoint, so how did you get here? |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
427 return oauth_error("invalid_request"); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
428 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
429 |
|
6204
4f0ed0e3ad5a
mod_http_oauth2: Require client authentication for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6179
diff
changeset
|
430 local function make_client_secret(client_id) --> client_secret |
|
6233
9014c95c4549
mod_http_oauth2: Fix indentation
Kim Alvefur <zash@zash.se>
parents:
6232
diff
changeset
|
431 return hashes.hmac_sha256(verification_key, client_id, true); |
|
6204
4f0ed0e3ad5a
mod_http_oauth2: Require client authentication for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6179
diff
changeset
|
432 end |
|
4f0ed0e3ad5a
mod_http_oauth2: Require client authentication for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6179
diff
changeset
|
433 |
|
4f0ed0e3ad5a
mod_http_oauth2: Require client authentication for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6179
diff
changeset
|
434 local function verify_client_secret(client_id, client_secret) |
|
6233
9014c95c4549
mod_http_oauth2: Fix indentation
Kim Alvefur <zash@zash.se>
parents:
6232
diff
changeset
|
435 return hashes.equals(make_client_secret(client_id), client_secret); |
|
6204
4f0ed0e3ad5a
mod_http_oauth2: Require client authentication for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6179
diff
changeset
|
436 end |
|
4f0ed0e3ad5a
mod_http_oauth2: Require client authentication for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6179
diff
changeset
|
437 |
|
6232
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
438 function grant_type_handlers.password(params, client) |
|
6207
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
439 local request_username |
|
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
440 |
|
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
441 if expect_username_jid then |
|
6244
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
442 local request_jid = params.username; |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
443 if not request_jid then |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
444 return oauth_error("invalid_request", "missing 'username' (JID)"); |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
445 end |
|
6234
b63202d66238
mod_http_oauth2: Remove unused variable [luacheck]
Kim Alvefur <zash@zash.se>
parents:
6233
diff
changeset
|
446 local _request_username, request_host = jid.prepped_split(request_jid); |
|
6207
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
447 |
|
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
448 if not (_request_username and request_host) or request_host ~= module.host then |
|
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
449 return oauth_error("invalid_request", "invalid JID"); |
|
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
450 end |
|
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
451 |
|
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
452 request_username = _request_username |
|
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
453 else |
|
6244
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
454 request_username = params.username; |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
455 if not request_username then |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
456 return oauth_error("invalid_request", "missing 'username'"); |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
457 end |
|
6515
ff55e93be449
mod_http_oauth2: Normalize username in password grant
Kim Alvefur <zash@zash.se>
parents:
6408
diff
changeset
|
458 request_username = encodings.stringprep.nodeprep(request_username); |
|
ff55e93be449
mod_http_oauth2: Normalize username in password grant
Kim Alvefur <zash@zash.se>
parents:
6408
diff
changeset
|
459 if not request_username then |
|
ff55e93be449
mod_http_oauth2: Normalize username in password grant
Kim Alvefur <zash@zash.se>
parents:
6408
diff
changeset
|
460 return oauth_error("invalid_request", "invalid 'username'"); |
|
ff55e93be449
mod_http_oauth2: Normalize username in password grant
Kim Alvefur <zash@zash.se>
parents:
6408
diff
changeset
|
461 end |
|
6207
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
462 end |
|
ab14e7ecb82f
mod_http_oauth2: Allow JIDs as username for password grant
magicfelix <felix@felix-zauberer.de>
parents:
6206
diff
changeset
|
463 |
|
6244
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
464 local request_password = params.password; |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
465 if not request_password then |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
466 return oauth_error("invalid_request", "missing 'password'"); |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
467 end |
|
6516
3b69df385f66
mod_http_oauth2: Normalize the password in the password grant
Kim Alvefur <zash@zash.se>
parents:
6515
diff
changeset
|
468 request_password = encodings.stringprep.saslprep(request_password); |
|
3b69df385f66
mod_http_oauth2: Normalize the password in the password grant
Kim Alvefur <zash@zash.se>
parents:
6515
diff
changeset
|
469 if not request_password then |
|
3b69df385f66
mod_http_oauth2: Normalize the password in the password grant
Kim Alvefur <zash@zash.se>
parents:
6515
diff
changeset
|
470 return oauth_error("invalid_request", "invalid 'password'"); |
|
3b69df385f66
mod_http_oauth2: Normalize the password in the password grant
Kim Alvefur <zash@zash.se>
parents:
6515
diff
changeset
|
471 end |
|
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
472 |
|
6245
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
473 local auth_event = { |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
474 session = { |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
475 type = "oauth2"; |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
476 ip = "::"; |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
477 username = request_username; |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
478 host = module.host; |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
479 log = module._log; |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
480 sasl_handler = { username = request_username; selected = "x-oauth2-password" }; |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
481 client_id = client.client_name; |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
482 }; |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
483 }; |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
484 |
|
6205
c1b94dd6e53b
mod_http_oauth2: Change password grant to take username instead of JID [BC]
Kim Alvefur <zash@zash.se>
parents:
6204
diff
changeset
|
485 if not usermanager.test_password(request_username, module.host, request_password) then |
|
6245
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
486 module:fire_event("authentication-failure", auth_event); |
|
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
487 return oauth_error("invalid_grant", "incorrect credentials"); |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
488 end |
|
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
489 |
|
6245
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
490 module:fire_event("authentication-success", auth_event); |
|
7e4238d2989c
mod_http_oauth2: Fire authentication events in password grant
Kim Alvefur <zash@zash.se>
parents:
6244
diff
changeset
|
491 |
|
6205
c1b94dd6e53b
mod_http_oauth2: Change password grant to take username instead of JID [BC]
Kim Alvefur <zash@zash.se>
parents:
6204
diff
changeset
|
492 local granted_jid = jid.join(request_username, module.host); |
|
5256
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
493 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
|
6206
a931a95e363e
mod_http_oauth2: Pass client to token to enable introspection
magicfelix <felix@felix-zauberer.de>
parents:
6205
diff
changeset
|
494 return json.encode(new_access_token(granted_jid, granted_role, granted_scopes, client)); |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
495 end |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
496 |
|
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
497 function response_type_handlers.code(client, params, granted_jid, id_token) |
|
5191
f5a58cbe86e4
mod_http_oauth2: Derive scope from correct user details
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
498 local request_username, request_host = jid.split(granted_jid); |
|
5256
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
499 if not request_host or request_host ~= module.host then |
|
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
500 return oauth_error("invalid_request", "invalid JID"); |
|
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
501 end |
|
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
502 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
|
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
503 |
|
5796
93d6e9026c1b
mod_http_oauth2: Do not enforce PKCE on Device and OOB flows
Kim Alvefur <zash@zash.se>
parents:
5771
diff
changeset
|
504 local redirect_uri = get_redirect_uri(client, params.redirect_uri); |
|
93d6e9026c1b
mod_http_oauth2: Do not enforce PKCE on Device and OOB flows
Kim Alvefur <zash@zash.se>
parents:
5771
diff
changeset
|
505 |
|
93d6e9026c1b
mod_http_oauth2: Do not enforce PKCE on Device and OOB flows
Kim Alvefur <zash@zash.se>
parents:
5771
diff
changeset
|
506 if pkce_required and not params.code_challenge and redirect_uri ~= device_uri and redirect_uri ~= oob_uri then |
|
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
507 return oauth_error("invalid_request", "PKCE required"); |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
508 end |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
509 |
|
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
510 local prefix = "authorization_code:"; |
|
5243
d5dc8edb2695
mod_http_oauth2: Use more compact IDs
Kim Alvefur <zash@zash.se>
parents:
5242
diff
changeset
|
511 local code = id.medium(); |
|
5796
93d6e9026c1b
mod_http_oauth2: Do not enforce PKCE on Device and OOB flows
Kim Alvefur <zash@zash.se>
parents:
5771
diff
changeset
|
512 if redirect_uri == device_uri then |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
513 local is_device, device_state = verify_device_token(params.state); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
514 if is_device then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
515 -- reconstruct the device_code |
|
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
516 prefix = "device_code:"; |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
517 code = b64url(hashes.hmac_sha256(verification_key, device_state.user_code)); |
|
5628
9aace51c3637
mod_http_oauth2: Bail on invalid or expired device flow state token
Kim Alvefur <zash@zash.se>
parents:
5626
diff
changeset
|
518 else |
|
9aace51c3637
mod_http_oauth2: Bail on invalid or expired device flow state token
Kim Alvefur <zash@zash.se>
parents:
5626
diff
changeset
|
519 return oauth_error("invalid_request"); |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
520 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
521 end |
|
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
522 local ok = codes:set(prefix.. params.client_id .. "#" .. code, { |
|
5213
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5210
diff
changeset
|
523 expires = os.time() + 600; |
|
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
524 granted_jid = granted_jid; |
|
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
525 granted_scopes = granted_scopes; |
|
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
526 granted_role = granted_role; |
|
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
527 challenge = params.code_challenge; |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
528 challenge_method = params.code_challenge_method; |
|
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
529 id_token = id_token; |
|
4670
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4669
diff
changeset
|
530 }); |
|
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4669
diff
changeset
|
531 if not ok then |
|
5476
575f52b15f5a
mod_http_oauth2: Return OAuth error for authz code store error
Kim Alvefur <zash@zash.se>
parents:
5475
diff
changeset
|
532 return oauth_error("temporarily_unavailable"); |
|
4670
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4669
diff
changeset
|
533 end |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
534 |
|
5458
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
535 if redirect_uri == oob_uri then |
|
5495
7998b49d6512
mod_http_oauth2: Create proper template for OOB code delivery
Kim Alvefur <zash@zash.se>
parents:
5480
diff
changeset
|
536 return render_page(templates.oob, { client = client; authorization_code = code }, true); |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
537 elseif redirect_uri == device_uri then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
538 return render_page(templates.device, { client = client }, true); |
|
5219
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
539 elseif not redirect_uri then |
|
5462
f6d8830a83fe
mod_http_oauth2: Return proper OAuth error for invalid redirect URI
Kim Alvefur <zash@zash.se>
parents:
5461
diff
changeset
|
540 return oauth_error("invalid_redirect_uri"); |
|
5188
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5187
diff
changeset
|
541 end |
|
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5187
diff
changeset
|
542 |
|
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5187
diff
changeset
|
543 local redirect = url.parse(redirect_uri); |
|
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5187
diff
changeset
|
544 |
|
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
545 local query = strict_formdecode(redirect.query); |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
546 if type(query) ~= "table" then query = {}; end |
|
5192
03aa9baa9ac3
mod_http_oauth2: Add support for 'iss' authz response parameter (RFC 9207)
Matthew Wild <mwild1@gmail.com>
parents:
5191
diff
changeset
|
547 table.insert(query, { name = "code", value = code }); |
|
5207
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5206
diff
changeset
|
548 table.insert(query, { name = "iss", value = get_issuer() }); |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
549 if params.state then |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
550 table.insert(query, { name = "state", value = params.state }); |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
551 end |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
552 redirect.query = http.formencode(query); |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
553 |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
554 return { |
|
5210
898575a0c6f3
mod_http_oauth2: Switch to '303 See Other' redirects
Matthew Wild <mwild1@gmail.com>
parents:
5209
diff
changeset
|
555 status_code = 303; |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
556 headers = { |
|
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
557 cache_control = "no-store"; |
|
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
558 pragma = "no-cache"; |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
559 location = url.build(redirect); |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
560 }; |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
561 } |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
562 end |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
563 |
|
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
564 -- Implicit flow |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
565 function response_type_handlers.token(client, params, granted_jid) |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
566 local request_username, request_host = jid.split(granted_jid); |
|
5256
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
567 if not request_host or request_host ~= module.host then |
|
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
568 return oauth_error("invalid_request", "invalid JID"); |
|
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
569 end |
|
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
570 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
571 local token_info = new_access_token(granted_jid, granted_role, granted_scopes, client, nil); |
|
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
572 |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
573 local redirect = url.parse(get_redirect_uri(client, params.redirect_uri)); |
|
5463
dacde53467f3
mod_http_oauth2: Proper OAuth error for invalid redirect URI in implicit flow too
Kim Alvefur <zash@zash.se>
parents:
5462
diff
changeset
|
574 if not redirect then return oauth_error("invalid_redirect_uri"); end |
|
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
575 token_info.state = params.state; |
|
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
576 redirect.fragment = http.formencode(token_info); |
|
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
577 |
|
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
578 return { |
|
5210
898575a0c6f3
mod_http_oauth2: Switch to '303 See Other' redirects
Matthew Wild <mwild1@gmail.com>
parents:
5209
diff
changeset
|
579 status_code = 303; |
|
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
580 headers = { |
|
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
581 cache_control = "no-store"; |
|
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
582 pragma = "no-cache"; |
|
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
583 location = url.build(redirect); |
|
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
584 }; |
|
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
585 } |
|
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
586 end |
|
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
587 |
|
6232
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
588 function grant_type_handlers.authorization_code(params, client) |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
589 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:
4237
diff
changeset
|
590 if params.scope and params.scope ~= "" then |
| 5450 | 591 -- FIXME allow a subset of granted scopes |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
592 return oauth_error("invalid_scope", "unknown scope requested"); |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
593 end |
|
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
594 local code, err = codes:get("authorization_code:" .. params.client_id .. "#" .. params.code); |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
595 if err then error(err); end |
|
5214
d5492bc861f6
mod_http_oauth2: Remove authorization codes after use
Kim Alvefur <zash@zash.se>
parents:
5213
diff
changeset
|
596 -- 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:
5213
diff
changeset
|
597 -- prevent a second attempted use |
|
5550
4fda06be6b08
mod_http_oauth2: Make note about handling repeated
Kim Alvefur <zash@zash.se>
parents:
5549
diff
changeset
|
598 -- TODO if a second attempt *is* made, revoke any tokens issued |
|
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
599 codes:set("authorization_code:" .. params.client_id .. "#" .. params.code, nil); |
|
4269
143515d0b212
mod_http_oauth2: Factor out authorization code validity decision
Kim Alvefur <zash@zash.se>
parents:
4265
diff
changeset
|
600 if not code or type(code) ~= "table" or code_expired(code) then |
|
4260
c539334dd01a
mod_http_oauth2: Rescope oauth client config into users' storage
Kim Alvefur <zash@zash.se>
parents:
4259
diff
changeset
|
601 module:log("debug", "authorization_code invalid or expired: %q", code); |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
602 return oauth_error("invalid_client", "incorrect credentials"); |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
603 end |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
604 |
|
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
605 -- TODO Decide if the code should be removed or not when PKCE fails |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
606 local transform = verifier_transforms[code.challenge_method or "plain"]; |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
607 if not transform then |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
608 return oauth_error("invalid_request", "unknown challenge transform method"); |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
609 elseif transform(params.code_verifier) ~= code.challenge then |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
610 return oauth_error("invalid_grant", "incorrect credentials"); |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
611 end |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
612 |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
613 return json.encode(new_access_token(code.granted_jid, code.granted_role, code.granted_scopes, client, code.id_token)); |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
614 end |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
615 |
|
6241
b460b2a65f0b
mod_http_oauth2: Remove now redundant client_id check from remaining grant handlers
Kim Alvefur <zash@zash.se>
parents:
6238
diff
changeset
|
616 function grant_type_handlers.refresh_token(params, client) |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
617 if not params.refresh_token then return oauth_error("invalid_request", "missing 'refresh_token'"); end |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
618 |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
619 local refresh_token_info = tokens.get_token_info(params.refresh_token); |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
620 if not refresh_token_info or refresh_token_info.purpose ~= "oauth2-refresh" then |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
621 return oauth_error("invalid_grant", "invalid refresh token"); |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
622 end |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
623 |
|
5512
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
624 local refresh_token_client = refresh_token_info.grant.data.oauth2_client; |
|
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
625 if not refresh_token_client.hash or refresh_token_client.hash ~= client.client_hash then |
|
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
626 module:log("warn", "OAuth client %q (%s) tried to use refresh token belonging to %q (%s)", client.client_name, client.client_hash, |
|
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
627 refresh_token_client.name, refresh_token_client.hash); |
|
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
628 return oauth_error("unauthorized_client", "incorrect credentials"); |
|
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
629 end |
|
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
630 |
|
5446
dd7bddc87f98
mod_http_oauth2: Fix inclusion of role in refreshed access tokens
Kim Alvefur <zash@zash.se>
parents:
5445
diff
changeset
|
631 local refresh_scopes = refresh_token_info.grant.data.oauth2_scopes; |
|
5448
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
632 |
|
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
633 if params.scope then |
|
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
634 local granted_scopes = set.new(parse_scopes(refresh_scopes)); |
|
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
635 local requested_scopes = parse_scopes(params.scope); |
|
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
636 refresh_scopes = array.filter(requested_scopes, function(scope) |
|
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
637 return granted_scopes:contains(scope); |
|
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
638 end):concat(" "); |
|
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
639 end |
|
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
640 |
|
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
641 local username = jid.split(refresh_token_info.jid); |
|
5446
dd7bddc87f98
mod_http_oauth2: Fix inclusion of role in refreshed access tokens
Kim Alvefur <zash@zash.se>
parents:
5445
diff
changeset
|
642 local new_scopes, role = filter_scopes(username, refresh_scopes); |
|
dd7bddc87f98
mod_http_oauth2: Fix inclusion of role in refreshed access tokens
Kim Alvefur <zash@zash.se>
parents:
5445
diff
changeset
|
643 |
|
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
644 -- new_access_token() requires the actual token |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
645 refresh_token_info.token = params.refresh_token; |
|
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
646 |
|
5448
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
647 return json.encode(new_access_token(refresh_token_info.jid, role, new_scopes, client, nil, refresh_token_info)); |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
648 end |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
649 |
|
6241
b460b2a65f0b
mod_http_oauth2: Remove now redundant client_id check from remaining grant handlers
Kim Alvefur <zash@zash.se>
parents:
6238
diff
changeset
|
650 grant_type_handlers[device_uri] = function(params, client) |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
651 if not params.device_code then return oauth_error("invalid_request", "missing 'device_code'"); end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
652 |
|
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
653 local code = codes:get("device_code:" .. params.client_id .. "#" .. params.device_code); |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
654 if type(code) ~= "table" or code_expired(code) then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
655 return oauth_error("expired_token"); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
656 elseif code.error then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
657 return code.error; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
658 elseif not code.granted_jid then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
659 return oauth_error("authorization_pending"); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
660 end |
|
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
661 codes:set("device_code:" .. params.client_id .. "#" .. params.device_code, nil); |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
662 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
663 return json.encode(new_access_token(code.granted_jid, code.granted_role, code.granted_scopes, client, code.id_token)); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
664 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
665 |
|
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
666 -- RFC 7636 Proof Key for Code Exchange by OAuth Public Clients |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
667 |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
668 function verifier_transforms.plain(code_verifier) |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
669 -- code_challenge = code_verifier |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
670 return code_verifier; |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
671 end |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
672 |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
673 function verifier_transforms.S256(code_verifier) |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
674 -- code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) |
|
5391
4aedce4fb95d
mod_http_oauth2: Fix accidental uppercase in invocation of hash function
Kim Alvefur <zash@zash.se>
parents:
5390
diff
changeset
|
675 return code_verifier and b64url(hashes.sha256(code_verifier)); |
|
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
676 end |
|
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
677 |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
678 -- 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:
5207
diff
changeset
|
679 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:
5207
diff
changeset
|
680 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
681 -- 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:
5207
diff
changeset
|
682 -- 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:
5207
diff
changeset
|
683 -- 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:
5207
diff
changeset
|
684 -- (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:
5207
diff
changeset
|
685 -- to one of them). |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
686 -- 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:
5207
diff
changeset
|
687 -- 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:
5207
diff
changeset
|
688 local function get_auth_state(request) |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
689 local form = request.method == "POST" |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
690 and request.body |
|
5276
67777cb7353d
mod_http_oauth2: Pedantic optimization
Kim Alvefur <zash@zash.se>
parents:
5273
diff
changeset
|
691 and request.body ~= "" |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
692 and request.headers.content_type == "application/x-www-form-urlencoded" |
|
5514
61b8d3eb91a4
mod_http_oauth2: Revert strict form check to allow consent of multiple scopes
Kim Alvefur <zash@zash.se>
parents:
5513
diff
changeset
|
693 and http.formdecode(request.body); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
694 |
|
5277
a1055024b94e
mod_http_oauth2: Stricten check of urlencoded form data
Kim Alvefur <zash@zash.se>
parents:
5276
diff
changeset
|
695 if type(form) ~= "table" then return {}; end |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
696 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
697 if not form.user_token then |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
698 -- First step: login |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
699 local username = encodings.stringprep.nodeprep(form.username); |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
700 local password = encodings.stringprep.saslprep(form.password); |
|
5752
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
701 -- Many things hooked to authentication-{success,failure} don't expect |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
702 -- non-XMPP sessions so here's something close enough... |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
703 local auth_event = { |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
704 session = { |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
705 type = "http"; |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
706 ip = request.ip; |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
707 conn = request.conn; |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
708 username = username; |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
709 host = module.host; |
|
5771
72799c330986
mod_http_oauth2: Add logger to "session" for auth event
Kim Alvefur <zash@zash.se>
parents:
5770
diff
changeset
|
710 log = request.log; |
|
5752
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
711 sasl_handler = { username = username; selected = "x-www-form" }; |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
712 client_id = request.headers.user_agent; |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
713 }; |
|
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
714 }; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
715 if not (username and password) or not usermanager.test_password(username, module.host, password) then |
|
5752
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
716 module:fire_event("authentication-failure", auth_event); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
717 return { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
718 error = "Invalid username/password"; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
719 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
720 end |
|
5752
c27eaa7117d6
mod_http_oauth2: Fire authentication events on login form
Kim Alvefur <zash@zash.se>
parents:
5751
diff
changeset
|
721 module:fire_event("authentication-success", auth_event); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
722 return { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
723 user = { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
724 username = username; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
725 host = module.host; |
|
5830
b109773ce6fe
mod_http_oauth2: Reuse JWT issuance time as substitute for auth time
Kim Alvefur <zash@zash.se>
parents:
5799
diff
changeset
|
726 token = new_user_token({ username = username; host = module.host; amr = { "pwd" } }); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
727 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
728 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
729 elseif form.user_token and form.consent then |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
730 -- Second step: consent |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
731 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:
5207
diff
changeset
|
732 if not ok then |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
733 return { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
734 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:
5207
diff
changeset
|
735 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
736 end |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
737 |
|
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
738 local scopes = array():append(form):filter(function(field) |
|
5424
b45d9a81b3da
mod_http_oauth2: Revert role selector, going to try something else
Kim Alvefur <zash@zash.se>
parents:
5423
diff
changeset
|
739 return field.name == "scope"; |
|
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
740 end):pluck("value"); |
|
5271
3a1df3adad0c
mod_http_oauth2: Allow user to decide which requested scopes to grant
Kim Alvefur <zash@zash.se>
parents:
5268
diff
changeset
|
741 |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
742 user.token = form.user_token; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
743 return { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
744 user = user; |
|
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
745 scopes = scopes; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
746 consent = form.consent == "granted"; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
747 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
748 end |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
749 |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
750 return {}; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
751 end |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
752 |
|
5222
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
753 local function get_request_credentials(request) |
|
5224
cd5cf4cc6304
mod_http_oauth2: Fail early when no authorization header present
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
754 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:
5223
diff
changeset
|
755 |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
756 local auth_type, auth_data = string.match(request.headers.authorization, "^(%S+)%s(.+)$"); |
|
5935
46394b327d17
mod_http_oauth2: Guard against malformed authorization header
Kim Alvefur <zash@zash.se>
parents:
5931
diff
changeset
|
757 if not auth_type then return nil; end |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
758 |
|
5931
ca3479c67e48
mod_http_oauth2: HTTP authentication schemes are case-insensitive
Kim Alvefur <zash@zash.se>
parents:
5858
diff
changeset
|
759 -- As described in Section 2.3 of [RFC5234], the string Bearer is case-insensitive. |
|
ca3479c67e48
mod_http_oauth2: HTTP authentication schemes are case-insensitive
Kim Alvefur <zash@zash.se>
parents:
5858
diff
changeset
|
760 -- https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-5.1.1 |
|
ca3479c67e48
mod_http_oauth2: HTTP authentication schemes are case-insensitive
Kim Alvefur <zash@zash.se>
parents:
5858
diff
changeset
|
761 auth_type = auth_type:lower(); |
|
ca3479c67e48
mod_http_oauth2: HTTP authentication schemes are case-insensitive
Kim Alvefur <zash@zash.se>
parents:
5858
diff
changeset
|
762 |
|
ca3479c67e48
mod_http_oauth2: HTTP authentication schemes are case-insensitive
Kim Alvefur <zash@zash.se>
parents:
5858
diff
changeset
|
763 if auth_type == "basic" then |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
764 local creds = base64.decode(auth_data); |
|
5222
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
765 if not creds then return; end |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
766 local username, password = string.match(creds, "^([^:]+):(.*)$"); |
|
5222
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
767 if not username then return; end |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
768 return { |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
769 type = "basic"; |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
770 username = username; |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
771 password = password; |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
772 }; |
|
5931
ca3479c67e48
mod_http_oauth2: HTTP authentication schemes are case-insensitive
Kim Alvefur <zash@zash.se>
parents:
5858
diff
changeset
|
773 elseif auth_type == "bearer" then |
|
5222
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
774 return { |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
775 type = "bearer"; |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
776 bearer_token = auth_data; |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
777 }; |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
778 end |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
779 |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
780 return nil; |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
781 end |
|
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
782 |
|
3920
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
783 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:
3919
diff
changeset
|
784 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:
3919
diff
changeset
|
785 |
|
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
786 function grant_type_handlers.password(params) |
|
6244
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
787 local request_jid = params.username; |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
788 if not request_jid then |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
789 return oauth_error("invalid_request", "missing 'username' (JID)"); |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
790 end |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
791 local request_password = params.password |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
792 if not request_password then |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
793 return oauth_error("invalid_request", "missing 'password'"); |
|
b7eb7d256939
mod_http_oauth2: Return instead of throwing errors
Kim Alvefur <zash@zash.se>
parents:
6243
diff
changeset
|
794 end |
|
3920
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
795 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:
3919
diff
changeset
|
796 if params.scope then |
| 5450 | 797 -- TODO shouldn't we support scopes / roles here? |
|
3920
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
798 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:
3919
diff
changeset
|
799 end |
|
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
800 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:
3919
diff
changeset
|
801 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:
3919
diff
changeset
|
802 end |
|
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
803 if request_password == component_secret then |
|
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
804 local granted_jid = jid.join(request_username, request_host, request_resource); |
|
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
805 return json.encode(new_access_token(granted_jid, nil, nil, nil)); |
|
3920
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
806 end |
|
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
807 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:
3919
diff
changeset
|
808 end |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
809 |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
810 -- TODO How would this make sense with components? |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
811 -- Have an admin authenticate maybe? |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
812 response_type_handlers.code = nil; |
|
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
813 response_type_handlers.token = nil; |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
814 grant_type_handlers.authorization_code = nil; |
|
3920
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
815 end |
|
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
816 |
|
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
817 local function render_error(err) |
|
6408
7fe484e7b574
mod_http_oauth2: Make error template optional
Kim Alvefur <zash@zash.se>
parents:
6296
diff
changeset
|
818 if not templates.error then return err or 500; end |
|
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
819 return render_page(templates.error, { error = err }); |
|
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
820 end |
|
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
821 |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
822 -- 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:
5207
diff
changeset
|
823 -- 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:
5207
diff
changeset
|
824 -- 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:
5207
diff
changeset
|
825 -- 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:
5207
diff
changeset
|
826 -- error directly to the user-agent. |
|
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
827 local function error_response(request, redirect_uri, err) |
|
6263
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
828 if not redirect_uri or redirect_uri == oob_uri then |
|
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
829 return render_error(err); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
830 end |
|
6263
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
831 local params = strict_formdecode(request.url.query); |
|
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
832 if redirect_uri == device_uri then |
|
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
833 local is_device, device_state = verify_device_token(params.state); |
|
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
834 if is_device then |
|
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
835 local device_code = b64url(hashes.hmac_sha256(verification_key, device_state.user_code)); |
|
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
836 local code = codes:get("device_code:" .. params.client_id .. "#" .. device_code); |
|
6264
e1c54de06905
mod_http_oauth2: Handle case of device state having expired
Kim Alvefur <zash@zash.se>
parents:
6263
diff
changeset
|
837 if type(code) == "table" then |
|
e1c54de06905
mod_http_oauth2: Handle case of device state having expired
Kim Alvefur <zash@zash.se>
parents:
6263
diff
changeset
|
838 code.error = err; |
|
e1c54de06905
mod_http_oauth2: Handle case of device state having expired
Kim Alvefur <zash@zash.se>
parents:
6263
diff
changeset
|
839 code.expires = os.time() + 60; |
|
e1c54de06905
mod_http_oauth2: Handle case of device state having expired
Kim Alvefur <zash@zash.se>
parents:
6263
diff
changeset
|
840 codes:set("device_code:" .. params.client_id .. "#" .. device_code, code); |
|
e1c54de06905
mod_http_oauth2: Handle case of device state having expired
Kim Alvefur <zash@zash.se>
parents:
6263
diff
changeset
|
841 end |
|
6263
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
842 end |
|
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
843 return render_error(err); |
|
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
844 end |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
845 local redirect_query = url.parse(redirect_uri); |
|
5229
c24a622a7b85
mod_http_oauth2: Fix appending of query parts in error redirects
Kim Alvefur <zash@zash.se>
parents:
5228
diff
changeset
|
846 local sep = redirect_query.query and "&" or "?"; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
847 redirect_uri = redirect_uri |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
848 .. sep .. http.formencode(err.extra.oauth2_response) |
|
6263
aae94f82c56e
mod_http_oauth2: Refactor to return all errors to Device clients
Kim Alvefur <zash@zash.se>
parents:
6248
diff
changeset
|
849 .. "&" .. http.formencode({ state = params.state, iss = get_issuer() }); |
|
5799
c75328aeaba3
mod_http_oauth2: Reduce log level for error delivery via redirect
Kim Alvefur <zash@zash.se>
parents:
5798
diff
changeset
|
850 module:log("debug", "Sending error response to client via redirect to %s", redirect_uri); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
851 return { |
|
5210
898575a0c6f3
mod_http_oauth2: Switch to '303 See Other' redirects
Matthew Wild <mwild1@gmail.com>
parents:
5209
diff
changeset
|
852 status_code = 303; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
853 headers = { |
|
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
854 cache_control = "no-store"; |
|
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
855 pragma = "no-cache"; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
856 location = redirect_uri; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
857 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
858 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
859 end |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
860 |
|
5549
01a0b67a9afd
mod_http_oauth2: Add TODO about disabling password grant
Kim Alvefur <zash@zash.se>
parents:
5548
diff
changeset
|
861 local allowed_grant_type_handlers = module:get_option_set("allowed_oauth2_grant_types", { |
|
01a0b67a9afd
mod_http_oauth2: Add TODO about disabling password grant
Kim Alvefur <zash@zash.se>
parents:
5548
diff
changeset
|
862 "authorization_code"; |
|
01a0b67a9afd
mod_http_oauth2: Add TODO about disabling password grant
Kim Alvefur <zash@zash.se>
parents:
5548
diff
changeset
|
863 "refresh_token"; |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
864 device_uri; |
|
5549
01a0b67a9afd
mod_http_oauth2: Add TODO about disabling password grant
Kim Alvefur <zash@zash.se>
parents:
5548
diff
changeset
|
865 }) |
|
5614
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
866 if allowed_grant_type_handlers:contains("device_code") then |
|
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
867 -- expand short form because that URI is long |
|
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
868 module:log("debug", "Expanding %q to %q in '%s'", "device_code", device_uri, "allowed_oauth2_grant_types"); |
|
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
869 allowed_grant_type_handlers:remove("device_code"); |
|
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
870 allowed_grant_type_handlers:add(device_uri); |
|
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
871 end |
|
5187
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
872 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:
5186
diff
changeset
|
873 if not allowed_grant_type_handlers:contains(handler_type) then |
|
5230
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
874 module:log("debug", "Grant type %q disabled", handler_type); |
|
5187
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
875 grant_type_handlers[handler_type] = nil; |
|
5230
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
876 else |
|
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
877 module:log("debug", "Grant type %q enabled", handler_type); |
|
5187
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
878 end |
|
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
879 end |
|
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
880 |
|
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
881 -- "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:
5186
diff
changeset
|
882 local allowed_response_type_handlers = module:get_option_set("allowed_oauth2_response_types", {"code"}) |
|
5198
2e8a7a0f932d
mod_http_oauth2: Fix response type config
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
883 for handler_type in pairs(response_type_handlers) do |
|
2e8a7a0f932d
mod_http_oauth2: Fix response type config
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
884 if not allowed_response_type_handlers:contains(handler_type) then |
|
5230
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
885 module:log("debug", "Response type %q disabled", handler_type); |
|
5231
bef543068077
mod_http_oauth2: Fix to disable disabled response handlers correctly
Kim Alvefur <zash@zash.se>
parents:
5230
diff
changeset
|
886 response_type_handlers[handler_type] = nil; |
|
5230
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
887 else |
|
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
888 module:log("debug", "Response type %q enabled", handler_type); |
|
5187
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
889 end |
|
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
890 end |
|
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
891 |
|
5716
426c42c11f89
mod_http_oauth2: Make defaults more secure
Kim Alvefur <zash@zash.se>
parents:
5715
diff
changeset
|
892 local allowed_challenge_methods = module:get_option_set("allowed_oauth2_code_challenge_methods", { "S256" }) |
|
5384
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
893 for handler_type in pairs(verifier_transforms) do |
|
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
894 if not allowed_challenge_methods:contains(handler_type) then |
|
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
895 module:log("debug", "Challenge method %q disabled", handler_type); |
|
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
896 verifier_transforms[handler_type] = nil; |
|
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
897 else |
|
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
898 module:log("debug", "Challenge method %q enabled", handler_type); |
|
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
899 end |
|
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
900 end |
|
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
901 |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
902 function handle_token_grant(event) |
|
5223
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
903 local credentials = get_request_credentials(event.request); |
|
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
904 |
|
3934
469408682152
mod_http_oauth2: Set content type on successful repsponses (fixes #1501)
Kim Alvefur <zash@zash.se>
parents:
3920
diff
changeset
|
905 event.response.headers.content_type = "application/json"; |
|
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
906 event.response.headers.cache_control = "no-store"; |
|
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
907 event.response.headers.pragma = "no-cache"; |
|
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
908 local params = strict_formdecode(event.request.body); |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
909 if not params then |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
910 return oauth_error("invalid_request", "Could not parse request body as 'application/x-www-form-urlencoded'"); |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
911 end |
|
5223
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
912 |
|
5225
3439eb37f23b
mod_http_oauth2: token endpoint: handle missing credentials
Matthew Wild <mwild1@gmail.com>
parents:
5224
diff
changeset
|
913 if credentials and credentials.type == "basic" then |
|
5385
544b92750a2a
mod_http_oauth2: Advertise supported token endpoint auth methods
Kim Alvefur <zash@zash.se>
parents:
5384
diff
changeset
|
914 -- client_secret_basic converted internally to client_secret_post |
|
5223
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
915 params.client_id = http.urldecode(credentials.username); |
|
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
916 params.client_secret = http.urldecode(credentials.password); |
|
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
917 end |
|
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
918 |
|
6232
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
919 if not params.client_id then return oauth_error("invalid_request", "missing 'client_id'"); end |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
920 if not params.client_secret then return oauth_error("invalid_request", "missing 'client_secret'"); end |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
921 |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
922 local client = check_client(params.client_id); |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
923 if not client then |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
924 return oauth_error("invalid_client", "incorrect credentials"); |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
925 end |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
926 |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
927 if not verify_client_secret(params.client_id, params.client_secret) then |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
928 module:log("debug", "client_secret mismatch"); |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
929 return oauth_error("invalid_client", "incorrect credentials"); |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
930 end |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
931 |
|
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
932 |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
933 local grant_type = params.grant_type |
|
6277
dfc035ecabb4
mod_http_oauth2: Remove defaults that should be included on clients
Kim Alvefur <zash@zash.se>
parents:
6276
diff
changeset
|
934 if not array_contains(client.grant_types, grant_type) then |
|
6238
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
935 return oauth_error("invalid_request", "'grant_type' not registered"); |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
936 end |
|
6237
9d88c3d9eea5
mod_http_oauth2: Enforce the registered grant types
Kim Alvefur <zash@zash.se>
parents:
6234
diff
changeset
|
937 |
|
6238
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
938 local grant_handler = grant_type_handlers[grant_type]; |
|
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
939 if not grant_handler then |
|
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
940 return oauth_error("invalid_request", "'grant_type' not available"); |
|
6237
9d88c3d9eea5
mod_http_oauth2: Enforce the registered grant types
Kim Alvefur <zash@zash.se>
parents:
6234
diff
changeset
|
941 end |
|
9d88c3d9eea5
mod_http_oauth2: Enforce the registered grant types
Kim Alvefur <zash@zash.se>
parents:
6234
diff
changeset
|
942 |
|
6232
2505542c6c50
mod_http_oauth2: Deduplicate client authentication
Kim Alvefur <zash@zash.se>
parents:
6207
diff
changeset
|
943 return grant_handler(params, client); |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
944 end |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
945 |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
946 local function handle_authorization_request(event) |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
947 local request = event.request; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
948 |
|
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
949 -- Directly returning errors to the user before we have a validated client object |
|
4258
cc712899becd
mod_http_oauth2: Unpack event object to improve readability
Kim Alvefur <zash@zash.se>
parents:
4257
diff
changeset
|
950 if not request.url.query then |
|
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
951 return render_error(oauth_error("invalid_request", "Missing query parameters")); |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
952 end |
|
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
953 local params = strict_formdecode(request.url.query); |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
954 if not params then |
|
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
955 return render_error(oauth_error("invalid_request", "Invalid query parameters")); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
956 end |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
957 |
|
5471
d4d333cb75b2
mod_http_oauth2: Clarify some error messages
Kim Alvefur <zash@zash.se>
parents:
5470
diff
changeset
|
958 if not params.client_id then |
|
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
959 return render_error(oauth_error("invalid_request", "Missing 'client_id' parameter")); |
|
5471
d4d333cb75b2
mod_http_oauth2: Clarify some error messages
Kim Alvefur <zash@zash.se>
parents:
5470
diff
changeset
|
960 end |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
961 |
|
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
962 local client = check_client(params.client_id); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
963 |
|
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
964 if not client then |
|
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
965 return render_error(oauth_error("invalid_request", "Invalid 'client_id' parameter")); |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
966 end |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
967 |
|
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
968 local redirect_uri = get_redirect_uri(client, params.redirect_uri); |
|
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
969 if not redirect_uri then |
|
5475
022733437fef
mod_http_oauth2: Validate redirect_uri before using it for error redirects
Kim Alvefur <zash@zash.se>
parents:
5474
diff
changeset
|
970 return render_error(oauth_error("invalid_request", "Invalid 'redirect_uri' parameter")); |
|
022733437fef
mod_http_oauth2: Validate redirect_uri before using it for error redirects
Kim Alvefur <zash@zash.se>
parents:
5474
diff
changeset
|
971 end |
|
022733437fef
mod_http_oauth2: Validate redirect_uri before using it for error redirects
Kim Alvefur <zash@zash.se>
parents:
5474
diff
changeset
|
972 -- From this point we know that redirect_uri is safe to use |
|
022733437fef
mod_http_oauth2: Validate redirect_uri before using it for error redirects
Kim Alvefur <zash@zash.se>
parents:
5474
diff
changeset
|
973 |
|
6238
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
974 local response_type = params.response_type; |
|
6277
dfc035ecabb4
mod_http_oauth2: Remove defaults that should be included on clients
Kim Alvefur <zash@zash.se>
parents:
6276
diff
changeset
|
975 if not array_contains(client.response_types, response_type) then |
|
6238
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
976 return error_response(request, redirect_uri, oauth_error("invalid_client", "'response_type' not registered")); |
|
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
977 end |
|
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
978 if not allowed_response_type_handlers:contains(response_type) then |
|
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
979 return error_response(request, redirect_uri, oauth_error("unsupported_response_type", "'response_type' not allowed")); |
|
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
980 end |
|
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
981 local response_handler = response_type_handlers[response_type]; |
|
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
982 if not response_handler then |
|
7b3316ac24b3
mod_http_oauth2: Refactor client grant and response type checks
Kim Alvefur <zash@zash.se>
parents:
6237
diff
changeset
|
983 return error_response(request, redirect_uri, oauth_error("unsupported_response_type")); |
|
5405
c7a5caad28ef
mod_http_oauth2: Enforce response type encoded in client_id
Kim Alvefur <zash@zash.se>
parents:
5404
diff
changeset
|
984 end |
|
c7a5caad28ef
mod_http_oauth2: Enforce response type encoded in client_id
Kim Alvefur <zash@zash.se>
parents:
5404
diff
changeset
|
985 |
|
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
986 local requested_scopes = parse_scopes(params.scope or ""); |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
987 if client.scope then |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
988 local client_scopes = set.new(parse_scopes(client.scope)); |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
989 requested_scopes:filter(function(scope) |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
990 return client_scopes:contains(scope); |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
991 end); |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
992 end |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
993 |
|
5518
d87d0e4a8516
mod_http_oauth2: Validate the OpenID 'prompt' parameter
Kim Alvefur <zash@zash.se>
parents:
5514
diff
changeset
|
994 -- The 'prompt' parameter from OpenID Core |
|
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
995 local prompt = set.new(parse_scopes(respect_prompt and params.prompt or "select_account login consent")); |
|
5518
d87d0e4a8516
mod_http_oauth2: Validate the OpenID 'prompt' parameter
Kim Alvefur <zash@zash.se>
parents:
5514
diff
changeset
|
996 |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
997 local auth_state = get_auth_state(request); |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
998 if not auth_state.user then |
|
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
999 if not prompt:contains("login") then |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1000 -- Currently no cookies or such are used, so login is required every time. |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1001 return error_response(request, redirect_uri, oauth_error("login_required")); |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1002 end |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1003 |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1004 -- Render login page |
|
5466
398d936e77fb
mod_http_oauth2: Add support for the OpenID 'login_hint' parameter
Kim Alvefur <zash@zash.se>
parents:
5465
diff
changeset
|
1005 local extra = {}; |
|
398d936e77fb
mod_http_oauth2: Add support for the OpenID 'login_hint' parameter
Kim Alvefur <zash@zash.se>
parents:
5465
diff
changeset
|
1006 if params.login_hint then |
|
5764
87920d436cb4
mod_http_oauth2: Handle login_hint without @hostpart
Kim Alvefur <zash@zash.se>
parents:
5752
diff
changeset
|
1007 extra.username_hint = (jid.prepped_split(params.login_hint) or encodings.stringprep.nodeprep(params.login_hint)); |
|
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1008 elseif not prompt:contains("select_account") then |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1009 -- TODO If the login page is split into account selection followed by login |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1010 -- (e.g. password), and then the account selection could be skipped iff the |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1011 -- 'login_hint' parameter is present. |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1012 return error_response(request, redirect_uri, oauth_error("account_selection_required")); |
|
5466
398d936e77fb
mod_http_oauth2: Add support for the OpenID 'login_hint' parameter
Kim Alvefur <zash@zash.se>
parents:
5465
diff
changeset
|
1013 end |
|
398d936e77fb
mod_http_oauth2: Add support for the OpenID 'login_hint' parameter
Kim Alvefur <zash@zash.se>
parents:
5465
diff
changeset
|
1014 return render_page(templates.login, { state = auth_state; client = client; extra = extra }); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1015 elseif auth_state.consent == nil then |
|
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1016 local scopes, roles = split_scopes(requested_scopes); |
|
5452
b071d8ee6555
mod_http_oauth2: Show only roles the user can use in consent dialog
Kim Alvefur <zash@zash.se>
parents:
5451
diff
changeset
|
1017 roles = user_assumable_roles(auth_state.user.username, roles); |
|
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1018 |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1019 if not prompt:contains("consent") then |
|
6272
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
1020 if array_contains(scopes, "offline_access") then |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
1021 -- MUST ensure that the prompt parameter contains consent |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
1022 return error_response(request, redirect_uri, oauth_error("consent_required")); |
|
8108aec64fb9
mod_http_oauth2: Support the "offline_access" for granting refresh tokens
Kim Alvefur <zash@zash.se>
parents:
6264
diff
changeset
|
1023 end |
|
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1024 local grants = tokens.get_user_grants(auth_state.user.username); |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1025 local matching_grant; |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1026 if grants then |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1027 for grant_id, grant in pairs(grants) do |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1028 if grant.data and grant.data.oauth2_client and grant.data.oauth2_client.hash == client.client_hash then |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1029 if set.new(parse_scopes(grant.data.oauth2_scopes)) == set.new(scopes+roles) then |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1030 matching_grant = grant_id; |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1031 break |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1032 end |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1033 end |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1034 end |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1035 end |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1036 |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1037 if not matching_grant then |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1038 return error_response(request, redirect_uri, oauth_error("consent_required")); |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1039 else |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1040 -- Consent for these scopes already granted to this exact client, continue |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1041 auth_state.scopes = scopes + roles; |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1042 auth_state.consent = "granted"; |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1043 end |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1044 |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1045 else |
|
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1046 -- Render consent page |
|
6291
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1047 module:log("debug", "scopes=%q", scopes); |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1048 local scope_choices = array.new(module:get_host_items("openid-claim")):map(function(item) |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1049 if type(item) == "string" then |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1050 return { claim = item }; |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1051 elseif type(item) == "table" and type(item.claim) == "string" then |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1052 return item; |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1053 end |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1054 end):filter(function (item) |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1055 if array_contains(scopes, item.claim) then |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1056 module:log("debug", "scopes contains %q", item); |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1057 return true; |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1058 else |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1059 module:log("debug", "scopes contains NO %q", item); |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1060 return false; |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1061 end |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1062 end); |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1063 for _, role in ipairs(roles) do |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1064 if role == "xmpp" then |
|
6295
c96bd4156664
mod_http_oauth2: Fix passing roles and scopes the same way to template
Kim Alvefur <zash@zash.se>
parents:
6291
diff
changeset
|
1065 scope_choices:push({ claim = role; title = "XMPP"; |
|
6291
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1066 description = "Unlimited access to your account, including sending and receiving messages."; }); |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1067 else |
|
6295
c96bd4156664
mod_http_oauth2: Fix passing roles and scopes the same way to template
Kim Alvefur <zash@zash.se>
parents:
6291
diff
changeset
|
1068 scope_choices:push({ claim = role; title = role, description = "Prosody Role" }); |
|
6291
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1069 end |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1070 end |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1071 return render_page(templates.consent, { state = auth_state; client = client; scopes = scope_choices }, true); |
|
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
1072 end |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1073 elseif not auth_state.consent then |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1074 -- Notify client of rejection |
|
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
1075 return error_response(request, redirect_uri, oauth_error("access_denied")); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1076 end |
|
5271
3a1df3adad0c
mod_http_oauth2: Allow user to decide which requested scopes to grant
Kim Alvefur <zash@zash.se>
parents:
5268
diff
changeset
|
1077 -- else auth_state.consent == true |
|
3a1df3adad0c
mod_http_oauth2: Allow user to decide which requested scopes to grant
Kim Alvefur <zash@zash.se>
parents:
5268
diff
changeset
|
1078 |
|
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1079 local granted_scopes = auth_state.scopes |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1080 if client.scope then |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1081 local client_scopes = set.new(parse_scopes(client.scope)); |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1082 granted_scopes:filter(function(scope) |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1083 return client_scopes:contains(scope); |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1084 end); |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1085 end |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1086 |
|
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
1087 params.scope = granted_scopes:concat(" "); |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1088 |
|
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
1089 local user_jid = jid.join(auth_state.user.username, module.host); |
|
6289
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1090 local id_token; |
|
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1091 -- https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3.1.2.1 |
|
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1092 if array_contains(granted_scopes, "openid") then |
|
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1093 local client_secret = make_client_secret(params.client_id); |
|
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1094 local id_token_signer = jwt.new_signer("HS256", client_secret); |
|
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1095 id_token = id_token_signer({ |
|
6291
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1096 iss = get_issuer(); -- REQUIRED |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1097 sub = url.build({ scheme = "xmpp"; path = user_jid }); -- REQUIRED |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1098 aud = params.client_id; -- REQUIRED |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1099 -- exp REQUIRED, set by util.jwt |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1100 -- iat REQUIRED, set by util.jwt |
|
6e80b2cb5fe6
mod_http_oauth2: Show scope descriptions
Kim Alvefur <zash@zash.se>
parents:
6289
diff
changeset
|
1101 auth_time = auth_state.user.iat; -- REQUIRED when Essential Claim, otherwise OPTIONAL |
|
6289
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1102 nonce = params.nonce; |
|
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1103 amr = auth_state.user.amr; -- RFC 8176: Authentication Method Reference Values |
|
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1104 }); |
|
9b03238d4e0e
mod_http_oauth2: Only issue id_token when granted openid scope
Kim Alvefur <zash@zash.se>
parents:
6282
diff
changeset
|
1105 end |
|
5468
14b5446e22e1
mod_http_oauth2: Fix returning errors from response handlers
Kim Alvefur <zash@zash.se>
parents:
5467
diff
changeset
|
1106 local ret = response_handler(client, params, user_jid, id_token); |
|
14b5446e22e1
mod_http_oauth2: Fix returning errors from response handlers
Kim Alvefur <zash@zash.se>
parents:
5467
diff
changeset
|
1107 if errors.is_err(ret) then |
|
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
1108 return error_response(request, redirect_uri, ret); |
|
5468
14b5446e22e1
mod_http_oauth2: Fix returning errors from response handlers
Kim Alvefur <zash@zash.se>
parents:
5467
diff
changeset
|
1109 end |
|
14b5446e22e1
mod_http_oauth2: Fix returning errors from response handlers
Kim Alvefur <zash@zash.se>
parents:
5467
diff
changeset
|
1110 return ret; |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
1111 end |
|
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
1112 |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1113 local function handle_device_authorization_request(event) |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1114 local request = event.request; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1115 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1116 local credentials = get_request_credentials(request); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1117 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1118 local params = strict_formdecode(request.body); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1119 if not params then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1120 return render_error(oauth_error("invalid_request", "Invalid query parameters")); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1121 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1122 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1123 if credentials and credentials.type == "basic" then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1124 -- client_secret_basic converted internally to client_secret_post |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1125 params.client_id = http.urldecode(credentials.username); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1126 local client_secret = http.urldecode(credentials.password); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1127 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1128 if not verify_client_secret(params.client_id, client_secret) then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1129 module:log("debug", "client_secret mismatch"); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1130 return oauth_error("invalid_client", "incorrect credentials"); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1131 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1132 else |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1133 return 401; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1134 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1135 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1136 local client = check_client(params.client_id); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1137 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1138 if not client then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1139 return render_error(oauth_error("invalid_request", "Invalid 'client_id' parameter")); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1140 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1141 |
|
6273
fe797da37174
mod_http_oauth2: Use cheaper array member check
Kim Alvefur <zash@zash.se>
parents:
6272
diff
changeset
|
1142 if not array_contains(client.grant_types, device_uri) then |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1143 return render_error(oauth_error("invalid_client", "Client not registered for device authorization grant")); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1144 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1145 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1146 local requested_scopes = parse_scopes(params.scope or ""); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1147 if client.scope then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1148 local client_scopes = set.new(parse_scopes(client.scope)); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1149 requested_scopes:filter(function(scope) |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1150 return client_scopes:contains(scope); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1151 end); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1152 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1153 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1154 -- TODO better code generator, this one should be easy to type from a |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1155 -- screen onto a phone |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1156 local user_code = (id.tiny() .. "-" .. id.tiny()):upper(); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1157 local collisions = 0; |
|
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
1158 while codes:get("authorization_code:" .. device_uri .. "#" .. user_code) do |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1159 collisions = collisions + 1; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1160 if collisions > 10 then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1161 return oauth_error("temporarily_unavailable"); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1162 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1163 user_code = (id.tiny() .. "-" .. id.tiny()):upper(); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1164 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1165 -- device code should be derivable after consent but not guessable by the user |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1166 local device_code = b64url(hashes.hmac_sha256(verification_key, user_code)); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1167 local verification_uri = module:http_url() .. "/device"; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1168 local verification_uri_complete = verification_uri .. "?" .. http.formencode({ user_code = user_code }); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1169 |
|
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
1170 local expires = os.time() + 600; |
|
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
1171 local dc_ok = codes:set("device_code:" .. params.client_id .. "#" .. device_code, { expires = expires }); |
|
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
1172 local uc_ok = codes:set("user_code:" .. user_code, |
|
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
1173 { user_code = user_code; expires = expires; client_id = params.client_id; |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1174 scope = requested_scopes:concat(" ") }); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1175 if not dc_ok or not uc_ok then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1176 return oauth_error("temporarily_unavailable"); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1177 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1178 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1179 return { |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1180 headers = { content_type = "application/json"; cache_control = "no-store"; pragma = "no-cache" }; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1181 body = json.encode { |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1182 device_code = device_code; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1183 user_code = user_code; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1184 verification_uri = verification_uri; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1185 verification_uri_complete = verification_uri_complete; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1186 expires_in = 600; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1187 interval = 5; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1188 }; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1189 } |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1190 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1191 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1192 local function handle_device_verification_request(event) |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1193 local request = event.request; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1194 local params = strict_formdecode(request.url.query); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1195 if not params or not params.user_code then |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1196 return render_page(templates.device, { client = false }); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1197 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1198 |
|
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
1199 local device_info = codes:get("user_code:" .. params.user_code); |
|
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
1200 if not device_info or code_expired(device_info) or not codes:set("user_code:" .. params.user_code, nil) then |
|
5608
1893ae742f66
mod_http_oauth2: Show errors on device flow user code entry page
Kim Alvefur <zash@zash.se>
parents:
5607
diff
changeset
|
1201 return render_page(templates.device, { |
|
1893ae742f66
mod_http_oauth2: Show errors on device flow user code entry page
Kim Alvefur <zash@zash.se>
parents:
5607
diff
changeset
|
1202 client = false; |
|
1893ae742f66
mod_http_oauth2: Show errors on device flow user code entry page
Kim Alvefur <zash@zash.se>
parents:
5607
diff
changeset
|
1203 error = oauth_error("expired_token", "Incorrect or expired code"); |
|
1893ae742f66
mod_http_oauth2: Show errors on device flow user code entry page
Kim Alvefur <zash@zash.se>
parents:
5607
diff
changeset
|
1204 }); |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1205 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1206 |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1207 return { |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1208 status_code = 303; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1209 headers = { |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1210 location = module:http_url() .. "/authorize" .. "?" .. http.formencode({ |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1211 client_id = device_info.client_id; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1212 redirect_uri = device_uri; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1213 response_type = "code"; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1214 scope = device_info.scope; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1215 state = new_device_token({ user_code = params.user_code }); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1216 }); |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1217 }; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1218 } |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1219 end |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1220 |
|
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1221 local function handle_introspection_request(event) |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1222 local request = event.request; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1223 local credentials = get_request_credentials(request); |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1224 if not credentials or credentials.type ~= "basic" then |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1225 event.response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1226 return 401; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1227 end |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1228 -- OAuth "client" credentials |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1229 if not verify_client_secret(credentials.username, credentials.password) then |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1230 return 401; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1231 end |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1232 |
|
5681
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1233 local client = check_client(credentials.username); |
|
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1234 if not client then |
|
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1235 return 401; |
|
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1236 end |
|
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1237 |
|
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1238 local form_data = http.formdecode(request.body or "="); |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1239 local token = form_data.token; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1240 if not token then |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1241 return 400; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1242 end |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1243 |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1244 local token_info = tokens.get_token_info(form_data.token); |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1245 if not token_info then |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1246 return { headers = { content_type = "application/json" }; body = json.encode { active = false } }; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1247 end |
|
5681
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1248 local token_client = token_info.grant.data.oauth2_client; |
|
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1249 if not token_client or token_client.hash ~= client.client_hash then |
|
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1250 return 403; |
|
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1251 end |
|
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1252 |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1253 return { |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1254 headers = { content_type = "application/json" }; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1255 body = json.encode { |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1256 active = true; |
|
5858
761142ee0ff2
mod_http_oauth2: Reflect changes to defaults etc
Kim Alvefur <zash@zash.se>
parents:
5830
diff
changeset
|
1257 client_id = credentials.username; -- Verified via client hash |
|
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1258 username = jid.node(token_info.jid); |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1259 scope = token_info.grant.data.oauth2_scopes; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1260 token_type = purpose_map[token_info.purpose]; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1261 exp = token.expires; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1262 iat = token.created; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1263 sub = url.build({ scheme = "xmpp"; path = token_info.jid }); |
|
5681
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1264 aud = credentials.username; |
|
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1265 iss = get_issuer(); |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1266 jti = token_info.id; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1267 }; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1268 }; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1269 end |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1270 |
|
5682
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1271 -- RFC 7009 says that the authorization server should validate that only the client that a token was issued to should be able to revoke it. However |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1272 -- this would prevent someone who comes across a leaked token from doing the responsible thing and revoking it, so this is not enforced by default. |
|
5626
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1273 local strict_auth_revoke = module:get_option_boolean("oauth2_require_auth_revoke", false); |
|
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1274 |
|
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1275 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:
4340
diff
changeset
|
1276 local request, response = event.request, event.response; |
|
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1277 response.headers.cache_control = "no-store"; |
|
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1278 response.headers.pragma = "no-cache"; |
|
5682
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1279 local credentials = get_request_credentials(request); |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1280 if credentials then |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1281 if credentials.type ~= "basic" then |
|
5265
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1282 response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); |
|
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1283 return 401; |
|
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1284 end |
|
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1285 -- OAuth "client" credentials |
|
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1286 if not verify_client_secret(credentials.username, credentials.password) then |
|
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1287 return 401; |
|
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1288 end |
|
5626
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1289 -- TODO check that it's their token I guess? |
|
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1290 elseif strict_auth_revoke then |
|
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1291 -- Why require auth to revoke a leaked token? |
|
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1292 response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); |
|
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1293 return 401; |
|
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1294 end |
|
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1295 |
|
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
1296 local form_data = strict_formdecode(event.request.body); |
|
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1297 if not form_data or not form_data.token then |
|
5267
60e0bc35de33
mod_http_oauth2: Relax payload content type checking in revocation
Kim Alvefur <zash@zash.se>
parents:
5266
diff
changeset
|
1298 response.headers.accept = "application/x-www-form-urlencoded"; |
|
60e0bc35de33
mod_http_oauth2: Relax payload content type checking in revocation
Kim Alvefur <zash@zash.se>
parents:
5266
diff
changeset
|
1299 return 415; |
|
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1300 end |
|
5682
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1301 |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1302 if credentials then |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1303 local client = check_client(credentials.username); |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1304 if not client then |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1305 return 401; |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1306 end |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1307 local token_info = tokens.get_token_info(form_data.token); |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1308 if not token_info then |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1309 return 404; |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1310 end |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1311 local token_client = token_info.grant.data.oauth2_client; |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1312 if not token_client or token_client.hash ~= client.client_hash then |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1313 return 403; |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1314 end |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1315 end |
|
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1316 |
|
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1317 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:
4340
diff
changeset
|
1318 if not ok then |
|
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1319 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:
4340
diff
changeset
|
1320 return 500; |
|
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1321 end |
|
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1322 return 200; |
|
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1323 end |
|
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1324 |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1325 local registration_schema = { |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1326 title = "OAuth 2.0 Dynamic Client Registration Protocol"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1327 description = "This endpoint allows dynamically registering an OAuth 2.0 client."; |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1328 type = "object"; |
|
5237
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1329 required = { |
|
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1330 -- 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:
5236
diff
changeset
|
1331 "client_name"; |
|
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1332 "client_uri"; |
|
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1333 }; |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1334 properties = { |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1335 redirect_uris = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1336 title = "List of Redirect URIs"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1337 type = "array"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1338 minItems = 1; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1339 uniqueItems = true; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1340 items = { |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1341 title = "Redirect URI"; |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1342 type = "string"; |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1343 format = "uri"; |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1344 examples = { |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1345 "https://app.example.com/redirect"; |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1346 "http://localhost:8080/redirect"; |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1347 "com.example.app:/redirect"; |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1348 oob_uri; |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1349 }; |
|
6280
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1350 ["not"] = { |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1351 const = device_uri; |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1352 } |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1353 }; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1354 }; |
|
5377
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1355 token_endpoint_auth_method = { |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1356 title = "Token Endpoint Authentication Method"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1357 description = "Authentication method the client intends to use. Recommended is `client_secret_basic`. \z |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1358 `none` is only allowed for use with the insecure Implicit flow."; |
|
5377
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1359 type = "string"; |
|
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1360 enum = { "none"; "client_secret_post"; "client_secret_basic" }; |
|
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1361 default = "client_secret_basic"; |
|
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1362 }; |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1363 grant_types = { |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1364 title = "Grant Types"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1365 description = "List of grant types the client intends to use."; |
|
5236
ff8623e2f9d9
mod_http_oauth2: Reorder client metadata validation schema
Kim Alvefur <zash@zash.se>
parents:
5231
diff
changeset
|
1366 type = "array"; |
|
5455
80a81e7f3c4e
mod_http_oauth2: Require non-empty arrays in client registration
Kim Alvefur <zash@zash.se>
parents:
5454
diff
changeset
|
1367 minItems = 1; |
|
5456
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1368 uniqueItems = true; |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1369 items = { |
|
5236
ff8623e2f9d9
mod_http_oauth2: Reorder client metadata validation schema
Kim Alvefur <zash@zash.se>
parents:
5231
diff
changeset
|
1370 type = "string"; |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1371 enum = { |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1372 "authorization_code"; |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1373 "implicit"; |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1374 "password"; |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1375 "client_credentials"; |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1376 "refresh_token"; |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1377 "urn:ietf:params:oauth:grant-type:jwt-bearer"; |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1378 "urn:ietf:params:oauth:grant-type:saml2-bearer"; |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1379 device_uri; |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1380 }; |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1381 }; |
|
5366
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1382 default = { "authorization_code" }; |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1383 }; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1384 application_type = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1385 title = "Application Type"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1386 description = "Determines which kinds of redirect URIs the client may register. \z |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1387 The value `web` limits the client to `https://` URLs with the same hostname as \z |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1388 in `client_uri` while the value `native` allows either loopback URLs like \z |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1389 `http://localhost:8080/` or application specific URIs like `com.example.app:/redirect`."; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1390 type = "string"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1391 enum = { "native"; "web" }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1392 default = "web"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1393 }; |
|
5456
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1394 response_types = { |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1395 title = "Response Types"; |
|
5456
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1396 type = "array"; |
|
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1397 uniqueItems = true; |
|
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1398 items = { type = "string"; enum = { "code"; "token" } }; |
|
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1399 default = { "code" }; |
|
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1400 }; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1401 client_name = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1402 title = "Client Name"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1403 description = "Human-readable name of the client, presented to the user in the consent dialog."; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1404 type = "string"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1405 }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1406 client_uri = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1407 title = "Client URL"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1408 description = "Should be an link to a page with information about the client. \z |
|
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1409 The hostname in this URL must be the same as in every other '_uri' property."; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1410 type = "string"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1411 format = "uri"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1412 pattern = "^https:"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1413 examples = { "https://app.example.com/" }; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1414 }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1415 logo_uri = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1416 title = "Logo URL"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1417 description = "URL to the clients logotype (not currently used)."; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1418 type = "string"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1419 format = "uri"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1420 pattern = "^https:"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1421 examples = { "https://app.example.com/appicon.png" }; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1422 }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1423 scope = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1424 title = "Scopes"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1425 description = "Space-separated list of scopes the client promises to restrict itself to."; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1426 type = "string"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1427 examples = { "openid xmpp" }; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1428 }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1429 contacts = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1430 title = "Contact Addresses"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1431 description = "Addresses, typically email or URLs where the client developers can be contacted."; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1432 type = "array"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1433 minItems = 1; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1434 items = { type = "string"; format = "email" }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1435 }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1436 tos_uri = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1437 title = "Terms of Service URL"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1438 description = "Link to Terms of Service for the client, presented to the user in the consent dialog. \z |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1439 MUST be a `https://` URL with hostname matching that of `client_uri`."; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1440 type = "string"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1441 format = "uri"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1442 pattern = "^https:"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1443 examples = { "https://app.example.com/tos.html" }; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1444 }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1445 policy_uri = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1446 title = "Privacy Policy URL"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1447 description = "Link to a Privacy Policy for the client. MUST be a `https://` URL with hostname matching that of `client_uri`."; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1448 type = "string"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1449 format = "uri"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1450 pattern = "^https:"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1451 examples = { "https://app.example.com/policy.pdf" }; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1452 }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1453 software_id = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1454 title = "Software ID"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1455 description = "Unique identifier for the client software, common for all instances. Typically an UUID."; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1456 type = "string"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1457 format = "uuid"; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1458 }; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1459 software_version = { |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1460 title = "Software Version"; |
|
5605
17aa3bac7f3a
mod_http_oauth2: Improve a description in schema
Kim Alvefur <zash@zash.se>
parents:
5598
diff
changeset
|
1461 description = "Version of the client software being registered. \z |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1462 E.g. to allow revoking all related tokens in the event of a security incident."; |
|
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1463 type = "string"; |
|
5797
03477980f1a9
mod_http_oauth2: Improve registration schema documentation parts
Kim Alvefur <zash@zash.se>
parents:
5796
diff
changeset
|
1464 examples = { "2.3.1" }; |
|
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1465 }; |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1466 }; |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1467 } |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1468 |
|
5554
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1469 -- Limit per-locale fields to allowed locales, partly to keep size of client_id |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1470 -- down, partly because we don't yet use them for anything. |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1471 -- Only relevant for user-visible strings and URIs. |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1472 if allowed_locales[1] then |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1473 local props = registration_schema.properties; |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1474 for _, locale in ipairs(allowed_locales) do |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1475 props["client_name#" .. locale] = props["client_name"]; |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1476 props["client_uri#" .. locale] = props["client_uri"]; |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1477 props["logo_uri#" .. locale] = props["logo_uri"]; |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1478 props["tos_uri#" .. locale] = props["tos_uri"]; |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1479 props["policy_uri#" .. locale] = props["policy_uri"]; |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1480 end |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1481 end |
|
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1482 |
|
5367
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1483 local function redirect_uri_allowed(redirect_uri, client_uri, app_type) |
|
5956
97375a78d2b5
mod_http_oauth2: Reject URLs with 'userinfo' part (thanks mimi89999)
Kim Alvefur <zash@zash.se>
parents:
5935
diff
changeset
|
1484 local uri = strict_url_parse(redirect_uri); |
|
5767
a967bb4972c5
mod_http_oauth2: Reject unparsable URLs
Kim Alvefur <zash@zash.se>
parents:
5766
diff
changeset
|
1485 if not uri then |
|
a967bb4972c5
mod_http_oauth2: Reject unparsable URLs
Kim Alvefur <zash@zash.se>
parents:
5766
diff
changeset
|
1486 return false; |
|
a967bb4972c5
mod_http_oauth2: Reject unparsable URLs
Kim Alvefur <zash@zash.se>
parents:
5766
diff
changeset
|
1487 end |
|
5457
9156a4754466
mod_http_oauth2: Reject relative redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5456
diff
changeset
|
1488 if not uri.scheme then |
|
9156a4754466
mod_http_oauth2: Reject relative redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5456
diff
changeset
|
1489 return false; -- no relative URLs |
|
9156a4754466
mod_http_oauth2: Reject relative redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5456
diff
changeset
|
1490 end |
|
5367
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1491 if app_type == "native" then |
|
5458
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
1492 return uri.scheme == "http" and loopbacks:contains(uri.host) or redirect_uri == oob_uri or uri.scheme:find(".", 1, true) ~= nil; |
|
5367
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1493 elseif app_type == "web" then |
|
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1494 return uri.scheme == "https" and uri.host == client_uri.host; |
|
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1495 end |
|
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1496 end |
|
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1497 |
|
5259
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1498 function create_client(client_metadata) |
|
5766
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1499 local valid, validation_errors = schema.validate(registration_schema, client_metadata); |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1500 if not valid then |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1501 return nil, errors.new({ |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1502 type = "modify"; |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1503 condition = "bad-request"; |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1504 code = 400; |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1505 text = "Failed schema validation."; |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1506 extra = { |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1507 oauth2_response = { |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1508 error = "invalid_request"; |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1509 error_description = "Client registration data failed schema validation."; -- TODO Generate from validation_errors? |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1510 -- JSON Schema Output Format |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1511 -- https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-01#name-basic |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1512 valid = false; |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1513 errors = validation_errors; |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1514 }; |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1515 }; |
|
b8a2b3ebe792
mod_http_oauth2: Return validation output added in trunk rev 72d7830505f0
Kim Alvefur <zash@zash.se>
parents:
5764
diff
changeset
|
1516 }); |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1517 end |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1518 |
|
5956
97375a78d2b5
mod_http_oauth2: Reject URLs with 'userinfo' part (thanks mimi89999)
Kim Alvefur <zash@zash.se>
parents:
5935
diff
changeset
|
1519 local client_uri = strict_url_parse(client_metadata.client_uri); |
|
5958
5f8a306c8306
mod_http_oauth2: Require a stringprepped host part of URLs
Kim Alvefur <zash@zash.se>
parents:
5957
diff
changeset
|
1520 if not client_uri or client_uri.scheme ~= "https" or not client_uri.host or loopbacks:contains(client_uri.host) then |
|
5633
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1521 return nil, oauth_error("invalid_client_metadata", "Missing, invalid or insecure client_uri"); |
|
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1522 end |
|
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1523 |
|
6280
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1524 if not client_metadata.application_type then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1525 if client_metadata.redirect_uris and redirect_uri_allowed(client_metadata.redirect_uris[1], client_uri, "native") then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1526 client_metadata.application_type = "native"; |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1527 elseif array_contains(client_metadata.grant_types, device_uri) then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1528 client_metadata.application_type = "native"; |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1529 end |
|
5633
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1530 end |
|
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1531 |
|
5366
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1532 -- Fill in default values |
|
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1533 for propname, propspec in pairs(registration_schema.properties) do |
|
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1534 if client_metadata[propname] == nil and type(propspec) == "table" and propspec.default ~= nil then |
|
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1535 client_metadata[propname] = propspec.default; |
|
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1536 end |
|
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1537 end |
|
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1538 |
|
5559
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1539 -- MUST ignore any metadata that it does not understand |
|
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1540 for propname in pairs(client_metadata) do |
|
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1541 if not registration_schema.properties[propname] then |
|
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1542 client_metadata[propname] = nil; |
|
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1543 end |
|
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1544 end |
|
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1545 |
|
6280
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1546 if client_metadata.redirect_uris then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1547 for _, redirect_uri in ipairs(client_metadata.redirect_uris) do |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1548 if not redirect_uri_allowed(redirect_uri, client_uri, client_metadata.application_type) then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1549 return nil, oauth_error("invalid_redirect_uri", "Invalid, insecure or inappropriate redirect URI."); |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1550 end |
|
5242
4746609a6656
mod_http_oauth2: Validate that informative URLs match the redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
1551 end |
|
4746609a6656
mod_http_oauth2: Validate that informative URLs match the redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
1552 end |
|
4746609a6656
mod_http_oauth2: Validate that informative URLs match the redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
1553 |
|
5244
fa7bd721a3f6
mod_http_oauth2: Fix validation of informative URIs
Kim Alvefur <zash@zash.se>
parents:
5243
diff
changeset
|
1554 for field, prop_schema in pairs(registration_schema.properties) do |
|
5246
fd0d25b42cd9
mod_http_oauth2: Validate all URIs against client_uri in client registration
Kim Alvefur <zash@zash.se>
parents:
5245
diff
changeset
|
1555 if field ~= "client_uri" and prop_schema.format == "uri" and client_metadata[field] then |
|
5403
c574aaaa4d57
mod_http_oauth2: Simplify validation of various URIs
Kim Alvefur <zash@zash.se>
parents:
5402
diff
changeset
|
1556 if not redirect_uri_allowed(client_metadata[field], client_uri, "web") then |
|
c574aaaa4d57
mod_http_oauth2: Simplify validation of various URIs
Kim Alvefur <zash@zash.se>
parents:
5402
diff
changeset
|
1557 return nil, oauth_error("invalid_client_metadata", "Invalid, insecure or inappropriate informative URI"); |
|
5242
4746609a6656
mod_http_oauth2: Validate that informative URLs match the redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
1558 end |
|
5239
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5237
diff
changeset
|
1559 end |
|
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5237
diff
changeset
|
1560 end |
|
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5237
diff
changeset
|
1561 |
|
5406
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1562 local grant_types = set.new(client_metadata.grant_types); |
|
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1563 local response_types = set.new(client_metadata.response_types); |
|
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1564 |
|
6243
5b269511ade7
mod_http_oauth2: Forbid inclusion of disabled grant and response types
Kim Alvefur <zash@zash.se>
parents:
6242
diff
changeset
|
1565 if not (grant_types - allowed_grant_type_handlers):empty() then |
|
5b269511ade7
mod_http_oauth2: Forbid inclusion of disabled grant and response types
Kim Alvefur <zash@zash.se>
parents:
6242
diff
changeset
|
1566 return nil, oauth_error("invalid_client_metadata", "Disallowed 'grant_types' specified"); |
|
5b269511ade7
mod_http_oauth2: Forbid inclusion of disabled grant and response types
Kim Alvefur <zash@zash.se>
parents:
6242
diff
changeset
|
1567 elseif not (response_types - allowed_response_type_handlers):empty() then |
|
5b269511ade7
mod_http_oauth2: Forbid inclusion of disabled grant and response types
Kim Alvefur <zash@zash.se>
parents:
6242
diff
changeset
|
1568 return nil, oauth_error("invalid_client_metadata", "Disallowed 'response_types' specified"); |
|
5b269511ade7
mod_http_oauth2: Forbid inclusion of disabled grant and response types
Kim Alvefur <zash@zash.se>
parents:
6242
diff
changeset
|
1569 end |
|
5b269511ade7
mod_http_oauth2: Forbid inclusion of disabled grant and response types
Kim Alvefur <zash@zash.se>
parents:
6242
diff
changeset
|
1570 |
|
6280
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1571 |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1572 if not client_metadata.redirect_uris then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1573 if grant_types:contains("authorization_code") then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1574 return nil, oauth_error("invalid_client_metadata", "The 'authorization_code' grant requires 'redirect_uris' to be present."); |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1575 elseif grant_types:contains("implicit") then |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1576 return nil, oauth_error("invalid_client_metadata", "The 'implicit' grant requires 'redirect_uris' to be present."); |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1577 end |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1578 end |
|
6ea80b73d8f2
mod_http_oauth2: Only require redirect URIs when using grant types that need it
Kim Alvefur <zash@zash.se>
parents:
6279
diff
changeset
|
1579 |
|
5406
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1580 if grant_types:contains("authorization_code") and not response_types:contains("code") then |
|
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1581 return nil, oauth_error("invalid_client_metadata", "Inconsistency between 'grant_types' and 'response_types'"); |
|
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1582 elseif grant_types:contains("implicit") and not response_types:contains("token") then |
|
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1583 return nil, oauth_error("invalid_client_metadata", "Inconsistency between 'grant_types' and 'response_types'"); |
|
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1584 end |
|
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1585 |
|
5770
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1586 if client_metadata.token_endpoint_auth_method ~= "none" then |
|
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1587 -- Ensure that each client_id JWT with a client_secret is unique. |
|
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1588 -- A short ID along with the issued at timestamp should be sufficient to |
|
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1589 -- rule out brute force attacks. |
|
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1590 -- Not needed for public clients without a secret, but those are expected |
|
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1591 -- to be uncommon since they can only do the insecure implicit flow. |
|
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1592 client_metadata.nonce = id.short(); |
|
6281
17d9533f7596
mod_http_oauth2: Reject invalid attempt to register client without credentials
Kim Alvefur <zash@zash.se>
parents:
6280
diff
changeset
|
1593 elseif grant_types ~= set.new({ "implicit" }) then |
|
17d9533f7596
mod_http_oauth2: Reject invalid attempt to register client without credentials
Kim Alvefur <zash@zash.se>
parents:
6280
diff
changeset
|
1594 return nil, oauth_error("invalid_client_metadata", "A 'token_endpoint_auth_method' value of 'none' only works with the 'implicit' grant"); |
|
5770
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1595 end |
|
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1596 |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1597 -- Do we want to keep everything? |
|
5459
260a859be86a
mod_http_oauth2: Rename variables to improve clarity
Kim Alvefur <zash@zash.se>
parents:
5458
diff
changeset
|
1598 local client_id = sign_client(client_metadata); |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1599 |
|
5221
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5219
diff
changeset
|
1600 client_metadata.client_id = client_id; |
|
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5219
diff
changeset
|
1601 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:
5219
diff
changeset
|
1602 |
|
5407
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1603 if client_metadata.token_endpoint_auth_method ~= "none" then |
|
5770
990c6adc4407
mod_http_oauth2: Move some code earlier
Kim Alvefur <zash@zash.se>
parents:
5767
diff
changeset
|
1604 local client_secret = make_client_secret(client_id); |
|
5407
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1605 client_metadata.client_secret = client_secret; |
|
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1606 client_metadata.client_secret_expires_at = 0; |
|
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1607 |
|
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1608 if not registration_options.accept_expired then |
|
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1609 client_metadata.client_secret_expires_at = client_metadata.client_id_issued_at + (registration_options.default_ttl or 3600); |
|
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1610 end |
|
5202
b81fd0d22c66
mod_http_oauth2: Calculate client secret expiry in registration response
Kim Alvefur <zash@zash.se>
parents:
5201
diff
changeset
|
1611 end |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1612 |
|
5259
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1613 return client_metadata; |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1614 end |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1615 |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1616 local function handle_register_request(event) |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1617 local request = event.request; |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1618 local client_metadata, err = json.decode(request.body); |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1619 if err then |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1620 return oauth_error("invalid_request", "Invalid JSON"); |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1621 end |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1622 |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1623 local response, err = create_client(client_metadata); |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1624 if err then return err end |
|
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1625 |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1626 return { |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1627 status_code = 201; |
|
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1628 headers = { |
|
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1629 cache_control = "no-store"; |
|
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1630 pragma = "no-cache"; |
|
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1631 content_type = "application/json"; |
|
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1632 }; |
|
5259
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1633 body = json.encode(response); |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1634 }; |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1635 end |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1636 |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1637 if not registration_key then |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1638 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:
5192
diff
changeset
|
1639 handle_authorization_request = nil |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1640 handle_register_request = nil |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1641 handle_device_authorization_request = nil |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1642 handle_device_verification_request = nil |
|
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1643 end |
|
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1644 |
|
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1645 local function handle_userinfo_request(event) |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1646 local request = event.request; |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1647 local credentials = get_request_credentials(request); |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1648 if not credentials or not credentials.bearer_token then |
|
5336
77ac04bd2f65
mod_http_oauth2: Add some debug logging for UserInfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5335
diff
changeset
|
1649 module:log("debug", "Missing credentials for UserInfo endpoint: %q", credentials) |
|
5335
53c6f49dcbb8
mod_http_oauth2: Correct error code when missing credentials for userinfo
Kim Alvefur <zash@zash.se>
parents:
5280
diff
changeset
|
1650 return 401; |
|
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1651 end |
|
5336
77ac04bd2f65
mod_http_oauth2: Add some debug logging for UserInfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5335
diff
changeset
|
1652 local token_info,err = tokens.get_token_info(credentials.bearer_token); |
|
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1653 if not token_info then |
|
5336
77ac04bd2f65
mod_http_oauth2: Add some debug logging for UserInfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5335
diff
changeset
|
1654 module:log("debug", "UserInfo query failed token validation: %s", err) |
|
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1655 return 403; |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1656 end |
|
5337
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1657 local scopes = set.new() |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1658 if type(token_info.grant.data) == "table" and type(token_info.grant.data.oauth2_scopes) == "string" then |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1659 scopes:add_list(parse_scopes(token_info.grant.data.oauth2_scopes)); |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1660 else |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1661 module:log("debug", "token_info = %q", token_info) |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1662 end |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1663 |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1664 if not scopes:contains("openid") then |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1665 module:log("debug", "Missing the 'openid' scope in %q", scopes) |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1666 -- The 'openid' scope is required for access to this endpoint. |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1667 return 403; |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1668 end |
|
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1669 |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1670 local user_info = { |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1671 iss = get_issuer(); |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1672 sub = url.build({ scheme = "xmpp"; path = token_info.jid }); |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1673 } |
|
5337
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1674 |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1675 local token_claims = set.intersection(openid_claims, scopes); |
|
5375
8b7d97f0ae8a
mod_http_oauth2: Fix to include "openid" scope in discovery metadata
Kim Alvefur <zash@zash.se>
parents:
5367
diff
changeset
|
1676 token_claims:remove("openid"); -- that's "iss" and "sub" above |
|
5337
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1677 if not token_claims:empty() then |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1678 -- Another module can do that |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1679 module:fire_event("token/userinfo", { |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1680 token = token_info; |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1681 claims = token_claims; |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1682 username = jid.split(token_info.jid); |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1683 userinfo = user_info; |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1684 }); |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1685 end |
|
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1686 |
|
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1687 return { |
|
5258
9629971e307f
mod_http_oauth2: Fix userinfo status code off-by-one
Kim Alvefur <zash@zash.se>
parents:
5257
diff
changeset
|
1688 status_code = 200; |
|
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1689 headers = { content_type = "application/json" }; |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1690 body = json.encode(user_info); |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1691 }; |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1692 end |
|
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1693 |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1694 module:depends("http"); |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1695 module:provides("http", { |
|
5480
5108f63e762b
mod_http_oauth2: Allow CORS for browser clients
Kim Alvefur <zash@zash.se>
parents:
5479
diff
changeset
|
1696 cors = { enabled = true; credentials = true }; |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1697 route = { |
|
5382
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1698 -- OAuth 2.0 in 5 simple steps! |
|
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1699 -- This is the normal 'authorization_code' flow. |
|
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1700 |
|
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1701 -- Step 1. Create OAuth client |
|
6179
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1702 ["GET /register"] = { headers = { content_type = "application/schema+json" }; body = json.encode(registration_schema) }; |
|
5382
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1703 ["POST /register"] = handle_register_request; |
|
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1704 |
|
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1705 -- Device flow |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1706 ["POST /device"] = handle_device_authorization_request; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1707 ["GET /device"] = handle_device_verification_request; |
|
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1708 |
|
5382
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1709 -- Step 2. User-facing login and consent view |
|
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
1710 ["GET /authorize"] = handle_authorization_request; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1711 ["POST /authorize"] = handle_authorization_request; |
|
5548
fd3c12c40cd9
mod_http_oauth2: Disable CORS for authorization endpoint
Kim Alvefur <zash@zash.se>
parents:
5547
diff
changeset
|
1712 ["OPTIONS /authorize"] = { status_code = 403; body = "" }; |
|
5245
e22cae58141d
mod_http_oauth2: Organize HTTP routes with comments
Kim Alvefur <zash@zash.se>
parents:
5244
diff
changeset
|
1713 |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1714 -- Optional static content for templates |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1715 ["GET /style.css"] = templates.css and { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1716 headers = { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1717 ["Content-Type"] = "text/css"; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1718 }; |
|
5642
7c105277a9ca
mod_http_oauth2: Remove broken in-CSS templating
Kim Alvefur <zash@zash.se>
parents:
5633
diff
changeset
|
1719 body = templates.css; |
|
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1720 } or nil; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1721 ["GET /script.js"] = templates.js and { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1722 headers = { |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1723 ["Content-Type"] = "text/javascript"; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1724 }; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1725 body = templates.js; |
|
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1726 } or nil; |
|
5393
9b9d612f9083
mod_http_oauth2: Add way to retrieve registration schema
Kim Alvefur <zash@zash.se>
parents:
5392
diff
changeset
|
1727 |
|
6179
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1728 -- Step 3. User is redirected to the 'redirect_uri' along with an |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1729 -- authorization code. In the insecure 'implicit' flow, the access token |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1730 -- is delivered here. |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1731 |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1732 -- Step 4. Retrieve access token using the code. |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1733 ["POST /token"] = handle_token_grant; |
|
5396
ac7c5669e5f5
mod_http_oauth2: Return status 405 for GET to endpoints without GET handler
Kim Alvefur <zash@zash.se>
parents:
5394
diff
changeset
|
1734 ["GET /token"] = function() return 405; end; |
|
6179
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1735 |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1736 -- Step 4 is later repeated using the refresh token to get new access tokens. |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1737 |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1738 -- Get info about a token |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1739 ["POST /introspect"] = handle_introspection_request; |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1740 ["GET /introspect"] = function() return 405; end; |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1741 |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1742 -- Get info about the user, used for OpenID Connect |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1743 ["GET /userinfo"] = handle_userinfo_request; |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1744 |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1745 -- Step 5. Revoke token (access or refresh) |
|
a1a33f0f6f6e
mod_http_oauth2: Reorder HTTP handler (noop)
Kim Alvefur <zash@zash.se>
parents:
6009
diff
changeset
|
1746 ["POST /revoke"] = handle_revocation_request; |
|
5396
ac7c5669e5f5
mod_http_oauth2: Return status 405 for GET to endpoints without GET handler
Kim Alvefur <zash@zash.se>
parents:
5394
diff
changeset
|
1747 ["GET /revoke"] = function() return 405; end; |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1748 }; |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1749 }); |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1750 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1751 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
|
1752 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1753 module:hook_object_event(http_server, "http-error", function (event) |
|
4276
ec33b3b1136c
mod_http_oauth2: Fix passing OAuth-specific error details
Kim Alvefur <zash@zash.se>
parents:
4272
diff
changeset
|
1754 local oauth2_response = event.error and event.error.extra and event.error.extra.oauth2_response; |
|
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1755 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
|
1756 return; |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1757 end |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1758 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
|
1759 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
|
1760 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
|
1761 end, 5); |
|
5189
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1762 |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1763 -- OIDC Discovery |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1764 |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1765 function get_authorization_server_metadata() |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1766 if authorization_server_metadata then |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1767 return authorization_server_metadata; |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1768 end |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1769 authorization_server_metadata = { |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1770 -- RFC 8414: OAuth 2.0 Authorization Server Metadata |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1771 issuer = get_issuer(); |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1772 authorization_endpoint = handle_authorization_request and module:http_url() .. "/authorize" or nil; |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1773 token_endpoint = handle_token_grant and module:http_url() .. "/token" or nil; |
|
6247
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1774 jwks_uri = nil; -- REQUIRED in OpenID Discovery but not in OAuth 2.0 Metadata |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1775 registration_endpoint = handle_register_request and module:http_url() .. "/register" or nil; |
|
6274
63ef69b2f046
mod_http_oauth2: Assume Prosody 13.0+ roles are available
Kim Alvefur <zash@zash.se>
parents:
6273
diff
changeset
|
1776 scopes_supported = array({ "xmpp" }):append(array(it.keys(usermanager.get_all_roles(module.host)))):append(array(openid_claims:items())); |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1777 response_types_supported = array(it.keys(response_type_handlers)); |
|
6247
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1778 response_modes_supported = array(it.keys(response_type_handlers)):map(tmap { token = "fragment"; code = "query" }); |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1779 grant_types_supported = array(it.keys(grant_type_handlers)); |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1780 token_endpoint_auth_methods_supported = array({ "client_secret_basic"; "client_secret_post"; "none" }); |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1781 token_endpoint_auth_signing_alg_values_supported = nil; |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1782 service_documentation = module:get_option_string("oauth2_service_documentation", "https://modules.prosody.im/mod_http_oauth2.html"); |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1783 ui_locales_supported = allowed_locales[1] and allowed_locales; |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1784 op_policy_uri = module:get_option_string("oauth2_policy_url", nil); |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1785 op_tos_uri = module:get_option_string("oauth2_terms_url", nil); |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1786 revocation_endpoint = handle_revocation_request and module:http_url() .. "/revoke" or nil; |
|
6247
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1787 revocation_endpoint_auth_methods_supported = array({ "client_secret_basic"; "client_secret_post"; "none" }); |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1788 revocation_endpoint_auth_signing_alg_values_supported = nil; |
|
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1789 introspection_endpoint = handle_introspection_request and module:http_url() .. "/introspect"; |
|
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1790 introspection_endpoint_auth_methods_supported = nil; |
|
6247
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1791 introspection_endpoint_auth_signing_alg_values_supported = nil; |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1792 code_challenge_methods_supported = array(it.keys(verifier_transforms)); |
|
6247
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1793 |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1794 -- RFC 8628: OAuth 2.0 Device Authorization Grant |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1795 device_authorization_endpoint = handle_device_authorization_request and module:http_url() .. "/device"; |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1796 |
|
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1797 -- RFC 9207: OAuth 2.0 Authorization Server Issuer Identification |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1798 authorization_response_iss_parameter_supported = true; |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1799 |
|
6247
7cf1fcac9b94
mod_http_oauth2: Reorder metadata by source
Kim Alvefur <zash@zash.se>
parents:
6245
diff
changeset
|
1800 -- OpenID Connect Discovery 1.0 |
|
6009
277ccafb4826
mod_http_oauth2: Fix check for userinfo endpoint handler
Kim Alvefur <zash@zash.se>
parents:
5961
diff
changeset
|
1801 userinfo_endpoint = handle_userinfo_request and module:http_url() .. "/userinfo" or nil; |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1802 id_token_signing_alg_values_supported = { "HS256" }; -- The algorithm RS256 MUST be included, but we use HS256 and client_secret as shared key. |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1803 } |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1804 return authorization_server_metadata; |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1805 end |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1806 |
|
5189
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1807 module:provides("http", { |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1808 name = "oauth2-discovery"; |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1809 default_path = "/.well-known/oauth-authorization-server"; |
|
5480
5108f63e762b
mod_http_oauth2: Allow CORS for browser clients
Kim Alvefur <zash@zash.se>
parents:
5479
diff
changeset
|
1810 cors = { enabled = true }; |
|
5189
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1811 route = { |
|
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1812 ["GET"] = function() |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1813 return { |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1814 headers = { content_type = "application/json" }; |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1815 body = json.encode(get_authorization_server_metadata()); |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1816 } |
|
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1817 end |
|
5189
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1818 }; |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1819 }); |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1820 |
|
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1821 module:shared("tokenauth/oauthbearer_config").oidc_discovery_url = module:http_url("oauth2-discovery", "/.well-known/oauth-authorization-server"); |
