Mercurial > openid
comparison src/ur/openid.ur @ 4:2d409aff8800
Received an OpenID authentication response, but haven't checked it yet
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Sun, 26 Dec 2010 17:19:52 -0500 |
parents | f59083771ee2 |
children | 443f27cd1572 |
comparison
equal
deleted
inserted
replaced
3:f59083771ee2 | 4:2d409aff8800 |
---|---|
8 val createInputs = | 8 val createInputs = |
9 is <- OpenidFfi.createInputs; | 9 is <- OpenidFfi.createInputs; |
10 OpenidFfi.addInput is "openid.ns" "http://specs.openid.net/auth/2.0"; | 10 OpenidFfi.addInput is "openid.ns" "http://specs.openid.net/auth/2.0"; |
11 return is | 11 return is |
12 | 12 |
13 table associations : { Endpoint : string, Secret : string, Expires : time } | 13 table associations : { Endpoint : string, Handle : string, Key : string, Expires : time } |
14 PRIMARY KEY Endpoint | 14 PRIMARY KEY Endpoint |
15 | 15 |
16 task periodic 0 = fn () => dml (DELETE FROM associations WHERE Expires < CURRENT_TIMESTAMP) | 16 task periodic 1 = fn () => dml (DELETE FROM associations WHERE Expires < CURRENT_TIMESTAMP) |
17 | 17 |
18 datatype association = Handle of string | Error of string | 18 datatype association = Association of {Handle : string, Key : string} | AssError of string |
19 | 19 |
20 fun association url = | 20 fun association url = |
21 secret <- oneOrNoRowsE1 (SELECT (associations.Secret) | 21 secret <- oneOrNoRows1 (SELECT associations.Handle, associations.Key |
22 FROM associations | 22 FROM associations |
23 WHERE associations.Endpoint = {[url]}); | 23 WHERE associations.Endpoint = {[url]}); |
24 case secret of | 24 case secret of |
25 Some v => return (Handle v) | 25 Some r => return (Association r) |
26 | None => | 26 | None => |
27 is <- createInputs; | 27 is <- createInputs; |
28 OpenidFfi.addInput is "openid.mode" "associate"; | 28 OpenidFfi.addInput is "openid.mode" "associate"; |
29 OpenidFfi.addInput is "openid.assoc_type" "HMAC-SHA256"; | 29 OpenidFfi.addInput is "openid.assoc_type" "HMAC-SHA256"; |
30 OpenidFfi.addInput is "openid.session_type" "no-encryption"; | 30 OpenidFfi.addInput is "openid.session_type" "no-encryption"; |
31 os <- OpenidFfi.indirect url is; | 31 |
32 os <- OpenidFfi.direct url is; | |
32 case OpenidFfi.getOutput os "error" of | 33 case OpenidFfi.getOutput os "error" of |
33 Some v => return (Error v) | 34 Some v => return (AssError v) |
34 | None => | 35 | None => |
35 case (OpenidFfi.getOutput os "assoc_handle", OpenidFfi.getOutput os "expires_in") of | 36 case (OpenidFfi.getOutput os "assoc_handle", OpenidFfi.getOutput os "mac_key", OpenidFfi.getOutput os "expires_in") of |
36 (Some handle, Some expires) => | 37 (Some handle, Some key, Some expires) => |
37 (case read expires of | 38 (case read expires of |
38 None => return (Error "Invalid 'expires_in' field") | 39 None => return (AssError "Invalid 'expires_in' field") |
39 | Some expires => | 40 | Some expires => |
40 tm <- now; | 41 tm <- now; |
41 dml (INSERT INTO associations (Endpoint, Secret, Expires) | 42 dml (INSERT INTO associations (Endpoint, Handle, Key, Expires) |
42 VALUES ({[url]}, {[handle]}, {[addSeconds tm expires]})); | 43 VALUES ({[url]}, {[handle]}, {[key]}, {[addSeconds tm expires]})); |
43 return (Handle handle)) | 44 return (Association {Handle = handle, Key = key})) |
44 | _ => return (Error "Missing fields in response from OP") | 45 | _ => return (AssError "Missing fields in response from OP") |
46 | |
47 fun returnTo (qs : option queryString) = | |
48 case qs of | |
49 None => error <xml>Empty query string for OpenID callback</xml> | |
50 | Some qs => | |
51 os <- OpenidFfi.indirect qs; | |
52 case OpenidFfi.getOutput os "openid.error" of | |
53 Some v => error <xml>Authentication failed: {[v]}</xml> | |
54 | None => | |
55 case OpenidFfi.getOutput os "openid.identity" of | |
56 None => error <xml>Missing identity in OP response</xml> | |
57 | Some v => return <xml>Identity: {[v]}</xml> | |
58 | |
59 fun authenticate id = | |
60 dy <- discover id; | |
61 case dy of | |
62 None => return "Discovery failed" | |
63 | Some dy => | |
64 assoc <- association dy.Endpoint; | |
65 case assoc of | |
66 AssError msg => return msg | |
67 | Association assoc => | |
68 redirect (bless (dy.Endpoint ^ "?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=checkid_setup&openid.claimed_id=" | |
69 ^ id ^ "&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.assoc_handle=" | |
70 ^ assoc.Handle ^ "&openid.return_to=" ^ show (effectfulUrl returnTo))) |