Anonymous user [OpenID enabled] [XRI enabled] [LID enabled]

LID By Example

From LID Wiki

(Redirected from LIDByExample)
Jump to: navigation, search

See also LID Profile Exchange Howto.

This is slightly out-of-date as LID has grown more modular, is based on Yadis now and supports OpenID.

After writing the first third party LID(tm) implementation, I (Dan Lyke) realized that trying to restate the process in the form of a document by example would both help me make sure that I understood the process, and provide a road map for others who came after me.

So this note is derived from the LID(tm) whitepaper, Johannes Ernst's example Perl code, and my own implementation for the Flutterby weblog content management system. See also the Implementation Notes for details of problems with the evolving spec, and how you should be liberal in what you accept.

This document assumes a fairly thorough knowledge of how "GET" CGI parameters get passed, and that you know how to "pipe" data into and out of "gpg" in your favorite development environment. I also strongly suggest that you explicitly specify the "--homedir" argument in every execution of "gpg".

For the purposes of this example, the user has a LID(tm) URL of http://user.lidentity.com/ . Note the trailing slash; its presence or absence is important. (See also LID 2.0 Canonical LID URLs)

The user is trying to log in to the example site at http://www.restrictedsite.com/, which processes its logins at that address.

Contents

Step 1: Key Creation

The user has previously created a key pair with "gpg --gen-key", and when it asked for "Real name:" typed in "http://user.lidentity.com/", and hit enter for "Email address:" and "Comment:". The public section of this key can be retrieved by going to:

http://user.lidentity.com/?lid-meta=gpg%20--export%20--armor

...and the site which you're trying to log in to will do this in step 5, below.

Step 2: www.restrictedsite.com retrieves the LID

The user enters their LID(tm) URL into a form on http://www.restrictedsite.com/, and presses "submit".

restrictedsite.com stores anything it already knows about the session somewhere that it can be retrieved with a relatively short "ticket" — for this example we'll say 9876 but it can be any thing that falls within the URL value encoding rules — and sends an HTTP redirect (302 works fine 303 is better) back to the user's browser, which points it to (all one line, in case this gets line-wrapped):

http://user.lidentity.com/?lid-action=sso-approve&lid-credtype=gpg%20--clearsign&lid-target=http://restrictedsite.com/

Note: Per the new nonce protocol, this does NOT involve adding a lid-nonce any more.

Step 3: http://user.lidentity.com/ validates the user

The user's LID(tm) software does whatever it needs to do to validate the user (user name and password, old cookie, whatever). Note that this could involve some non-browser application, keys off of a keychain USB device, it doesn't matter, as long as eventually the browser can get redirected.

Step 4: Creation of the URL that does the login

The user's LID(tm) software then generates a redirect which send the browser back to (all one line):

  http://www.restrictedsite.com/?lid=http://user.lidentity.com/&lid-credtype=gpg%20--clearsign&lid-nonce=2005-09-10T07:28:12.123Z&lid-credential=...

where

  • the value of lid-nonce is the current time at host user.lidentity.com, expressed in UTC
  • and where "..." in "credential=..." is

created by the the user's LID(tm) software performing the following process:

1. Take everything from the beginning to just prior to "&lid-credential", ie (again, all one line):
http://www.restrictedsite.com/?lid=http://user.lidentity.com%/&lid-credtype=gpg%20--clearsign&lid-nonce=2005-09-10T07:28:12.123Z
and pipe this into "gpg --clearsign". This should result in something like:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

http://www.restrictedsite.com/?lid=http://user.lidentity.com%/&lid-credtype=gpg%20--clearsign&lid-nonce=2005-09-10T07:28:12.123Z

-----BEGIN PGP SIGNATURE-----

Version: GnuPG v1.4.0 (GNU/Linux)

iD8DBQFCCvzNNmrPV+m2dK4RArX1AKCHuoocAMl7q98dymOd4rdO2NlaEQCbBp6f
UAnlIpEtc8suusCabMkgsvo=
=pKrG

-----END PGP SIGNATURE-----
2. Take the string following the hash, in this case "SHA1", append an ASCII newline character ("\n") and everything from "Version:" to (but not including) the line "-----END PGP SIGNATURE-----", and "%" escape (urlencode) the results, ie:
http://www.restrictedsite.com/?lid=http://user.lidentity.com%/&lid-credtype=gpg%20--clearsign&lid-nonce=2005-09-10T07:28:12.123Z&lid-credential=SHA1%0AVersion%3A%20GnuPG%20v1.4.0%20(GNU%2FLinux)%0A%0AiD8DBQFCCDkcNmrPV%2Bm2dK4RApnCAJ93%2BYermhVf9hDOWA1DJSByVpvWLwCfdwdq%0AffEWUmo9irjN7EI19Muu%2Bm8%3D%0A%3DnIxG

Step 5: www.restrictedsite.com validates the login URL

Upon receiving this, http://www.restrictedsite.com determines the public key of the user with the given LID(tm) URL. If this user is unknown at the site (or if the site does not store public keys of its users), it retrieves the user's key using:

http://user.lidentity.com/?meta=gpg%20--export%20--armor

and imports it by piping it to "gpg --import".

It can then verify the validity of what it was passed by taking everything to (but excluding) the '&lid-credential' and the information in the credential, recreating the PGP signature above, and sending that to "gpg --verify".

Implementation Considerations:

The LID whitepaper suggests encoding per RFC2396. In practice, it doesn't matter if you encode too much, but per RFC2396, the minimum set that needs to be escaped by replacing the character in question with "%" and a two digit hexadecimal representation of the ASCII of the character is:

 ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

And any whitespace. Note that the examples above do not necessarily all follow this convention -- on the other hand, they are more readable that way.

The time stamp in the lid-nonce is constructed according to ISO 8601 (overview), but must be in UTC and in extended format, including 3 digits after the decimal point.

Credits

Originally written by Dan Lyke. Updated for consistency with LID 2.0 by Johannes Ernst.

Personal tools