From avodonosov at yandex.ru Wed Jul 9 21:10:23 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Thu, 10 Jul 2008 00:10:23 +0300 Subject: [cl-openid-devel] no need for storage backend Message-ID: <1647089707.20080710001023@yandex.ru> Hello Maciek. I've just realized that we do not need any storage backend. There is nothing to store - in memory hash map is sufficient for associations; as for user accounts, we are not going to manage them in the OpenID Provider side, we only provide protocol to communicate with Relying Party. What do you think? Best regards, - Anton From avodonosov at yandex.ru Wed Jul 9 21:21:08 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Thu, 10 Jul 2008 00:21:08 +0300 Subject: [cl-openid-devel] meaning of immediate authentication request Message-ID: <776160191.20080710002108@yandex.ru> Hello Maciek. What I do not understand from the spec is immediate authentication requests. Could you explain me? How could OpenID Provider return positive authentication reply in response to a query containing essentially just a user name without any password, etc? What is a real word scenario for this? Best regards, - Anton From maciej at pasternacki.net Wed Jul 9 21:38:45 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Wed, 09 Jul 2008 23:38:45 +0200 Subject: [cl-openid-devel] Re: no need for storage backend In-Reply-To: <1647089707.20080710001023@yandex.ru> References: <1647089707.20080710001023@yandex.ru> Message-ID: <1215639526.10126.51.camel@localhost> Hello, On Thu, 2008-07-10 at 00:10 +0300, Anton Vodonosov wrote: > I've just realized that we do not need any storage > backend. There is nothing to store - in memory hash > map is sufficient for associations; as for user accounts, > we are not going to manage them in the OpenID Provider > side, we only provide protocol to communicate with > Relying Party. > > What do you think? As far as the user wants to run OpenID server on a single machine, you're right. However, for horizontal scaling, it might be useful to be able to share associations e.g. via memcached. I agree that full backend is unnecessary, but I think I will provide some hooks: I was writing on first-class RP/server; storing/retrieving/GCing associations may be exported generic functions so that they could be overriden. No need for actually creating backends, just provide hooks for users to override. Regards, Maciek. -- -><- Maciej 'japhy' Pasternacki -><- http://www.pasternacki.net/ -><- From maciej at pasternacki.net Wed Jul 9 21:46:33 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Wed, 09 Jul 2008 23:46:33 +0200 Subject: [cl-openid-devel] Re: meaning of immediate authentication request In-Reply-To: <776160191.20080710002108@yandex.ru> References: <776160191.20080710002108@yandex.ru> Message-ID: <1215639993.10126.60.camel@localhost> Hello, On Thu, 2008-07-10 at 00:21 +0300, Anton Vodonosov wrote: > What I do not understand from the spec is immediate authentication > requests. > > Could you explain me? How could OpenID Provider return positive > authentication reply in response to a query containing essentially > just a user name without any password, etc? Immediate authentication request is still an indirect request, i.e. a redirect for authenticated user's browser. So the OP may be able to authenticate end user by e.g. IP, cookies, HTTPS client certficate (like in http://certifi.ca/ provider), and so on. The immediate request is just an indication that OP should not attempt to interact with end user. > What is a real word scenario for this? E.g. some shiny AJAX OpenID login widget that allows user to log in without reloading the page. User inputs ID in Ajax widget, the JavaScript's XMLHTTPRequest is redirected (30x status) to OP, then immediately 30x back to RP with either positive assertion, or setup_needed. In second case, RP returns to JavaScript that authentication was not successful, and that JS should attempt to reload whole page for the interactive checkid_setup request. If in such scenario OP attempted to interact with end user, the XMLHTTPRequest would only got some HTML garbage and wouldn't know what to do with it. Regards, Maciek. -- -><- Maciej 'japhy' Pasternacki -><- http://www.pasternacki.net/ -><- From avodonosov at yandex.ru Wed Jul 9 22:19:06 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Thu, 10 Jul 2008 02:19:06 +0400 Subject: [cl-openid-devel] Re: meaning of immediate authentication request In-Reply-To: 9110000000130655205 References: <776160191.20080710002108@yandex.ru> 9110000000130655205 Message-ID: <167051215641946@webmail50.yandex.ru> I see. Thanks. 10.07.08, 01:46, "Maciek Pasternacki" : > Hello, > On Thu, 2008-07-10 at 00:21 +0300, Anton Vodonosov wrote: > > What I do not understand from the spec is immediate authentication > > requests. > > > > Could you explain me? How could OpenID Provider return positive > > authentication reply in response to a query containing essentially > > just a user name without any password, etc? > Immediate authentication request is still an indirect request, i.e. a > redirect for authenticated user's browser. So the OP may be able to > authenticate end user by e.g. IP, cookies, HTTPS client certficate (like > in http://certifi.ca/ provider), and so on. The immediate request is > just an indication that OP should not attempt to interact with end user. > > What is a real word scenario for this? > E.g. some shiny AJAX OpenID login widget that allows user to log in > without reloading the page. User inputs ID in Ajax widget, the > JavaScript's XMLHTTPRequest is redirected (30x status) to OP, then > immediately 30x back to RP with either positive assertion, or > setup_needed. In second case, RP returns to JavaScript that > authentication was not successful, and that JS should attempt to reload > whole page for the interactive checkid_setup request. > If in such scenario OP attempted to interact with end user, the > XMLHTTPRequest would only got some HTML garbage and wouldn't know what > to do with it. > Regards, > Maciek. From scusack at fastmail.com.au Mon Jul 14 12:45:39 2008 From: scusack at fastmail.com.au (Simon Cusack) Date: Mon, 14 Jul 2008 22:45:39 +1000 Subject: [cl-openid-devel] missing packages in shelf and trivial-utf8 bug Message-ID: <20080714224539.fb050a9f.scusack@fastmail.com.au> Hi, Thanks for cl-openid I want to add openid logins to a website I have written in lisp so this has been great to play with, it looks excellent. I had to add the following libs to shelf.lisp to get it to load cleanly (cl-librarian made this part really painless, kudos). (babel tarball-repo :source "asdf-install:babel") (alexandria darcs-repo :source "http://common-lisp.net/project/alexandria/darcs/alexandria/") (trivial-features tarball-repo :source "asdf-install:trivial-features") I then fired up hunchentoot and (after changing the realm) added the required handler using; (hunchentoot:start-server :port 4242) (push (openid-ht-dispatcher "/cl-openid" "http://lizard.tasak.gda.pl:4242/") hunchentoot:*dispatch-table*) I then tried to login using an openid that I have and got hit by an error in UTF-8-BYTES-TO-STRING. I tracked it down to one of the (UTF-8-BYTES-TO-STRING array :start start :end colon) calls in PARSE-KV. I did the http-request call at the REPL and then saved the body from the response into *test-body*. (defparameter *test-body* #(97 115 115 111 99 95 104 97 110 100 108 101 58 123 72 77 65 67 45 83 72 65 50 53 54 125 123 52 56 55 98 52 49 50 56 125 123 67 89 99 54 121 81 61 61 125 10 97 115 115 111 99 95 116 121 112 101 58 72 77 65 67 45 83 72 65 50 53 54 10 100 104 95 115 101 114 118 101 114 95 112 117 98 108 105 99 58 65 73 78 57 88 113 100 109 51 116 52 100 67 109 55 108 50 88 121 87 114 68 68 78 102 109 70 72 78 88 76 73 120 121 57 80 83 83 73 69 81 116 47 97 118 57 99 83 87 67 68 56 69 115 81 72 88 111 82 43 90 114 114 102 110 115 67 101 77 121 102 109 113 89 72 78 111 104 65 85 115 109 43 112 71 88 65 120 87 79 69 100 122 116 102 66 90 112 105 116 68 49 88 101 80 53 90 52 65 107 111 117 84 86 103 84 65 53 86 56 118 49 77 100 109 87 117 89 110 52 106 97 79 85 100 75 99 90 88 119 103 79 101 122 111 50 69 71 100 78 73 71 75 102 104 80 50 89 66 115 67 102 71 47 109 89 74 47 81 55 65 43 10 101 110 99 95 109 97 99 95 107 101 121 58 85 74 54 99 49 118 71 86 105 66 68 106 77 115 100 121 83 50 80 55 51 104 119 47 118 106 55 86 111 55 67 119 113 122 80 99 55 108 78 109 110 52 73 61 10 101 120 112 105 114 101 115 95 105 110 58 49 50 48 57 54 48 48 10 110 115 58 104 116 116 112 58 47 47 115 112 101 99 115 46 111 112 101 110 105 100 46 110 101 116 47 97 117 116 104 47 50 46 48 10 115 101 115 115 105 111 110 95 116 121 112 101 58 68 72 45 83 72 65 50 53 54 10)) Calling (utf-8-bytes-to-string *test-body*) results in "Invalid byte at start of character: 0x84". However (flexi-streams:octets-to-string *test-body* :external-format :utf-8) results in; "assoc_handle:{HMAC-SHA256}{487b4128}{CYc6yQ==} assoc_type:HMAC-SHA256 dh_server_public:AIN9Xqdm3t4dCm7l2XyWrDDNfmFHNXLIxy9PSSIEQt/av9cSWCD8EsQHXoR+ZrrfnsCeMyfmqYHNohAUsm+pGXAxWOEdztfBZpitD1XeP5Z4AkouTVgTA5V8v1MdmWuYn4jaOUdKcZXwgOezo2EGdNIGKfhP2YBsCfG/mYJ/Q7A+ enc_mac_key:UJ6c1vGViBDjMsdyS2P73hw/vj7Vo7CwqzPc7lNmn4I= expires_in:1209600 ns:http://specs.openid.net/auth/2.0 session_type:DH-SHA256 " So I'm guessing it is a bug in trivial-utf8. When I changed PARSE-KV to use flexi-streams instead like so; (defun parse-kv (array) "Parse key-value form message passed as an (unsigned-byte 8) array into alist. OpenID Authentication 2.0 4.1.1. Key-Value Form Encoding." (loop for line in (cl-ppcre:split #\NewLine (flexi-streams:octets-to-string array :external-format :utf-8)) as colon = (position #\: line) collect (cons (subseq line 0 colon) (subseq line (1+ colon))))) And it worked beautifully, woohoo! I'm not sure what the correct approach here is, I read the openid spec and the above seems ok to me. Is there a reason that trivial-utf8 was used instead of flexi-streams and cl-ppcre? regards, sim. From avodonosov at yandex.ru Mon Jul 14 13:10:59 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Mon, 14 Jul 2008 16:10:59 +0300 Subject: [cl-openid-devel] missing packages in shelf and trivial-utf8 bug In-Reply-To: <20080714224539.fb050a9f.scusack@fastmail.com.au> References: <20080714224539.fb050a9f.scusack@fastmail.com.au> Message-ID: <1843887487.20080714161059@yandex.ru> Hello, I've just experienced this error too. It turned out that the problem happens only with SBCL. With CLISP the bug does not appear. Best regards, -Anton on Monday, July 14, 2008, 3:45:39 PM Simon wrote: > Hi, > Thanks for cl-openid I want to add openid logins to a website I have > written in lisp so this has been great to play with, it looks > excellent. > I had to add the following libs to shelf.lisp to get it to load > cleanly (cl-librarian made this part really painless, kudos). > (babel tarball-repo :source "asdf-install:babel") > (alexandria darcs-repo :source > "http://common-lisp.net/project/alexandria/darcs/alexandria/") > (trivial-features tarball-repo :source "asdf-install:trivial-features") > I then fired up hunchentoot and (after changing the realm) added the > required handler using; > (hunchentoot:start-server :port 4242) > (push (openid-ht-dispatcher "/cl-openid" > "http://lizard.tasak.gda.pl:4242/") hunchentoot:*dispatch-table*) > I then tried to login using an openid that I have and got hit by an > error in UTF-8-BYTES-TO-STRING. > I tracked it down to one of the (UTF-8-BYTES-TO-STRING array :start > start :end colon) calls in PARSE-KV. > I did the http-request call at the REPL and then saved the body from > the response into *test-body*. > (defparameter *test-body* #(97 115 115 111 99 95 104 97 110 100 108 101 > 58 123 72 77 65 67 45 83 72 65 50 53 54 125 123 52 56 55 98 52 49 50 56 > 125 123 67 89 99 54 121 81 61 61 125 10 97 115 115 111 99 95 116 121 > 112 101 58 72 77 65 67 45 83 72 65 50 53 54 10 100 104 95 115 101 114 > 118 101 114 95 112 117 98 108 105 99 58 65 73 78 57 88 113 100 109 51 > 116 52 100 67 109 55 108 50 88 121 87 114 68 68 78 102 109 70 72 78 88 > 76 73 120 121 57 80 83 83 73 69 81 116 47 97 118 57 99 83 87 67 68 56 > 69 115 81 72 88 111 82 43 90 114 114 102 110 115 67 101 77 121 102 109 > 113 89 72 78 111 104 65 85 115 109 43 112 71 88 65 120 87 79 69 100 122 > 116 102 66 90 112 105 116 68 49 88 101 80 53 90 52 65 107 111 117 84 86 > 103 84 65 53 86 56 118 49 77 100 109 87 117 89 110 52 106 97 79 85 100 > 75 99 90 88 119 103 79 101 122 111 50 69 71 100 78 73 71 75 102 104 80 > 50 89 66 115 67 102 71 47 109 89 74 47 81 55 65 43 10 101 110 99 95 109 > 97 99 95 107 101 121 58 85 74 54 99 49 118 71 86 105 66 68 106 77 115 > 100 121 83 50 80 55 51 104 119 47 118 106 55 86 111 55 67 119 113 122 > 80 99 55 108 78 109 110 52 73 61 10 101 120 112 105 114 101 115 95 105 > 110 58 49 50 48 57 54 48 48 10 110 115 58 104 116 116 112 58 47 47 115 > 112 101 99 115 46 111 112 101 110 105 100 46 110 101 116 47 97 117 116 > 104 47 50 46 48 10 115 101 115 115 105 111 110 95 116 121 112 101 58 68 > 72 45 83 72 65 50 53 54 10)) > Calling (utf-8-bytes-to-string *test-body*) results in > "Invalid byte at start of character: 0x84". > However (flexi-streams:octets-to-string > *test-body* :external-format :utf-8) results in; > "assoc_handle:{HMAC-SHA256}{487b4128}{CYc6yQ==} > assoc_type:HMAC-SHA256 > dh_server_public:AIN9Xqdm3t4dCm7l2XyWrDDNfmFHNXLIxy9PSSIEQt/av9cSWCD8EsQHXoR+ZrrfnsCeMyfmqYHNohAUsm+pGXAxWOEdztfBZpitD1XeP5Z4AkouTVgTA5V8v1MdmWuYn4jaOUdKcZXwgOezo2EGdNIGKfhP2YBsCfG/mYJ/Q7A+ > enc_mac_key:UJ6c1vGViBDjMsdyS2P73hw/vj7Vo7CwqzPc7lNmn4I= > expires_in:1209600 > ns:http://specs.openid.net/auth/2.0 > session_type:DH-SHA256 > " > So I'm guessing it is a bug in trivial-utf8. > When I changed PARSE-KV to use flexi-streams instead like so; > (defun parse-kv (array) > "Parse key-value form message passed as an (unsigned-byte 8) array into alist. > OpenID Authentication 2.0 4.1.1. Key-Value Form Encoding." > (loop for line in (cl-ppcre:split #\NewLine > (flexi-streams:octets-to-string array :external-format :utf-8)) > as colon = (position #\: line) > collect (cons (subseq line 0 colon) > (subseq line (1+ colon))))) > And it worked beautifully, woohoo! > I'm not sure what the correct approach here is, I read the openid spec > and the above seems ok to me. Is there a reason that trivial-utf8 was > used instead of flexi-streams and cl-ppcre? > regards, sim. > _______________________________________________ > cl-openid-devel mailing list > cl-openid-devel at common-lisp.net > http://common-lisp.net/cgi-bin/mailman/listinfo/cl-openid-devel From avodonosov at yandex.ru Mon Jul 14 14:53:21 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Mon, 14 Jul 2008 17:53:21 +0300 Subject: [cl-openid-devel] missing packages in shelf and trivial-utf8 bug In-Reply-To: <20080714224539.fb050a9f.scusack@fastmail.com.au> References: <20080714224539.fb050a9f.scusack@fastmail.com.au> Message-ID: <215735975.20080714175321@yandex.ru> I've reported the error to the trivial-utf-8-devel list, Marijn Haverbeke kindly fixed the problem. With new version of trivial-utf-8 cl-openid works SBCL now. Simon, thank your for the bug report and for the interest in the project. As for usage of flexi-streams instead of trivial-utf-8, perhaps it makes sense, in case when drakma and/or hunchentoot is used (Maicek has an intention to make the cl-openid independent of http client and server). As drakma and hunchentoot already depend on flexi-streams, trivial-utf-8 add some redundancy into library dependency. But this is not a big problem IMHO, at least for now. Maicek works on OpenID Provider, so that our Common Lisp sites will be able not only login users by their livejournal etc. credentials, but also allow our users to login into livejournal, blogger etc. by credentials from Common Lisp sites. After working OpenID Provider will be implemented (perhaps this week), a refactoring is planned and here we will have a chance to rethink library dependencies. -Anton From maciej at pasternacki.net Mon Jul 14 15:11:27 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Mon, 14 Jul 2008 17:11:27 +0200 Subject: [cl-openid-devel] missing packages in shelf and trivial-utf8 bug In-Reply-To: <20080714224539.fb050a9f.scusack@fastmail.com.au> References: <20080714224539.fb050a9f.scusack@fastmail.com.au> Message-ID: <1216048287.10126.93.camel@localhost> Hello, On Mon, 2008-07-14 at 22:45 +1000, Simon Cusack wrote: > Thanks for cl-openid I want to add openid logins to a website I have > written in lisp so this has been great to play with, it looks > excellent. Please remember it's only prototype at the moment; after implementation of OpenID Provider prototype it will undergo major refactoring into a usable library. It's probably not usable at all yet. If you're willing to help in testing this beast, it would be great (RP can use some testing with different providers). > I had to add the following libs to shelf.lisp to get it to load > cleanly (cl-librarian made this part really painless, kudos). Thanks! I was tired myself by downloading endless dependencies, so I started the Librarian. However, it does not automatically discover dependencies, like asdf-install, yet, and that's where your problem comes from. > (babel tarball-repo :source "asdf-install:babel") > (alexandria darcs-repo :source "http://common-lisp.net/project/alexandria/darcs/alexandria/") > (trivial-features tarball-repo :source "asdf-install:trivial-features") I added this to the Librarian (since it's within Hunchentoot's dependencies that are only included by shelf.lisp -- CFFI introduced those recently, and I still have version without those dependencies). I added the main darcs repos of all projects -- Librarian prefers those. Just ?darcs pull in 'lib/' subdirectory, and no changes to shelf.lisp are needed. > I then tried to login using an openid that I have and got hit by an > error in UTF-8-BYTES-TO-STRING. > > I tracked it down to one of the (UTF-8-BYTES-TO-STRING array :start > start :end colon) calls in PARSE-KV. > > I did the http-request call at the REPL and then saved the body from > the response into *test-body*. [...] > Calling (utf-8-bytes-to-string *test-body*) results in > "Invalid byte at start of character: 0x84". As Anton wrote, it's already fixed in trivial-utf-8 repo. > I'm not sure what the correct approach here is, I read the openid spec > and the above seems ok to me. Is there a reason that trivial-utf8 was > used instead of flexi-streams and cl-ppcre? Efficiency (trivial-utf-8 is small and fast) and keeping direct dependency list as little as possible. CL-OpenID is supposed to be usable with different HTTP server and client libraries, so I decided not to use flexi-streams even though it comes with Hunchentoot and Drakma -- it is known to be quite slow, and introduces yet another dependency (on trivial-gray-streams). Flexi-streams do recoding strings via Gray streams CLOS machinery, which just has to be much slower than simply operating on array of bytes -- more flexible, too, but CL-OpenID doesn't need this flexibility. As for CL-PPCRE:SPLIT, for similar reasons, I prefer to use SPLIT-SEQUENCE when possible. Also, your solution conses more than one with TRIVIAL-UTF-8: first a new string is created by FLEXI-STREAMS (which itself would cons a bit internally), then a new string for every line, and then a new string for every key and value. My solution works directly on octet array and creates only strings that are actually needed: those for keys and values. Regards and thanks for feedback, Maciej. -- -><- Maciej 'japhy' Pasternacki -><- http://www.pasternacki.net/ -><- From avodonosov at yandex.ru Mon Jul 14 19:40:04 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Mon, 14 Jul 2008 22:40:04 +0300 Subject: [cl-openid-devel] missing packages in shelf and trivial-utf8 bug In-Reply-To: <1216048287.10126.93.camel@localhost> References: <20080714224539.fb050a9f.scusack@fastmail.com.au> <1216048287.10126.93.camel@localhost> Message-ID: <1487610283.20080714224004@yandex.ru> on Monday, July 14, 2008, 6:11:27 PM Maciek wrote: >> I'm not sure what the correct approach here is, I read the openid spec >> and the above seems ok to me. Is there a reason that trivial-utf8 was >> used instead of flexi-streams and cl-ppcre? > Efficiency (trivial-utf-8 is small and fast) and keeping direct > dependency list as little as possible. CL-OpenID is supposed to be > usable with different HTTP server and client libraries, so I decided not > to use flexi-streams even though it comes with Hunchentoot and Drakma -- > it is known to be quite slow, and introduces yet another dependency (on > trivial-gray-streams). Flexi-streams do recoding strings via Gray > streams CLOS machinery, which just has to be much slower than simply > operating on array of bytes -- more flexible, too, but CL-OpenID doesn't > need this flexibility. Flexi-streams are not slow. Some work was invested into optimization recently. Take a look: (defparameter *test-body* #(97 115 115 111 99 95 104 97 110 100 108 101 58 123 72 77 65 67 45 83 72 65 50 53 54 125 123 52 56 55 98 52 49 50 56 125 123 67 89 99 54 121 81 61 61 125 10 97 115 115 111 99 95 116 121 112 101 58 72 77 65 67 45 83 72 65 50 53 54 10 100 104 95 115 101 114 118 101 114 95 112 117 98 108 105 99 58 65 73 78 57 88 113 100 109 51 116 52 100 67 109 55 108 50 88 121 87 114 68 68 78 102 109 70 72 78 88 76 73 120 121 57 80 83 83 73 69 81 116 47 97 118 57 99 83 87 67 68 56 69 115 81 72 88 111 82 43 90 114 114 102 110 115 67 101 77 121 102 109 113 89 72 78 111 104 65 85 115 109 43 112 71 88 65 120 87 79 69 100 122 116 102 66 90 112 105 116 68 49 88 101 80 53 90 52 65 107 111 117 84 86 103 84 65 53 86 56 118 49 77 100 109 87 117 89 110 52 106 97 79 85 100 75 99 90 88 119 103 79 101 122 111 50 69 71 100 78 73 71 75 102 104 80 50 89 66 115 67 102 71 47 109 89 74 47 81 55 65 43 10 101 110 99 95 109 97 99 95 107 101 121 58 85 74 54 99 49 118 71 86 105 66 68 106 77 115 100 121 83 50 80 55 51 104 119 47 118 106 55 86 111 55 67 119 113 122 80 99 55 108 78 109 110 52 73 61 10 101 120 112 105 114 101 115 95 105 110 58 49 50 48 57 54 48 48 10 110 115 58 104 116 116 112 58 47 47 115 112 101 99 115 46 111 112 101 110 105 100 46 110 101 116 47 97 117 116 104 47 50 46 48 10 115 101 115 115 105 111 110 95 116 121 112 101 58 68 72 45 83 72 65 50 53 54 10)) (time (dotimes (i 100000) (utf-8-bytes-to-string *test-body*))) Evaluation took: 4.813 seconds of real time 4.8125 seconds of user run time 0.0 seconds of system run time [Run times include 0.454 seconds GC run time.] 0 calls to %EVAL 0 page faults and 528,785,288 bytes consed. (defparameter *utf8-ex-fmt* (flexi-streams:make-external-format :utf-8)) (time (dotimes (i 100000) (flexi-streams:octets-to-string *test-body* :external-format *utf8-ex-fmt*))) Evaluation took: 4.109 seconds of real time 4.109375 seconds of user run time 0.0 seconds of system run time [Run times include 0.078 seconds GC run time.] 0 calls to %EVAL 0 page faults and 159,986,344 bytes consed. This is SBCL with flexi-streams-1.0.3 and the latest trivial-utf-8. - Anton From maciej at pasternacki.net Tue Jul 15 21:49:18 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Tue, 15 Jul 2008 23:49:18 +0200 Subject: [cl-openid-devel] missing packages in shelf and trivial-utf8 bug In-Reply-To: <1487610283.20080714224004@yandex.ru> References: <20080714224539.fb050a9f.scusack@fastmail.com.au> <1216048287.10126.93.camel@localhost> <1487610283.20080714224004@yandex.ru> Message-ID: <1216158559.10126.101.camel@localhost> On Mon, 2008-07-14 at 22:40 +0300, Anton Vodonosov wrote: > Flexi-streams are not slow. Some work was invested into optimization > recently. Take a look: [...] > (time > (dotimes (i 100000) > (utf-8-bytes-to-string *test-body*))) > > Evaluation took: > 4.813 seconds of real time > 4.8125 seconds of user run time > 0.0 seconds of system run time > [Run times include 0.454 seconds GC run time.] > 0 calls to %EVAL > 0 page faults and > 528,785,288 bytes consed. > > (defparameter *utf8-ex-fmt* (flexi-streams:make-external-format :utf-8)) > > (time > (dotimes (i 100000) > (flexi-streams:octets-to-string *test-body* > :external-format *utf8-ex-fmt*))) > > Evaluation took: > 4.109 seconds of real time > 4.109375 seconds of user run time > 0.0 seconds of system run time > [Run times include 0.078 seconds GC run time.] > 0 calls to %EVAL > 0 page faults and > 159,986,344 bytes consed. > > This is SBCL with flexi-streams-1.0.3 and the latest trivial-utf-8. Wow! Flexi-streams even cons less than trivial-utf-8! It seems that I have outdated info (I remember from not long ago some discussions about Hunchentoot being slow, and about flexi-streams being the cause). I still like trivial-utf-8 better, partly because it's simpler and I understand it better. ;) I will rethink the decision about trivial-utf-8 during the refactoring -- I'll have to look at the portability, too. Regards, Maciej. -- -><- Maciej 'japhy' Pasternacki -><- http://www.pasternacki.net/ -><- From leslie.polzer at gmx.net Sat Jul 19 08:04:59 2008 From: leslie.polzer at gmx.net (Leslie P. Polzer) Date: Sat, 19 Jul 2008 10:04:59 +0200 (CEST) Subject: [cl-openid-devel] Re: CL-OPENID problem Message-ID: <64400.88.73.251.157.1216454699.squirrel@mail.stardawn.org> > Have you got latest TRIVIAL-UTF-8 code from the darcs repo (i.e. later > than June 14)? There was a bug in this library that caused this kind of > error, and it has been fixed just a few days ago. The exact patch that > fixes this is: > > Mon Jul 14 16:14:11 CEST 2008 marijnh at gmail.com > * add (*) dimensions to simple-array type specs to please SBCL That fixed it, thanks! > This was discussed on the development list on Monday (starting with > http://common-lisp.net/pipermail/cl-openid-devel/2008-July/000010.html), > and on the same day this bug was fixed. The bug has slipped me, because > for development I use Clozure CL for Linux, and test with SBCL only from > time to time. I haven't had a chance to try Clozure CL (I run IA32 on my 64 bit CPU) -- why do you prefer it to SBCL? I'm curious. > There is an active development list for CL-OpenID, and you should rather > send mails regarding CL-OpenID directly there (unless there is some > reason you'd prefer to mail me personally). Sorry, that list escaped me. :) Am I right in that CL-OPENID will happily serve all basic needs in its current state? Leslie From leslie.polzer at gmx.net Sat Jul 19 14:11:06 2008 From: leslie.polzer at gmx.net (Leslie P. Polzer) Date: Sat, 19 Jul 2008 16:11:06 +0200 (CEST) Subject: [cl-openid-devel] What happens after verification? Message-ID: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> Suppose I'm a relying party and send a HANDLE-OPENID-REQUEST to the appropriate provider. This function returns an URI which I'm going to redirect the user to. The user authenticates himself. What happens then? I know that I can specify a return URI (which possibly contains some secret key that maps to the login process), but isn't CL-OPENID supposed to take care of this? Thanks! Leslie -- LinkedIn Profile: http://www.linkedin.com/in/polzer Blog: http://blog.viridian-project.de/ From avodonosov at yandex.ru Sat Jul 19 14:43:35 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Sat, 19 Jul 2008 17:43:35 +0300 Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> Message-ID: <3371536.20080719174335@yandex.ru> on Saturday, July 19, 2008, 5:11:06 PM Leslie wrote: > Suppose I'm a relying party and send a HANDLE-OPENID-REQUEST > to the appropriate provider. This function returns an URI > which I'm going to redirect the user to. > The user authenticates himself. > What happens then? > I know that I can specify a return URI (which possibly contains > some secret key that maps to the login process), but isn't > CL-OPENID supposed to take care of this? > Thanks! > Leslie After user authenticated himself at the provider, the provider returns Redirect status to user's browser. Redirect is performed to the return URI you specified. The provider also ads parameters to the return URI. These parameters specify whether authentication was successful. So, relying party receives new HTTP request from the redirected user browser. This is called "indirect reply" from provider. You need to pass the request parameters to the HANDLE-INDIRECT-REPLY function. This function takes care of interpreting the parameters meaning and also verifying that the reply was really from the provider, by verifying digital signature. Best regards, -Anton From maciej at pasternacki.net Sat Jul 19 20:06:47 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Sat, 19 Jul 2008 22:06:47 +0200 Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> Message-ID: <1216498007.10126.145.camel@localhost> On Sat, 2008-07-19 at 16:11 +0200, Leslie P. Polzer wrote: > Suppose I'm a relying party and send a HANDLE-OPENID-REQUEST > to the appropriate provider. This function returns an URI > which I'm going to redirect the user to. ?The URI contains "openid.return_to" address, referring to the Relying Party endpoint URI (or to what the HANDLE-OPENID-REQUEST thinks it is). > The user authenticates himself. > > What happens then? ?User is redirected to the return_to address, which contains the key that maps to the specific login process -- it's an indirect reply. The assertion received via the reply is examined (by the very same HANDLE-OPENID-REQUEST function called by Hunchentoot handler), and -- currently -- only HTML describing the status is returned. > I know that I can specify a return URI (which possibly contains > some secret key that maps to the login process), but isn't > CL-OPENID supposed to take care of this? Remember it is just a working prototype, the proof of concept, not an actually usable library. Yes, CL-OpenID will take care of this. Functions for registering the handler will -- most probably -- take a callback argument that will receive authentication status as an argument. It will be able to set authorisation cookies, display actual error message specific for the service, redirect user to his dashboard, and so on. Please, don't look at current state of project as anything fixed. I am working bottom up: from internally functional proof of concept up to actual API. The RP is still a proof of concept. It will undergo major refactoring that will aim to provide an actual API (it will be CLOS oriented, I have some initial ideas already). However, before the refactoring, I wish to do also a proof of concept OP, to have good grasp on the common part of functionality (coding/decoding messages, associations etc). Regards, Maciej. -- -><- Maciej 'japhy' Pasternacki -><- http://www.pasternacki.net/ -><- From leslie.polzer at gmx.net Sun Jul 20 08:34:01 2008 From: leslie.polzer at gmx.net (Leslie P. Polzer) Date: Sun, 20 Jul 2008 10:34:01 +0200 (CEST) Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <3371536.20080719174335@yandex.ru> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> Message-ID: <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> > You need to pass the request parameters to the HANDLE-INDIRECT-REPLY > function. This function takes care of interpreting the parameters > meaning and also verifying that the reply was really from the > provider, by verifying digital signature. Thanks, that was the missing piece. I guess checkid_immediate isn't supported yet? Leslie From leslie.polzer at gmx.net Sun Jul 20 08:44:40 2008 From: leslie.polzer at gmx.net (Leslie P. Polzer) Date: Sun, 20 Jul 2008 10:44:40 +0200 (CEST) Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <1216498007.10126.145.camel@localhost> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <1216498007.10126.145.camel@localhost> Message-ID: <61323.88.73.215.244.1216543480.squirrel@mail.stardawn.org> > Remember it is just a working prototype, the proof of concept, not an > actually usable library. Yes, CL-OpenID will take care of this. > Functions for registering the handler will -- most probably -- take a > callback argument that will receive authentication status as an > argument. It will be able to set authorisation cookies, display actual > error message specific for the service, redirect user to his dashboard, > and so on. > > Please, don't look at current state of project as anything fixed. I dont. :) I'm just trying to get a grasp on the OpenID stuff and integrate a preliminary version into my project. I'll happily adapt to any API changes. Leslie From avodonosov at yandex.ru Sun Jul 20 08:49:50 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Sun, 20 Jul 2008 11:49:50 +0300 Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> Message-ID: <1481248106.20080720114950@yandex.ru> on Sunday, July 20, 2008, 11:34:01 AM Leslie wrote: > I guess checkid_immediate isn't supported yet? Right From maciej at pasternacki.net Sun Jul 20 13:40:25 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Sun, 20 Jul 2008 15:40:25 +0200 Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> Message-ID: <1216561225.10126.175.camel@localhost> On Sun, 2008-07-20 at 10:34 +0200, Leslie P. Polzer wrote: > > You need to pass the request parameters to the HANDLE-INDIRECT-REPLY > > function. This function takes care of interpreting the parameters > > meaning and also verifying that the reply was really from the > > provider, by verifying digital signature. > > Thanks, that was the missing piece. > > I guess checkid_immediate isn't supported yet? It is supported. The function that you are calling, HANDLE-OPENID-REQUEST, is the entry point for the HTTP request. It is intended to be called by handlers, and to be provided GET parameters (plus handler's root URI, realm URI and request's URI postfix, which I explained earlier). It does display simple login form, handle the form's return (that's what you emulate with your call) and the OP's indirect reply. This entry point, and the login form, at the moment, calls only checkid_setup. The programmer's entry point for starting authorisation process is INITIATE-AUTHORIZATION. I think this is what you actually want to call, and it supports the IMMEDIATE-P keyword parameter. It returns the URI to redirect user to. The actual handler for indirect reply is HANDLE-INDIRECT-REPLY. This is the function you should call, if you wish to handle the reply from your own handler framework. This function analyses the authentication response, and returns the identity object (at the moment it's an alist) on successful authentication, returns NIL on "cancel" (authentication failure)[1], or raises the OPENID-ASSERTION-ERROR on failure. When setup is needed, HANDLE-INDIRECT-REPLY raises OPENID-ASSERTION-ERROR with code :SETUP-NEEDED. It's up to caller how to handle it. At the moment, HANDLE-OPENID-REQUEST does not handle the assertion errors at all. This is because it should be treated rather as an example, simple implementation, not as the main entry point. This is a plain Web 1.0 interface and endpoint at the same URI, and as such needs no checkid_immediate support. To properly use checkid_immediate, more elaborate setup is needed and it needs to know more of the overall application (it's supposed to be called from e.g. an AJAX framework, which may take very different forms). I may add the "immediate" checkbox to login form, and pretty display of exceptions on result page, but I wish to leave it to the polishing-refactoring phase, and now concentrate on having the OP prototype faster and getting to the refactoring phase earlier. I know it's hard to figure out all of this at the moment, as no symbols are even exported. It's because exporting symbols from published package means that it's official API that I should provide later on, and, as I wrote, current project state is nowhere near the final API. [1] The return values should be probably reworked -- on authentication failure, the caller may still need to know the ID object. Probably it will return T, NIL (or -- if the condition proves problematic -- :SETUP-NEEDED) as first value, and the ID object as second value. -- -><- Maciej 'japhy' Pasternacki -><- http://www.pasternacki.net/ -><- From leslie.polzer at gmx.net Sun Jul 20 15:27:57 2008 From: leslie.polzer at gmx.net (Leslie P. Polzer) Date: Sun, 20 Jul 2008 17:27:57 +0200 (CEST) Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <1216561225.10126.175.camel@localhost> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> <1216561225.10126.175.camel@localhost> Message-ID: <64029.88.73.215.244.1216567677.squirrel@mail.stardawn.org> Thanks for the elaborate reply. I understood everything pretty well, but... > At the moment, HANDLE-OPENID-REQUEST does not handle the assertion > errors at all. This is because it should be treated rather as an > example, simple implementation, not as the main entry point. This is a > plain Web 1.0 interface and endpoint at the same URI, and as such needs > no checkid_immediate support. To properly use checkid_immediate, more > elaborate setup is needed and it needs to know more of the overall > application (it's supposed to be called from e.g. an AJAX framework, > which may take very different forms). That's what I'm interested in. I see that using IMMEDIATE-P causes my identity provider to redirect immediately to my site; but not completely; when I say: (initiate-authorization "http://skypher.myopenid.com/" "http://handler.tld/path" "http://realm.tld/" :immediate-p t) the redirect will return to http://handler.tld/IDx. How am I supposed to catch this? I'd rather be redirected to the full URI I specified and then pick up GET parameters or something. And how am I suppose to use this stuff with AJAX, since I don't want to do a full page redirect in this case? I suppose I have a fundamental misunderstanding here, sorry for being dumb... :) Leslie From maciej at pasternacki.net Sun Jul 20 16:12:06 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Sun, 20 Jul 2008 18:12:06 +0200 Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <64029.88.73.215.244.1216567677.squirrel@mail.stardawn.org> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> <1216561225.10126.175.camel@localhost> <64029.88.73.215.244.1216567677.squirrel@mail.stardawn.org> Message-ID: <1216570326.10126.196.camel@localhost> On Sun, 2008-07-20 at 17:27 +0200, Leslie P. Polzer wrote: > Thanks for the elaborate reply. I understood everything pretty > well, but... > > > At the moment, HANDLE-OPENID-REQUEST does not handle the assertion > > errors at all. This is because it should be treated rather as an > > example, simple implementation, not as the main entry point. This is a > > plain Web 1.0 interface and endpoint at the same URI, and as such needs > > no checkid_immediate support. To properly use checkid_immediate, more > > elaborate setup is needed and it needs to know more of the overall > > application (it's supposed to be called from e.g. an AJAX framework, > > which may take very different forms). > > That's what I'm interested in. > > I see that using IMMEDIATE-P causes my identity provider to redirect > immediately to my site; but not completely; > > when I say: > > (initiate-authorization "http://skypher.myopenid.com/" > "http://handler.tld/path" > "http://realm.tld/" > :immediate-p t) > > the redirect will return to http://handler.tld/IDx. How am I > supposed to catch this? I'd rather be redirected to the full > URI I specified and then pick up GET parameters or something. ? Use trailing slash: (initiate-authorization "http://skypher.myopenid.com/" "http://handler.tld/path/" "http://realm.tld/" :immediate-p t) This way, you'll get redirected to http://handler.tld/path/IDx -- that's how PURI:MERGE-URIS work. You are supposed to handle whole hierarchy under http://handler.tld/path/, and to pass IDx as POSTFIX parameter to HANDLE-OPENID-REQUEST, or get the ID by postfix as this function does: (handle-indirect-reply parameters (gethash (intern postfix :cl-openid.ids) *ids*)) The GETHASH part will be eventually its own, exported function. A handler for Hunchentoot with usage example is included after the "Hunchentoot specific part" comment in relying-party.lisp. The INITIATE-AUTHORIZATION function expects the trailing slash -- the top-level OPENID-HT-DISPATCHER function adds them if necessary. At the moment (and the prototype will stay this way), the final result page for all authentication requests is the HTML page with reply details, no further redirections. If you wish to hack the possibility of integration into real site (I wouldn't recommend this), you can add keyword parameter CALLBACK and/or IMMEDIATE-CALLBACK to INITIATE-AUTHORIZATION (or just check if the IMMEDIATE-P is a function), push (cons :CALLBACK CALLBACK) to ID alist, and call appropriate element from the ID alist in either handler that calls HANDLE-INDIRECT-REPLY, or make HANDLE-OPENID-REQUEST call the callback if present. Before the refactoring, however, you are on your own and I don't recommend actually using this code as it is now. I may incorporate your patch into the prototype, but I will focus now on having the provider, refactoring and providing proper API. The GSoC project ends with end of August and that's when I think I will have the 1.0 with documentation and tests; I think the proper API for relying party will start to emerge near the end of July. > And how am I suppose to use this stuff with AJAX, since I > don't want to do a full page redirect in this case? At the moment, you are not supposed to use this stuff at all ;) the internal functions are working, but there is no real API, as I already wrote -- it's available for testing, as a prototype. I outlined above, how I would hack the callback support into current code base -- you're free to put it there, my focus is on getting to final API. Regards, Maciej. P.S. The change that I wrote about in earlier post (adding "immediate" checkbox to login form and pretty display of assertion errors on result page) is already in repo -- it was just a few lines anyway, and pretty display of exceptions helps in debugging. -- -><- Maciej 'japhy' Pasternacki -><- http://www.pasternacki.net/ -><- From maciej at pasternacki.net Sun Jul 20 16:15:01 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Sun, 20 Jul 2008 18:15:01 +0200 Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <1216570326.10126.196.camel@localhost> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> <1216561225.10126.175.camel@localhost> <64029.88.73.215.244.1216567677.squirrel@mail.stardawn.org> <1216570326.10126.196.camel@localhost> Message-ID: <1216570501.10126.199.camel@localhost> On Sun, 2008-07-20 at 18:12 +0200, Maciek Pasternacki wrote: > > when I say: > > > > (initiate-authorization "http://skypher.myopenid.com/" > > "http://handler.tld/path" > > "http://realm.tld/" > > :immediate-p t) > > > > the redirect will return to http://handler.tld/IDx. How am I > > supposed to catch this? I'd rather be redirected to the full > > URI I specified and then pick up GET parameters or something. > > ? > Use trailing slash: > (initiate-authorization "http://skypher.myopenid.com/" > "http://handler.tld/path/" > "http://realm.tld/" > :immediate-p t) > > This way, you'll get redirected to http://handler.tld/path/IDx -- that's > how PURI:MERGE-URIS work. You are supposed to handle whole hierarchy > under http://handler.tld/path/, and to pass IDx as POSTFIX parameter to > HANDLE-OPENID-REQUEST, or get the ID by postfix as this function does: > > (handle-indirect-reply parameters (gethash (intern postfix :cl-openid.ids) *ids*)) > > The GETHASH part will be eventually its own, exported function. Update (I forgot to add this): I used URI postfix instead of GET parameters because OpenID spec is not clear on how the OPs should treat existing GET parameters in incoming "openid.return_to" fields. The GET parameters might get lost or mangled, and the postfix is part of URI path, so it will stay untouched. -- -><- Maciej 'japhy' Pasternacki -><- http://www.pasternacki.net/ -><- From avodonosov at yandex.ru Sun Jul 20 16:44:51 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Sun, 20 Jul 2008 19:44:51 +0300 Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <1216570501.10126.199.camel@localhost> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> <1216561225.10126.175.camel@localhost> <64029.88.73.215.244.1216567677.squirrel@mail.stardawn.org> <1216570326.10126.196.camel@localhost> <1216570501.10126.199.camel@localhost> Message-ID: <109794029.20080720194451@yandex.ru> on Sunday, July 20, 2008, 7:15:01 PM Maciek wrote: > > Update (I forgot to add this): I used URI postfix instead of GET > parameters because OpenID spec is not clear on how the OPs should treat > existing GET parameters in incoming "openid.return_to" fields. The GET > parameters might get lost or mangled, and the postfix is part of URI > path, so it will stay untouched. IMHO the spec allows it, in the 9.1. Request Parameters: "Note: The return_to URL MAY be used as a mechanism for the Relying Party to attach context about the authentication request to the authentication response. This document does not define a mechanism by which the RP can ensure that query parameters are not modified by outside parties; such a mechanism can be defined by the RP itself." I understand it as request parameters are allowed. But URI postfix is OK as well. Anyway, I agree that HANDLE-OPENID-REQUEST must serve mostly as example and programmer will use more low-level functions. Example when programmer may want to add query parameters another than authentication transaction ID: 1. user (guest) tries to access a page requiring authentication. 2. he is redirected to login page. 3. openid authentication is performed 4. the page user wanted to access initially (from the step 1) is displayed. Programmer may want to pull the URL of the initial page through all the process using query parameters (although is possible to store it on the server, as we store openid auth. sessions). - Anton From maciej at pasternacki.net Sun Jul 20 17:28:33 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Sun, 20 Jul 2008 19:28:33 +0200 Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <109794029.20080720194451@yandex.ru> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> <1216561225.10126.175.camel@localhost> <64029.88.73.215.244.1216567677.squirrel@mail.stardawn.org> <1216570326.10126.196.camel@localhost> <1216570501.10126.199.camel@localhost> <109794029.20080720194451@yandex.ru> Message-ID: <1216574913.10126.209.camel@localhost> On Sun, 2008-07-20 at 19:44 +0300, Anton Vodonosov wrote: > > Update (I forgot to add this): I used URI postfix instead of GET > > parameters because OpenID spec is not clear on how the OPs should treat > > existing GET parameters in incoming "openid.return_to" fields. The GET > > parameters might get lost or mangled, and the postfix is part of URI > > path, so it will stay untouched. > > IMHO the spec allows it, in the 9.1. Request Parameters: > > "Note: The return_to URL MAY be used as a mechanism for > the Relying Party to attach context about the authentication > request to the authentication response. This document does not > define a mechanism by which the RP can ensure that query parameters > are not modified by outside parties; such a mechanism can be defined > by the RP itself." Yes, but it also implies that this method may be fragile. URI postfix seems to be more robust. > Example when programmer may want to add query parameters another > than authentication transaction ID: > 1. user (guest) tries to access a page requiring authentication. > 2. he is redirected to login page. > 3. openid authentication is performed > 4. the page user wanted to access initially (from the step 1) > is displayed. > > Programmer may want to pull the URL of the initial page through > all the process using query parameters (although is possible > to store it on the server, as we store openid auth. sessions). I thought initially about keeping such information in ID object, but it is unRESTful and keeps too much burden on the server. I just added the ADD-POSTFIX-TO-URI function, which keeps the query part and adds trailing slash if the base URI doesn't end with one, and use it to get the final return_to URI. -- -><- Maciej 'japhy' Pasternacki -><- http://www.pasternacki.net/ -><- From avodonosov at yandex.ru Sun Jul 20 17:50:27 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Sun, 20 Jul 2008 20:50:27 +0300 Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <1216574913.10126.209.camel@localhost> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> <1216561225.10126.175.camel@localhost> <64029.88.73.215.244.1216567677.squirrel@mail.stardawn.org> <1216570326.10126.196.camel@localhost> <1216570501.10126.199.camel@localhost> <109794029.20080720194451@yandex.ru> <1216574913.10126.209.camel@localhost> Message-ID: <610034262.20080720205027@yandex.ru> on Sunday, July 20, 2008, 8:28:33 PM Maciek wrote: > On Sun, 2008-07-20 at 19:44 +0300, Anton Vodonosov wrote: >> > Update (I forgot to add this): I used URI postfix instead of GET >> > parameters because OpenID spec is not clear on how the OPs should treat >> > existing GET parameters in incoming "openid.return_to" fields. The GET >> > parameters might get lost or mangled, and the postfix is part of URI >> > path, so it will stay untouched. >> >> IMHO the spec allows it, in the 9.1. Request Parameters: >> >> "Note: The return_to URL MAY be used as a mechanism for >> the Relying Party to attach context about the authentication >> request to the authentication response. This document does not >> define a mechanism by which the RP can ensure that query parameters >> are not modified by outside parties; such a mechanism can be defined >> by the RP itself." > Yes, but it also implies that this method may be fragile. URI postfix > seems to be more robust. They mean that the spec does not define a protection from intentional cracking - changing the values to imitate different "context about the authentication request". I.e. we should not attach really sensitive information to the context until we defined a way to verify the context. The same applies to URI postfix. The setion 11.1 also explicitly mentions query parameters in the return_to URI. -Anton From leslie.polzer at gmx.net Sun Jul 20 17:50:41 2008 From: leslie.polzer at gmx.net (Leslie P. Polzer) Date: Sun, 20 Jul 2008 19:50:41 +0200 (CEST) Subject: [cl-openid-devel] What happens after verification? In-Reply-To: <1216570326.10126.196.camel@localhost> References: <63697.88.73.251.157.1216476666.squirrel@mail.stardawn.org> <3371536.20080719174335@yandex.ru> <63267.88.73.215.244.1216542841.squirrel@mail.stardawn.org> <1216561225.10126.175.camel@localhost> <64029.88.73.215.244.1216567677.squirrel@mail.stardawn.org> <1216570326.10126.196.camel@localhost> Message-ID: <62257.88.73.215.244.1216576241.squirrel@mail.stardawn.org> > Use trailing slash: Whoo, what a gotcha. > At the moment (and the prototype will stay this way), the final result > page for all authentication requests is the HTML page with reply > details, no further redirections. If you wish to hack the possibility > of integration into real site (I wouldn't recommend this), you can add > keyword parameter CALLBACK and/or IMMEDIATE-CALLBACK to > INITIATE-AUTHORIZATION (or just check if the IMMEDIATE-P is a function), > push (cons :CALLBACK CALLBACK) to ID alist, and call appropriate element > from the ID alist in either handler that calls HANDLE-INDIRECT-REPLY, or > make HANDLE-OPENID-REQUEST call the callback if present. Before the > refactoring, however, you are on your own and I don't recommend actually > using this code as it is now. I may incorporate your patch into the > prototype, but I will focus now on having the provider, refactoring and > providing proper API. Will check this out, thanks. Leslie From avodonosov at yandex.ru Mon Jul 28 20:22:46 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Mon, 28 Jul 2008 23:22:46 +0300 Subject: [cl-openid-devel] announcment: provider prototype Message-ID: <1847151267.20080728232246@yandex.ru> Hi All. For those who is interested to try the work-in-progress library, Maciej has finished provider prototype. Best regards, -Anton From maciej at pasternacki.net Wed Jul 30 11:03:04 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Wed, 30 Jul 2008 13:03:04 +0200 Subject: [cl-openid-devel] Re: cl-openid: API design, code finalization and nearest future plans In-Reply-To: <1783167532.20080730020231@yandex.ru> (Anton Vodonosov's message of "Wed\, 30 Jul 2008 02\:02\:31 +0300") References: <1783167532.20080730020231@yandex.ru> Message-ID: Hello, Since this is not personal message, but design discussion, Cc: to development list so that anyone interested can chime in. Anton Vodonosov writes: > The SoC programs comes to its end. It is time to finalize the code > and write documentation. First of all, lets discuss what remains > to be done in the code: > > - what to make the public interface of the library > - what to keep private > - what to left as a responsibility of the library user > > In short, I think current design is adequate and requires only small > refinement. Below is my view of this. As I wrote in yesterday's report, there's one more thing I decided to change. I'd wish to turn from alists representing messages to OPENID-MESSAGE structure (it?s just a struct, since there?s no need for OOP here). The structure would be a thin layer atop parameter alist, plus accessors. This may make the code cleaner by use of clearly named accessors instead of sprinkling code with AGETs. Also, commonly used lookups (such as namespace check to determine protocol version) can be moved to struct fields, which would make many alist lookups unnecessary. This is actually not a major change, but one I see really useful for cleaning up the code. > For the Relying Party two functions are intended for most of > the library users: > > (initiate-authentication relying-party given-id return-to > realm &key immediate-p) > Performs dicsovery, association, creates and stores authentication > transaction object in the relying-party under unique key; returns URI > to redirect user browser. > > (handle-indirect-response relying-party requested-url parameters) > ;; I am not sure here, maybe it is sufficient to have just one > ;; parameter - requested-url including query part. > Lookups the authentication transaction object in the relying-party > by unique key in the requested-url (or parameters). Verifies the assertion. > Returns: authenticated identity, authentication failture or setup-needed. > > Here relying-party parameter is an object encapsulating current *ids*, > *associations* and *nonces*. I agree. That?s also pretty much the same API as python-openid?s (which is a bit more convoluted because it?s more flexible; that?s what we may want to add later). Core of the script I used for testing the Provider (the general request workflow, which I called from ipython?s command line) looks like this: ,---- | c = openid.consumer.consumer.Consumer( | {}, openid.store.memstore.MemoryStore() ) | r = c.begin('http://common-lisp.net/project/cl-openid/') | | redirection = r.redirectURL('http://example.com/', 'http://example.com/', immediate=True) | | url = # paste return url from browser | q = {} | for k,v in cgi.parse_qsl(urlparse.urlparse(url)[4]): | q[k] = v.decode('utf-8') | | i = c.complete(q, 'http://example.com/') `---- Parameter parsing into a dictionary is user?s responsibility. > In addition to this we may provide functions that more or less correspond > to the basic protocol operations described in the spec: > > discover > associate > request-authentication-uri > veryfy-assertion I think I?ll create either a class, or a structure (didn?t decided yet whether OO would be needed) instead of an ?id? alist. These parts of API may be exported, and it would be glue between ?id? and RP object. I didn?t settle yet on a better name for what is currently ?id? alist. > And perhaps even > > kv-encode > parse-kv > btwoc > base64-btwoc I think those may stay internal, and some MESSAGE struct API would be exported. I think the rule of thumb may be to export things that seem actually usable by someone wishing to use the library as a whole, not only some parts of it as building blocks, and then consider exporting other functions or features when someone asks for it on development list. > Creating user interface (login form, result page, etc.) and creation > of web server handlers is responsibility of the library user. I agree. This way, all the parts labeled ?Hunchentoot-specific? will be provided as example implementations, not as a part of code. These will actually need to be tailored to specific app, so providing these parts as a code will not be actually useful. > For the provider we offer protocol primitives to the library user: > > (create-asssociation provider parameters ssl-p) > (check-authentication provider parameters) > (error-response ...) > All these return a string to be used as a response to > direct HTTP request. > > (positive-assertion-uri provider setup-parameters) > (negative-assertion-uri provider setup-parameters) > Both return URL to redirect user's browser to. > > The PROVIDER parameter here is an object encapsulating all the current > provider-related globals. So, INDIRECT-RESPONSE would go to an example, INDIRECT-RESPONSE-URI, ERROR-RESPONSE and DIRECT-RESPONSE will be exit points, and entry points will be registered callbacks. I have to decide whether they?d be slots containing functions, or specialized methods. I?m not sure whether to expose CREATE-ASSOCIATION. I?d rather lean to exposing association preferences via provider object. > Library user is responsible for creation of web server handler for the > OP endpoint URI, based on example we provide (current handle-openid-provider-request > function). This handler will dispatch to a necessary protocol > primitive based on the "openid.mode" HTTP request parameter. > User handles "checkid_immediate" and "checkid_setup" as he wants. > > Note, this design, in particular, eliminates server portability > question. This is great idea, something I?ve started to consider lately after looking at python-openid, but it didn?t take enough shape to be posted yet. Let?s go for it. For the provider part, I?ll also look into python-openid for inspiration, its API seems good, flexible and it is tested. > Please provide your comments. In your blog you mentioned some MESSAGE > object and I have impression that you are planing more complex > refractoring. Not really. The OpenID protocol is concentrated on exchanging messages. The messages take different forms, external encodings and transmission channels, but they?re essentially same thing all over. Protocol draws a distinct line between logic (behaviour) and data (message encoding, decoding, handling). In current code, it is not so. The message handling code is mixed with logic, and done with general functions. What I want to do is to separate message-handling code to its own file, with clearly named functions and accessors. Consider the fragment from auth-request.lisp: ,---- | (let ((response (direct-request (aget :op-endpoint-url id) | (acons "openid.mode" "check_authentication" | (remove "openid.mode" parameters | :key #'car | :test #'string=))))) | ?) `---- Protocol logic is mixed with low-level message mangling. I want it to look more like this: ,---- | (let ((response (direct-request (endpoint-url auth-process) | (copy-message response | :mode "check_authentication")))) | ?) `---- This should also improve testability ? it should be easy to write tests for internal message API, and it would ensure there are no alist-mangling-level bugs in the conversation implementation, so only the behaviour would need to be tested there. > After discussing API and refactoring, I hope we finish the coding ASAP > and start documentation. > > As a program mentor, I postpone http-client and storage backend > portability, until we will complete documentation and release > a library, even despite these portability issues looks simple. > I hope we will produce complete library by the program finish, > and undocumented code may be qualified more like as unfinished work, > then as complete library. Agreed. > Good example is Edi Weit's documentation and I hope we will provide > something similar: short summary, links to specifications, breaf of > protocol (very short but clean, for details users may read specs), > documentation for all exported symbols, function parameters, > installation and dependencies, etc. We can even start from Edi?s DOCUMENTATION-TEMPLATE output. I was even thinking for a while about hacking it to be able to actually use it for generating final doc, not only the template, but it would be too much work to do right now. > We need at least two examples: for RP and OP, based on > handle-openid-request and handle-openid-provider-request. > Samples must be simple, short, self-contained, fully functioning, > single file working web sites. No portability over web server > is necessary, to avoid obscuring open-id protocol and library API. > If some function is used in both - duplicate, to keep sample > single-file. > > Every protocol related invocation must be commented, to make > users not familiar with open-id grasp the protocol idea from > the code. I will probably copy and polish a bit the Hunchentoot-specific parts of relying-party.lisp and provider.lisp ? most of example code is already done. I agree about the form. > I feel we are short of time. I think there is enough time to provide complete package with docs, I think (without optional features, though). There is not really much refactoring to do, and final week can be used for polishing documentation, bugfixing and testing. I?ll add the docstrings and exports as I go with refactoring. Regards, Maciej. From avodonosov at yandex.ru Wed Jul 30 23:12:19 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Thu, 31 Jul 2008 02:12:19 +0300 Subject: [cl-openid-devel] provider API (was: cl-openid: API design, code finalization and nearest future plans) In-Reply-To: References: <1783167532.20080730020231@yandex.ru> Message-ID: <1325144550.20080731021219@yandex.ru> on Wednesday, July 30, 2008, 2:03:04 PM Maciek wrote: >> For the provider we offer protocol primitives to the library user: >> >> (create-asssociation provider parameters ssl-p) >> (check-authentication provider parameters) >> (error-response ...) >> All these return a string to be used as a response to >> direct HTTP request. >> >> (positive-assertion-uri provider setup-parameters) >> (negative-assertion-uri provider setup-parameters) >> Both return URL to redirect user's browser to. >> >> The PROVIDER parameter here is an object encapsulating all the current >> provider-related globals. > So, INDIRECT-RESPONSE would go to an example, INDIRECT-RESPONSE-URI, > ERROR-RESPONSE and DIRECT-RESPONSE will be exit points, and entry > points will be registered callbacks. I have to decide whether they?d > be slots containing functions, or specialized methods. > I?m not sure whether to expose CREATE-ASSOCIATION. I?d rather lean to > exposing association preferences via provider object. >> Library user is responsible for creation of web server handler for the >> OP endpoint URI, based on example we provide (current handle-openid-provider-request >> function). This handler will dispatch to a necessary protocol >> primitive based on the "openid.mode" HTTP request parameter. >> User handles "checkid_immediate" and "checkid_setup" as he wants. >> >> Note, this design, in particular, eliminates server portability >> question. > This is great idea, something I?ve started to consider lately after > looking at python-openid, but it didn?t take enough shape to be posted > yet. Let?s go for it. What I mean, the user must create something like following code, based on the pattern we will provide in the example: (define-easy-handler (opendid-provider-endpoint "/openid-provider-endpoint") ((mode :real-name "openid.mode") (id :real-name "openid.identity")) (let ((params (append (hunchentoot:post-parameters) (hunchentoot:get-parameters)))) (cond ((string= mode "associate") (cl-openid:create-association *provider* params hunchentoot:ssl-p)) ((string= mode "checkid_immediate") ;; here user's code cames, for example: (if (and (string= (session-value 'cur-user) id) ;; BTW, it looks like we completelly ;; missed return_to verification ;; based on realm; see 9.2.1 ;; we must provide some function(s) for this (cl-open-id:realm-is-good ...)) (hunchentoot:redirect (positive-assertion-uri *provider* params)) (hunchentoot:redirect (negative-assertion-uri *provider* params))) ((string= mode "checkid_setup") ;; here user's defined code too ... ) ((string= mode "check_authentication") (check-authentication *provider* params)) (t (error-response (format nil "Unknown openid.mode ~S" mode)))))) I.e. no callbacks, user does not plug into our code, but wraps our code into his handler. I suspect this would be simpler for him. He must dispatch all the modes to predefined functions, except for "checkid_setup" and "checkid_immediate" that he handles himself. While writing this code sketch, I realized that not all the details are clear, e.g. glaring oversight is the return-to verification based on realm. More tomorrow, it is late now. We need to think out the details carefully. Best regards, -Anton From avodonosov at yandex.ru Thu Jul 31 00:02:07 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Thu, 31 Jul 2008 03:02:07 +0300 Subject: [cl-openid-devel] message object (was: cl-openid: API design, code finalization and nearest future plans) In-Reply-To: References: <1783167532.20080730020231@yandex.ru> Message-ID: <755645306.20080731030207@yandex.ru> on Wednesday, July 30, 2008, 2:03:04 PM Maciek wrote: > As I wrote in yesterday's report, there's one more thing I decided to > change. I'd wish to turn from alists representing messages to > OPENID-MESSAGE structure (it?s just a struct, since there?s no need > for OOP here). The structure would be a thin layer atop parameter > alist, plus accessors. This may make the code cleaner by use of > clearly named accessors instead of sprinkling code with AGETs. Also, > commonly used lookups (such as namespace check to determine protocol > version) can be moved to struct fields, which would make many alist > lookups unnecessary. > This is actually not a major change, but one I see really useful for > cleaning up the code. ... >> Please provide your comments. In your blog you mentioned some MESSAGE >> object and I have impression that you are planing more complex >> refractoring. > Not really. The OpenID protocol is concentrated on exchanging > messages. The messages take different forms, external encodings and > transmission channels, but they?re essentially same thing all over. > Protocol draws a distinct line between logic (behaviour) and data > (message encoding, decoding, handling). > In current code, it is not so. The message handling code is mixed > with logic, and done with general functions. What I want to do is to > separate message-handling code to its own file, with clearly named > functions and accessors. > Consider the fragment from auth-request.lisp: > ,---- > | (let ((response (direct-request (aget :op-endpoint-url id) > | (acons "openid.mode" "check_authentication" > | (remove "openid.mode" parameters > | :key #'car > | :test #'string=))))) > | ?) > `---- > Protocol logic is mixed with low-level message mangling. I want it to > look more like this: > ,---- > | (let ((response (direct-request (endpoint-url auth-process) > | (copy-message response > | :mode "check_authentication")))) > | ?) > `---- > This should also improve testability ? it should be easy to write > tests for internal message API, and it would ensure there are no > alist-mangling-level bugs in the conversation implementation, so only > the behaviour would need to be tested there. OpenID messages are key-value lists, so alists are close enough... Of course we should not sprinkle the code with AGETs, but you can defun clearly named accessors operating directly on alists, without introducing a MESSAGE struct: (defun get-field (msg key) (aget key msg)) (defun copy-msg (msg alist-to-add) (append alist-to-add (remove-if (lambda (key) (member key alist-to-add :key #'car :test #'string=)) msg :key #'car))) (copy-msg response '(("mode" . "check_authentication"))) (The functions have not been tested) Defining copy-msg to accept parameters as in your example is not a problem too. As for caching namespace check and other lookups into the MESSAGE struct fields, it is unnecessary - alists in questing are short and lookups are very cheap; also, in many cases namespace check is performed only one, maybe two times during message lifetime, so you will not save any performance (to be precise, you may even lose it - parsing server parameters into message struct has some cost too). In sort, considering performance questions here is an exactly "preliminary optimization". As I see Python's open-id message class deals with some namespaces for parameters, but this is for extensions as I understand and we do not need it now. I will try to think more about the messages tomorrow too. Best regards, -Anton From maciej at pasternacki.net Thu Jul 31 08:57:01 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Thu, 31 Jul 2008 10:57:01 +0200 Subject: [cl-openid-devel] Re: message object In-Reply-To: <755645306.20080731030207@yandex.ru> (Anton Vodonosov's message of "Thu\, 31 Jul 2008 03\:02\:07 +0300") References: <1783167532.20080730020231@yandex.ru> <755645306.20080731030207@yandex.ru> Message-ID: Anton Vodonosov writes: >>> Please provide your comments. In your blog you mentioned some MESSAGE >>> object and I have impression that you are planing more complex >>> refractoring. > >> Not really. The OpenID protocol is concentrated on exchanging >> messages. The messages take different forms, external encodings and >> transmission channels, but they?re essentially same thing all over. >> Protocol draws a distinct line between logic (behaviour) and data >> (message encoding, decoding, handling). > >> In current code, it is not so. The message handling code is mixed >> with logic, and done with general functions. What I want to do is to >> separate message-handling code to its own file, with clearly named >> functions and accessors. > >> Consider the fragment from auth-request.lisp: > >> ,---- >> | (let ((response (direct-request (aget :op-endpoint-url id) >> | (acons "openid.mode" "check_authentication" >> | (remove "openid.mode" parameters >> | :key #'car >> | :test #'string=))))) >> | ?) >> `---- > >> Protocol logic is mixed with low-level message mangling. I want it to >> look more like this: > >> ,---- >> | (let ((response (direct-request (endpoint-url auth-process) >> | (copy-message response >> | :mode "check_authentication")))) >> | ?) >> `---- > >> This should also improve testability ? it should be easy to write >> tests for internal message API, and it would ensure there are no >> alist-mangling-level bugs in the conversation implementation, so only >> the behaviour would need to be tested there. > > OpenID messages are key-value lists, so alists are close enough... > > Of course we should not sprinkle the code with AGETs, but you can defun > clearly named accessors operating directly on alists, without introducing > a MESSAGE struct: [cut code] Yes, accessors working directly on alists may be good enough. One thing that I'd prefer about struct would be that it's possible to modify a struct in-place, but that's a really minor issue. You're right - I'm overengineering and optimizing prematurely. Let's stay with alists and just do some accessors for them. > As I see Python's open-id message class deals with some namespaces > for parameters, but this is for extensions as I understand and > we do not need it now. Namespaces are also possible with alists, sort of like what xmls does with XML namespaces: CAR is a cons (key . namespace-uri), which is as searchable as simple one-element key. However, you're right that we don't need this now. Regards, Maciej. From maciej at pasternacki.net Thu Jul 31 13:25:18 2008 From: maciej at pasternacki.net (Maciek Pasternacki) Date: Thu, 31 Jul 2008 15:25:18 +0200 Subject: [cl-openid-devel] Re: provider API In-Reply-To: <1325144550.20080731021219@yandex.ru> (Anton Vodonosov's message of "Thu\, 31 Jul 2008 02\:12\:19 +0300") References: <1783167532.20080730020231@yandex.ru> <1325144550.20080731021219@yandex.ru> Message-ID: Anton Vodonosov writes: > What I mean, the user must create something like following code, > based on the pattern we will provide in the example: > > (define-easy-handler (opendid-provider-endpoint > "/openid-provider-endpoint") > ((mode :real-name "openid.mode") > (id :real-name "openid.identity")) > (let ((params (append (hunchentoot:post-parameters) > (hunchentoot:get-parameters)))) > (cond ((string= mode "associate") > (cl-openid:create-association *provider* > params > hunchentoot:ssl-p)) > ((string= mode "checkid_immediate") > ;; here user's code cames, for example: > (if (and (string= (session-value 'cur-user) > id) > ;; BTW, it looks like we completelly > ;; missed return_to verification > ;; based on realm; see 9.2.1 > ;; we must provide some function(s) for this > (cl-open-id:realm-is-good ...)) > (hunchentoot:redirect (positive-assertion-uri *provider* > params)) > (hunchentoot:redirect (negative-assertion-uri *provider* > params))) > ((string= mode "checkid_setup") > ;; here user's defined code too > ... ) > ((string= mode "check_authentication") > (check-authentication *provider* params)) > (t (error-response (format nil > "Unknown openid.mode ~S" > mode)))))) > > I.e. no callbacks, user does not plug into our code, but wraps our > code into his handler. I suspect this would be simpler for him. > He must dispatch all the modes to predefined functions, except > for "checkid_setup" and "checkid_immediate" that he handles > himself. I don't like this. This way, we put too much of protocol-related code in user's hands. That's what higher-order functions are for; and protocol implementation really belongs to our library. I see it more like this: (defvar *op* (make-instance 'openid-provider ;; true -> id_res, false -> setup_needed, error raised -> error :immediate-callback #'(lambda (provider message) (string= (session-value 'cur-user) (claimed-id message))) ;; Do own authentication (e.g. redirect to login page), finally redirect :setup-callback #'(lambda (provider message) ...))) ;; Or: (defclass my-op (openid-provider) () ()) (defmethod checkid-immediate ((op my-op) message) (string= (session-value 'cur-user) (claimed-id message))) (defmethod checkid-setup ((op my-op) message) ...) (defvar *op* (make-instance 'my-op ...)) ; Maybe instead of subclassing, the EQL-specialized methods would be ; good enough? ;; Finally: (define-easy-handler (openid-provider-endpoint "/openid-provider-endpoint") () (multiple-value-bind (body status redirect-uri) (cl-openid:handle-provider-request *op* (append (get-parameters) (post-parameters))) (when redirect-uri (hunchentoot:redirect redirect-uri)) (when status (setf (hunchentoot:return-code status))) body)) It's way simpler and less fragile. There is no protocol implementation mixed into HTTP handler. > While writing this code sketch, I realized that not all the details > are clear, e.g. glaring oversight is the return-to verification based > on realm. You're right, I missed it. Just added a ticket to make sure it won't get lost. Regards, Maciej. From avodonosov at yandex.ru Thu Jul 31 22:49:41 2008 From: avodonosov at yandex.ru (Anton Vodonosov) Date: Fri, 1 Aug 2008 01:49:41 +0300 Subject: [cl-openid-devel] Re: provider API In-Reply-To: References: <1783167532.20080730020231@yandex.ru> <1325144550.20080731021219@yandex.ru> Message-ID: <525884830.20080801014941@yandex.ru> on Thursday, July 31, 2008, 4:25:18 PM Maciek wrote: > Anton Vodonosov writes: >> What I mean, the user must create something like following code, >> based on the pattern we will provide in the example: >> >> (define-easy-handler (opendid-provider-endpoint >> "/openid-provider-endpoint") >> ((mode :real-name "openid.mode") >> (id :real-name "openid.identity")) >> (let ((params (append (hunchentoot:post-parameters) >> (hunchentoot:get-parameters)))) >> (cond ((string= mode "associate") >> (cl-openid:create-association *provider* >> params >> hunchentoot:ssl-p)) >> ((string= mode "checkid_immediate") >> ;; here user's code cames, for example: >> (if (and (string= (session-value 'cur-user) >> id) >> ;; BTW, it looks like we completelly >> ;; missed return_to verification >> ;; based on realm; see 9.2.1 >> ;; we must provide some function(s) for this >> (cl-open-id:realm-is-good ...)) >> (hunchentoot:redirect (positive-assertion-uri *provider* >> params)) >> (hunchentoot:redirect (negative-assertion-uri *provider* >> params))) >> ((string= mode "checkid_setup") >> ;; here user's defined code too >> ... ) >> ((string= mode "check_authentication") >> (check-authentication *provider* params)) >> (t (error-response (format nil >> "Unknown openid.mode ~S" >> mode)))))) >> >> I.e. no callbacks, user does not plug into our code, but wraps our >> code into his handler. I suspect this would be simpler for him. >> He must dispatch all the modes to predefined functions, except >> for "checkid_setup" and "checkid_immediate" that he handles >> himself. > I don't like this. This way, we put too much of protocol-related code > in user's hands. That's what higher-order functions are for; and > protocol implementation really belongs to our library. I see it more > like this: > (defvar *op* > (make-instance 'openid-provider > ;; true -> id_res, false -> setup_needed, error raised -> error > :immediate-callback #'(lambda (provider message) > (string= (session-value 'cur-user) > (claimed-id message))) > ;; Do own authentication (e.g. redirect to login page), finally redirect > :setup-callback #'(lambda (provider message) > ...))) > ;; Or: > (defclass my-op (openid-provider) () > ()) > (defmethod checkid-immediate ((op my-op) message) > (string= (session-value 'cur-user) (claimed-id message))) > (defmethod checkid-setup ((op my-op) message) > ...) > (defvar *op* > (make-instance 'my-op ...)) > ; Maybe instead of subclassing, the EQL-specialized methods would be > ; good enough? > ;; Finally: > (define-easy-handler (openid-provider-endpoint "/openid-provider-endpoint") () > (multiple-value-bind (body status redirect-uri) > (cl-openid:handle-provider-request *op* (append > (get-parameters) (post-parameters))) > (when redirect-uri > (hunchentoot:redirect redirect-uri)) > (when status > (setf (hunchentoot:return-code status))) > body)) > It's way simpler and less fragile. There is no protocol > implementation mixed into HTTP handler. Maybe, I can not say for sure now. Initially I too thought about a single entry point that user must call. But after the entry point started looking requiring complex parameterization, I started considering the variant I provided above. It is like in TCP/IP. bind, then listen, then accept is a commonly known pattern, but sockets API (at least BSD sockets, and others modeled after that) does not provide a single function for this. User must understand what is IP addres, port, bind, listen, accept and implement the pattern. Perhaps another advantage of more protocol-oriented API is that user must learn only one protocol - OpenID, instead of learning two: OpenID and a 'protocol' of extending our API. With explicit OpenID protocol flow in his code, user feel understanding and controlling over what is happening, which is essential characteristic of good design (of any technical system, be it API, UI or whatever). Anyway, I suggest to start coding the provider example in a separate package. The example must handle all the relevant use cases: - immediate requests, - checkid_setup requests with login, - handle realms. For example, when you login to livejournal by a blogger account, blogger first time asks you: Tell http://www.livejournal.com/ that you own http://yournick.blogger.com ? - Yes, just once. - Yes, always. - No. If you answer "Yes, always", next time it will not ask. - invalidate associations (btw, another missed point in the current provider, see the section 10 of the spec). - maybe something else I missed. When you polish the example code, you will have the API. What is good for you, will be good for others. Remaining refactoring may be done during this process. Regards, -Anton