webmcp
annotate framework/env/auth/openid/verify.lua @ 506:83b3882dc31b
New functions moonhash.shake128(data, len, alphabet), moonhash.shake256(data, len, alphabet)
Removed moonhash.shake128_128(...)
Removed moonhash.shake128_128(...)
| author | jbe | 
|---|---|
| date | Wed Aug 16 00:31:11 2017 +0200 (2017-08-16) | 
| 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 |