webmcp

annotate framework/env/auth/openid/verify.lua @ 562:328f120924a2

Removed if-clause when initializing file descriptor set to avoid compiler warning for mondelefant_conn_try_wait
author jbe
date Fri Feb 05 15:51:39 2021 +0100 (2021-02-05)
parents b66d446226af
children
rev   line source
jbe/bsw@20 1 --[[--
jbe@362 2 claimed_identifier, -- identifier owned by the user
jbe@362 3 errmsg, -- error message in case of failure
jbe@362 4 errcode = -- error code in case of failure (TODO: not implemented yet)
jbe@362 5 auth.openid.verify{
jbe@362 6 force_https = force_https, -- only allow https
jbe@362 7 curl_options = curl_options -- options passed to "curl" binary, when performing discovery
jbe@362 8 }
jbe/bsw@20 9
jbe/bsw@20 10 --]]--
jbe/bsw@20 11
jbe/bsw@20 12 function auth.openid.verify(args)
jbe/bsw@20 13 local args = args or {}
jbe@223 14 if request.get_param{name="openid.ns"} ~= "http://specs.openid.net/auth/2.0" then
jbe/bsw@20 15 return nil, "No indirect OpenID 2.0 message received."
jbe/bsw@20 16 end
jbe@223 17 local mode = request.get_param{name="openid.mode"}
jbe/bsw@20 18 if mode == "id_res" then
jbe@223 19 local return_to_url = request.get_param{name="openid.return_to"}
jbe/bsw@20 20 if not return_to_url then
jbe/bsw@20 21 return nil, "No return_to URL received in answer."
jbe/bsw@20 22 end
jbe/bsw@20 23 if return_to_url ~= encode.url{
jbe/bsw@20 24 base = request.get_absolute_baseurl(),
jbe/bsw@20 25 module = request.get_module(),
jbe/bsw@20 26 view = request.get_view()
jbe/bsw@20 27 } then
jbe/bsw@20 28 return nil, "return_to URL not matching."
jbe/bsw@20 29 end
jbe/bsw@20 30 local discovery_args = table.new(args)
jbe@223 31 local claimed_identifier = request.get_param{name="openid.claimed_id"}
jbe/bsw@20 32 if not claimed_identifier then
jbe/bsw@20 33 return nil, "No claimed identifier received."
jbe/bsw@20 34 end
jbe/bsw@20 35 local cropped_identifier = string.match(claimed_identifier, "[^#]*")
jbe/bsw@20 36 local normalized_identifier = auth.openid._normalize_url(
jbe/bsw@20 37 cropped_identifier
jbe/bsw@20 38 )
jbe/bsw@20 39 if not normalized_identifier then
jbe/bsw@20 40 return nil, "Claimed identifier could not be normalized."
jbe/bsw@20 41 end
jbe/bsw@20 42 if normalized_identifier ~= cropped_identifier then
jbe/bsw@20 43 return nil, "Claimed identifier was not normalized."
jbe/bsw@20 44 end
jbe/bsw@20 45 discovery_args.user_supplied_identifier = cropped_identifier
jbe/bsw@20 46 local dd, errmsg, errcode = auth.openid.discover(discovery_args)
jbe/bsw@20 47 if not dd then
jbe/bsw@20 48 return nil, errmsg, errcode
jbe/bsw@20 49 end
jbe/bsw@20 50 if not dd.claimed_identifier then
jbe/bsw@20 51 return nil, "Identifier is an OpenID Provider."
jbe/bsw@20 52 end
jbe/bsw@20 53 if dd.claimed_identifier ~= cropped_identifier then
jbe/bsw@20 54 return nil, "Claimed identifier does not match."
jbe/bsw@20 55 end
jbe@223 56 local nonce = request.get_param{name="openid.response_nonce"}
jbe/bsw@20 57 if not nonce then
jbe/bsw@20 58 return nil, "Did not receive a response nonce."
jbe/bsw@20 59 end
jbe/bsw@20 60 local year, month, day, hour, minute, second = string.match(
jbe/bsw@20 61 nonce,
jbe/bsw@20 62 "^([0-9][0-9][0-9][0-9])%-([0-9][0-9])%-([0-9][0-9])T([0-9][0-9]):([0-9][0-9]):([0-9][0-9])Z"
jbe/bsw@20 63 )
jbe/bsw@20 64 if not year then
jbe/bsw@20 65 return nil, "Response nonce did not contain a parsable date/time."
jbe/bsw@20 66 end
jbe/bsw@20 67 local ts = atom.timestamp{
jbe/bsw@20 68 year = tonumber(year),
jbe/bsw@20 69 month = tonumber(month),
jbe/bsw@20 70 day = tonumber(day),
jbe/bsw@20 71 hour = tonumber(hour),
jbe/bsw@20 72 minute = tonumber(minute),
jbe/bsw@20 73 second = tonumber(second)
jbe/bsw@20 74 }
jbe/bsw@20 75 -- NOTE: 50 hours margin allows us to ignore time zone issues here:
jbe/bsw@20 76 if math.abs(ts - atom.timestamp:get_current()) > 3600 * 50 then
jbe/bsw@20 77 return nil, "Response nonce contains wrong time or local time is wrong."
jbe/bsw@20 78 end
jbe/bsw@20 79 local params = {}
jbe/bsw@20 80 for key, value in pairs(cgi.params) do
jbe/bsw@20 81 local trimmed_key = string.match(key, "^openid%.(.+)")
jbe/bsw@20 82 if trimmed_key then
jbe/bsw@20 83 params[key] = value
jbe/bsw@20 84 end
jbe/bsw@20 85 end
jbe/bsw@20 86 params["openid.mode"] = "check_authentication"
jbe/bsw@20 87 local options = table.new(args.curl_options)
jbe/bsw@20 88 for key, value in pairs(params) do
jbe/bsw@20 89 options[#options+1] = "--data-urlencode"
jbe/bsw@20 90 options[#options+1] = key .. "=" .. value
jbe/bsw@20 91 end
jbe/bsw@20 92 local status, headers, body = auth.openid._curl(dd.op_endpoint, options)
jbe/bsw@20 93 if status ~= 200 then
jbe/bsw@20 94 return nil, "Authorization could not be verified."
jbe/bsw@20 95 end
jbe/bsw@20 96 local result = {}
jbe/bsw@20 97 for key, value in string.gmatch(body, "([^\n:]+):([^\n]*)") do
jbe/bsw@20 98 result[key] = value
jbe/bsw@20 99 end
jbe/bsw@20 100 if result.ns ~= "http://specs.openid.net/auth/2.0" then
jbe/bsw@20 101 return nil, "No OpenID 2.0 message replied."
jbe/bsw@20 102 end
jbe/bsw@20 103 if result.is_valid == "true" then
jbe/bsw@20 104 return claimed_identifier
jbe/bsw@20 105 else
jbe/bsw@20 106 return nil, "Signature invalid."
jbe/bsw@20 107 end
jbe/bsw@20 108 elseif mode == "cancel" then
jbe/bsw@20 109 return nil, "Authorization failed according to OpenID provider."
jbe/bsw@20 110 else
jbe/bsw@20 111 return nil, "Unexpected OpenID mode."
jbe/bsw@20 112 end
jbe/bsw@20 113 end

Impressum / About Us