webmcp
annotate framework/env/auth/openid/verify.lua @ 33:fc98e5c6bfab
add missing debug_table
trace.debug_table prints a table into the log.
trace.debug_table prints a table into the log.
author | Daniel Poelzleithner <poelzi@poelzi.org> |
---|---|
date | Tue Oct 05 05:19:47 2010 +0200 (2010-10-05) |
parents | 47ddf0f86009 |
children | 32ec28229bb5 |
rev | line source |
---|---|
jbe/bsw@20 | 1 --[[-- |
jbe/bsw@20 | 2 claimed_identifier, -- identifier owned by the user |
jbe/bsw@20 | 3 errmsg, -- error message in case of failure |
jbe/bsw@20 | 4 errcode = -- error code in case of failure (TODO: not implemented yet) |
jbe/bsw@20 | 5 auth.openid.verify( |
jbe/bsw@20 | 6 force_https = force_https, -- only allow https |
jbe/bsw@20 | 7 curl_options = curl_options -- options passed to "curl" binary, when performing discovery |
jbe/bsw@20 | 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/bsw@20 | 14 if cgi.params["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/bsw@20 | 17 local mode = cgi.params["openid.mode"] |
jbe/bsw@20 | 18 if mode == "id_res" then |
jbe/bsw@20 | 19 local return_to_url = cgi.params["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/bsw@20 | 31 local claimed_identifier = cgi.params["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/bsw@20 | 56 local nonce = cgi.params["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 |