Simple Comments and OpenID (1/5)
[next] |
Simple Comments Meets OpenID
[This is a supplementary article for the Simple Comments script. For general information pertaining to the script, including the latest release download, system requirements, etc., visit the Simple Comments main page.]
Beginning with version .960, Simple Comments supports visitor logins using OpenID identifiers. For those unfamiliar with OpenID in general, I described the basics in the initial v.960 release bulletin, and I refer you to that article for relevant background information. You might also have a look at the OpenID introduction at the OpenID Wiki site. It does a good job of describing the details of the OpenID process without getting bogged down in specification-speak.
In this article, I'll discuss some of the specific architectural and developmental considerations that went into the process of OpenID-enabling the Simple Comments system. Whether you're a Simple Comments user or just a Perl coder with an interest in OpenID implementations you're welcome to follow along. Be sure to add your thoughts and experiences in our comment submission form, located at the end of the article!
Relying Parties and OpenID Providers
As mentioned in the previous article, OpenID authentication requires communication between three primary players: The end user who wishes to authenticate themselves to a site or application, the site or application that needs to verify the user and a 3rd party willing to vouch for the end user's authentication. In OpenID parlance, the site or application that needs to verify the end user is called a Relying Party, or RP, and the site willing to vouch for the user's authentication is called an OpenID Provider, or OP. The ID itself--i.e., the string the end user is claiming as their own, unique identifier--is called an OpenID Identifier, or Claimed Identifier. The goal of OpenID authentication is to positively verify that the identifier the end user is claiming as their own actually belongs to them (and no one else).
Obtaining this verification requires both direct and indirect communications between the RP and the OP.
Direct vs. Indirect Communications
Direct communications occur between an RP and OP at various points in the OpenID
protocol, and provide a means for the RP to 'discuss' something privately with the
OP in a way that others--including the end user--cannot interfere with. These communications
are straightforward in Perl, and can generally be performed by way of the
LWP::UserAgent module. For example, here's a snippet that
posts a small amount of data (in the same general manner that a Web form might) to
the fictitious application http://example.com/test.cgi:
use LWP::UserAgent ();
# Initialize the useragent
my $ua = LWP::UserAgent->new();
# Set some default values
$ua->timeout(10);
push (@{$ua->requests_redirectable},'POST');
$ua->agent('LWP Test');
# Setup data to be posted
my $post_form = { 'name' => 'foo',
'pass' => 'bar' };
# And send the post
my $res = $ua->post('http://example.com/test.cgi', $post_form);
# Test the result
if ($res->is_success) {
print $res->content;
}
else {
print 'Error retrieving document: ' . $res->status_line;
}
Following the initialization of the LWP::UserAgent
object, we set up a default timeout value, allow post requests to be redirectable
(i.e., enable the module to follow server redirects on post requests, if they're
provided), and set up our user-agent string (which will typically show up in the
host server's logs). The post method handles
all the dirty work, returning an HTTP Response object with the results
of the communication (i.e., whatever information the host returned as a result of
the request). For full details I refer you to your perldoc
documentation for LWP::UserAgent.
With OpenID, we don't know who the OP we'll be communicating with is, nor do we know if we can trust them. Original OpenID author
Brad Fitzpatrick recommends the use of the Perl module LWPx::ParanoidAgent,
a subclass of LWP::UserAgent that adds such features as
a global timeout and protection from connecting to local IP ranges, among other
goodies. Simple Comments automatically uses LWPx::ParanoidAgent
if it's available; and will otherwise fall back to LWP::UserAgent
for direct OP communications.
Indirect communications occur when the end user must be redirected to the OP (and vice versa for the return communication), with additional information provided by the RP/OP going along for the ride. Indirect communications are a critical part of the OpenID specification, since they provide both privacy for the end user (the RP cannot see the resulting interactions between the OP and end user), and they provide a means for the OP to recognize if the end user has already previously authenticated themselves. Since the end user is redirected to the OP, they (the OP) have access to any previously saved session cookies or identifiers that may be stored in the user's browser1 for that OP.
To redirect an end user's browser to the OP, the RP first determines where the end
user needs to be redirected to (i.e., what URL), and then builds that URL including
any additional parameters it needs to send to the OP. Then, the redirect itself
can be as simple as executing the redirect method of
the CGI object. The whole process might look something
like this:
use CGI ();
# Initialize the CGI object
my $cgi = CGI->new();
# Setup the redirection URL
my $redirectURL = 'http://example.com/test.cgi?param1=value1¶m2=value2';
# And send the user to it
print $cgi->redirect($redirectURL);
When a browser receives a redirect request in this manner, it automatically takes
the user to the new target URL ($redirectURL in the code
above). This typically happens in a transparent fashion; in some cases the end user
will only know the redirect has happened by checking the address in the address
bar of their browser. This type of GET redirect--where
any additional parameters are tacked onto the end of the target URL--is sufficient
for most OpenID redirection needs, and should be used whenever
possible.
Some browsers, however, limit the
length of data that can be included in a GET
request. Thus, an alternative form of redirect may be used in which a standard HTML
page is presented to the end user with a form that points to the target URL and a
button asking the user to click to proceed to the target URL (the form is nearly
always autosubmitted using JavaScript, so the user only needs to click if JavaScript
is unavailable in their browser). While not nearly as glamorous as the redirect
above, this redirect method has the distinct advantage in that additional
parameters that need to be communicated to the RP can be presented as hidden parameters
of the form, as opposed to presented literally as part of the URL. i.e., following the
above example, the HTML form sent to the browser might look something like this:
<html>
<head>
<title>OpenID Authentication Redirect</title>
<script type="text/javascript">
window.onload=function() { document.forms['openid_redirect_form'].submit(); };
</script>
</head>
<body>
<p>We are about to redirect you to another site. If you are
not redirected automatically then you can do so directly
by clicking the <strong>Continue</strong> button below.</p>
<form action="http://example.com/test.cgi"
method="post" name="openid_redirect_form">
<input type="Submit" value="Continue">
<input type="hidden" name="param1" value="value1" />
<input type="hidden" name="param2" value="value2" />
</form>
</body>
</html>
Simple Comments includes a function (called openid_redirect)
which examines the length of the URL that you wish to redirect to. If that URL is
longer than 2,000 characters, a form similar to the above is built and presented
to the end user. Otherwise, the end user is redirected using the preferred
CGI method described above.
On the next page, we'll examine the two different types of OpenID Identifiers a user may present to your login form and introduce you to XRI proxy resolvers.
1. To simplify the discussion, I'll assume throughout this article that the end user is using a standard Web browser to communicate/authenticate with the RP/OP, but theoretically, the end user might be using any type of user agent that supports redirection and HTTP/HTTPS communications.
[next] |
Created: July 31, 2008
Revised: July 31, 2008
URL: http://webreference.com/programming/perl/comments/openid/index.html

Find a programming school near you