[cl-openid-devel] Re: provider API
Maciek Pasternacki
maciej at pasternacki.net
Thu Jul 31 13:25:18 UTC 2008
Anton Vodonosov <avodonosov at yandex.ru> 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.
More information about the cl-openid-devel
mailing list