Mercurial > openid
diff 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 |
line wrap: on
line diff
--- a/src/ur/openid.ur Sun Dec 26 15:11:23 2010 -0500 +++ b/src/ur/openid.ur Sun Dec 26 17:19:52 2010 -0500 @@ -10,35 +10,61 @@ OpenidFfi.addInput is "openid.ns" "http://specs.openid.net/auth/2.0"; return is -table associations : { Endpoint : string, Secret : string, Expires : time } +table associations : { Endpoint : string, Handle : string, Key : string, Expires : time } PRIMARY KEY Endpoint -task periodic 0 = fn () => dml (DELETE FROM associations WHERE Expires < CURRENT_TIMESTAMP) +task periodic 1 = fn () => dml (DELETE FROM associations WHERE Expires < CURRENT_TIMESTAMP) -datatype association = Handle of string | Error of string +datatype association = Association of {Handle : string, Key : string} | AssError of string fun association url = - secret <- oneOrNoRowsE1 (SELECT (associations.Secret) + secret <- oneOrNoRows1 (SELECT associations.Handle, associations.Key FROM associations WHERE associations.Endpoint = {[url]}); case secret of - Some v => return (Handle v) + Some r => return (Association r) | None => is <- createInputs; OpenidFfi.addInput is "openid.mode" "associate"; OpenidFfi.addInput is "openid.assoc_type" "HMAC-SHA256"; OpenidFfi.addInput is "openid.session_type" "no-encryption"; - os <- OpenidFfi.indirect url is; + + os <- OpenidFfi.direct url is; case OpenidFfi.getOutput os "error" of - Some v => return (Error v) + Some v => return (AssError v) | None => - case (OpenidFfi.getOutput os "assoc_handle", OpenidFfi.getOutput os "expires_in") of - (Some handle, Some expires) => + case (OpenidFfi.getOutput os "assoc_handle", OpenidFfi.getOutput os "mac_key", OpenidFfi.getOutput os "expires_in") of + (Some handle, Some key, Some expires) => (case read expires of - None => return (Error "Invalid 'expires_in' field") + None => return (AssError "Invalid 'expires_in' field") | Some expires => tm <- now; - dml (INSERT INTO associations (Endpoint, Secret, Expires) - VALUES ({[url]}, {[handle]}, {[addSeconds tm expires]})); - return (Handle handle)) - | _ => return (Error "Missing fields in response from OP") + dml (INSERT INTO associations (Endpoint, Handle, Key, Expires) + VALUES ({[url]}, {[handle]}, {[key]}, {[addSeconds tm expires]})); + return (Association {Handle = handle, Key = key})) + | _ => return (AssError "Missing fields in response from OP") + +fun returnTo (qs : option queryString) = + case qs of + None => error <xml>Empty query string for OpenID callback</xml> + | Some qs => + os <- OpenidFfi.indirect qs; + case OpenidFfi.getOutput os "openid.error" of + Some v => error <xml>Authentication failed: {[v]}</xml> + | None => + case OpenidFfi.getOutput os "openid.identity" of + None => error <xml>Missing identity in OP response</xml> + | Some v => return <xml>Identity: {[v]}</xml> + +fun authenticate id = + dy <- discover id; + case dy of + None => return "Discovery failed" + | Some dy => + assoc <- association dy.Endpoint; + case assoc of + AssError msg => return msg + | Association assoc => + redirect (bless (dy.Endpoint ^ "?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=checkid_setup&openid.claimed_id=" + ^ id ^ "&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.assoc_handle=" + ^ assoc.Handle ^ "&openid.return_to=" ^ show (effectfulUrl returnTo)))