[GENERIC] Zend_Translate:
[zend.git] / documentation / manual / en / module_specs / Zend_InfoCard-Basics.xml
blob559b096c52322ec07b34aebabea14ec502c436bc
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.infocard.basics">
4     <title>Introduction</title>
6     <para>
7         The <classname>Zend_InfoCard</classname> component implements relying-party
8         support for Information Cards. Information Cards are used for identity
9         management on the internet and authentication of users to web sites. The web sites
10         that the user ultimately authenticates to are called <emphasis>relying-parties</emphasis>.
11     </para>
13     <para>
14         Detailed information about information cards and their importance to the
15         internet identity metasystem can be found on the <ulink
16             url="http://www.identityblog.com/">IdentityBlog</ulink>.
17     </para>
19     <sect2 id="zend.infocard.basics.theory">
20         <title>Basic Theory of Usage</title>
22         <para>
23             Usage of <classname>Zend_InfoCard</classname> can be done one of two ways:
24             either as part of the larger <classname>Zend_Auth</classname> component via
25             the <classname>Zend_InfoCard</classname> authentication adapter or as a
26             stand-alone component. In both cases an information card can be
27             requested from a user by using the following <acronym>HTML</acronym> block in your
28             <acronym>HTML</acronym> login form:
29         </para>
31         <programlisting language="html"><![CDATA[
32 <form action="http://example.com/server" method="POST">
33   <input type='image' src='/images/ic.png' align='center'
34         width='120px' style='cursor:pointer' />
35   <object type="application/x-informationCard"
36           name="xmlToken">
37    <param name="tokenType"
38          value="urn:oasis:names:tc:SAML:1.0:assertion" />
39    <param name="requiredClaims"
40          value="http://.../claims/privatepersonalidentifier
41          http://.../claims/givenname
42          http://.../claims/surname" />
43  </object>
44 </form>
45 ]]></programlisting>
47         <para>
48             In the example above, the <code>requiredClaims</code>
49             <code>&lt;param&gt;</code> tag is used to identify pieces of
50             information known as claims (i.e. person's first name, last name)
51             which the web site (a.k.a "relying party") needs in order a user to
52             authenticate using an information card. For your reference, the full
53             <acronym>URI</acronym> (for instance the <code>givenname</code> claim) is as follows:
54             <code>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname</code>
55         </para>
57         <para>
58             When the above <acronym>HTML</acronym> is activated by a user (clicks on it), the
59             browser will bring up a card selection program which not only shows
60             them which information cards meet the requirements of the site, but
61             also allows them to select which information card to use if multiple
62             meet the criteria. This information card is transmitted as an <acronym>XML</acronym>
63             document to the specified POST <acronym>URL</acronym> and is ready to be
64             processed by the <classname>Zend_InfoCard</classname> component.
65         </para>
67         <para>
68             Note, Information cards can only be <code>HTTP POST</code>ed to
69             <acronym>SSL</acronym>-encrypted <acronym>URL</acronym>s. Please consult your web
70             server's documentation on how to set up <acronym>SSL</acronym> encryption.
71         </para>
72     </sect2>
74     <sect2 id="zend.infocard.basics.auth">
75         <title>Using as part of Zend_Auth</title>
77         <para>
78             In order to use the component as part of the <classname>Zend_Auth</classname>
79             authentication system, you must use the provided
80             <classname>Zend_Auth_Adapter_InfoCard</classname> to do so (not available in
81             the standalone <classname>Zend_InfoCard</classname> distribution). An example
82             of its usage is shown below:
83         </para>
85         <programlisting language="php"><![CDATA[
86 <?php
87 if (isset($_POST['xmlToken'])) {
89     $adapter = new Zend_Auth_Adapter_InfoCard($_POST['xmlToken']);
91     $adapter->addCertificatePair('/usr/local/Zend/apache2/conf/server.key',
92                                  '/usr/local/Zend/apache2/conf/server.crt');
94     $auth = Zend_Auth::getInstance();
96     $result = $auth->authenticate($adapter);
98     switch ($result->getCode()) {
99         case Zend_Auth_Result::SUCCESS:
100             $claims = $result->getIdentity();
101             print "Given Name: {$claims->givenname}<br />";
102             print "Surname: {$claims->surname}<br />";
103             print "Email Address: {$claims->emailaddress}<br />";
104             print "PPI: {$claims->getCardID()}<br />";
105             break;
106         case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
107             print "The Credential you provided did not pass validation";
108             break;
109         default:
110         case Zend_Auth_Result::FAILURE:
111             print "There was an error processing your credentials.";
112             break;
113     }
115     if (count($result->getMessages()) > 0) {
116         print "<pre>";
117         var_dump($result->getMessages());
118         print "</pre>";
119     }
123 <hr />
124 <div id="login" style="font-family: arial; font-size: 2em;">
125 <p>Simple Login Demo</p>
126  <form method="post">
127   <input type="submit" value="Login" />
128    <object type="application/x-informationCard" name="xmlToken">
129     <param name="tokenType"
130           value="urn:oasis:names:tc:SAML:1.0:assertion" />
131     <param name="requiredClaims"
132           value="http://.../claims/givenname
133                  http://.../claims/surname
134                  http://.../claims/emailaddress
135                  http://.../claims/privatepersonalidentifier" />
136   </object>
137  </form>
138 </div>
139 ]]></programlisting>
141         <para>
142             In the example above, we first create an instance of the
143             <classname>Zend_Auth_Adapter_InfoCard</classname> and pass the <acronym>XML</acronym>
144             data posted by the card selector into it. Once an instance has been created you
145             must then provide at least one <acronym>SSL</acronym> certificate public/private key
146             pair used by the web server that received the <code>HTTP
147             POST</code>. These files are used to validate the destination
148             of the information posted to the server and are a requirement when
149             using Information Cards.
150         </para>
152         <para>
153             Once the adapter has been configured, you can then use the standard
154             <classname>Zend_Auth</classname> facilities to validate the provided
155             information card token and authenticate the user by examining the
156             identity provided by the <methodname>getIdentity()</methodname> method.
157         </para>
158     </sect2>
160     <sect2 id="zend.infocard.basics.standalone">
161         <title>Using the Zend_InfoCard component standalone</title>
163         <para>
164             It is also possible to use the <classname>Zend_InfoCard</classname> component as a
165             standalone component by interacting with the
166             <classname>Zend_InfoCard</classname> class directly. Using the
167             <classname>Zend_InfoCard</classname> class is very similar to its use with the
168             <classname>Zend_Auth</classname> component. An example of its use is shown below:
169         </para>
171         <programlisting language="php"><![CDATA[
172 <?php
173 if (isset($_POST['xmlToken'])) {
174     $infocard = new Zend_InfoCard();
175     $infocard->addCertificatePair('/usr/local/Zend/apache2/conf/server.key',
176                                   '/usr/local/Zend/apache2/conf/server.crt');
178     $claims = $infocard->process($_POST['xmlToken']);
180     if($claims->isValid()) {
181         print "Given Name: {$claims->givenname}<br />";
182         print "Surname: {$claims->surname}<br />";
183         print "Email Address: {$claims->emailaddress}<br />";
184         print "PPI: {$claims->getCardID()}<br />";
185     } else {
186         print "Error Validating identity: {$claims->getErrorMsg()}";
187     }
190 <hr />
191 <div id="login" style="font-family: arial; font-size: 2em;">
192  <p>Simple Login Demo</p>
193  <form method="post">
194   <input type="submit" value="Login" />
195    <object type="application/x-informationCard" name="xmlToken">
196     <param name="tokenType"
197           value="urn:oasis:names:tc:SAML:1.0:assertion" />
198     <param name="requiredClaims"
199           value="http://.../claims/givenname
200                  http://.../claims/surname
201                  http://.../claims/emailaddress
202                  http://.../claims/privatepersonalidentifier" />
203    </object>
204  </form>
205 </div>
206 ]]></programlisting>
208         <para>
209             In the example above, we use the <classname>Zend_InfoCard</classname> component
210             independently to validate the token provided by the user. As was the
211             case with the <classname>Zend_Auth_Adapter_InfoCard</classname>, we create an
212             instance of <classname>Zend_InfoCard</classname> and then set one or more
213             <acronym>SSL</acronym> certificate public/private key pairs used by the web server. Once
214             configured, we can use the <methodname>process()</methodname> method to process
215             the information card and return the results.
216         </para>
217     </sect2>
219     <sect2 id="zend.infocard.basics.claims">
220         <title>Working with a Claims object</title>
222         <para>
223             Regardless of whether the <classname>Zend_InfoCard</classname> component is used as
224             a standalone component or as part of <classname>Zend_Auth</classname> via
225             <classname>Zend_Auth_Adapter_InfoCard</classname>, the ultimate
226             result of the processing of an information card is a
227             <classname>Zend_InfoCard_Claims</classname> object. This object contains the
228             assertions (a.k.a. claims) made by the submitting user based on the
229             data requested by your web site when the user authenticated. As
230             shown in the examples above, the validity of the information card
231             can be ascertained by calling the
232             <methodname>Zend_InfoCard_Claims::isValid()</methodname> method. Claims
233             themselves can either be retrieved by simply accessing the
234             identifier desired (i.e. <code>givenname</code>) as a property of
235             the object or through the <methodname>getClaim()</methodname> method.
236         </para>
238         <para>
239             In most cases you will never need to use the <methodname>getClaim()</methodname>
240             method. However, if your <code>requiredClaims</code> mandate that
241             you request claims from multiple different sources/namespaces then
242             you will need to extract them explicitly using this method (simply
243             pass it the full <acronym>URI</acronym> of the claim to retrieve its value from within
244             the information card). Generally speaking however, the
245             <classname>Zend_InfoCard</classname> component will set the default
246             <acronym>URI</acronym> for claims to be the one used the most frequently within the
247             information card itself and the simplified property-access method can be used.
248         </para>
250         <para>
251             As part of the validation process, it is the developer's responsibility to
252             examine the issuing source of the claims contained within the
253             information card and to decide if that source is a trusted source of
254             information. To do so, the <methodname>getIssuer()</methodname> method is
255             provided within the <classname>Zend_InfoCard_Claims</classname> object which
256             returns the <acronym>URI</acronym> of the issuer of the information card claims.
257         </para>
258     </sect2>
260     <sect2 id="zend.infocard.basics.attaching">
261         <title>Attaching Information Cards to existing accounts</title>
263         <para>
264             It is possible to add support for information cards to an existing
265             authentication system by storing the private personal identifier
266             (PPI) to a previously traditionally-authenticated account and
267             including at least the
268             <code>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier</code>
269             claim as part of the <code>requiredClaims</code> of the request. If
270             this claim is requested then the <classname>Zend_InfoCard_Claims</classname>
271             object will provide a unique identifier for the specific card that
272             was submitted by calling the <methodname>getCardID()</methodname> method.
273         </para>
275         <para>
276             An example of how to attach an information card to an existing
277             traditional-authentication account is shown below:
278         </para>
280         <programlisting language="php"><![CDATA[
281 // ...
282 public function submitinfocardAction()
284     if (!isset($_REQUEST['xmlToken'])) {
285         throw new ZBlog_Exception('Expected an encrypted token ' .
286                                   'but was not provided');
287     }
289     $infoCard = new Zend_InfoCard();
290     $infoCard->addCertificatePair(SSL_CERTIFICATE_PRIVATE,
291                                   SSL_CERTIFICATE_PUB);
293     try {
294         $claims = $infoCard->process($request['xmlToken']);
295     } catch(Zend_InfoCard_Exception $e) {
296         // TODO Error processing your request
297         throw $e;
298     }
300     if ($claims->isValid()) {
301         $db = ZBlog_Data::getAdapter();
303         $ppi = $db->quote($claims->getCardID());
304         $fullname = $db->quote("{$claims->givenname} {$claims->surname}");
306         $query = "UPDATE blogusers
307                      SET ppi = $ppi,
308                          real_name = $fullname
309                    WHERE username='administrator'";
311         try {
312             $db->query($query);
313         } catch(Exception $e) {
314             // TODO Failed to store in DB
315         }
317         $this->view->render();
318         return;
319     } else {
320         throw new
321             ZBlog_Exception("Infomation card failed security checks");
322     }
324 ]]></programlisting>
325     </sect2>
327     <sect2 id="zend.infocard.basics.adapters">
328         <title>Creating Zend_InfoCard Adapters</title>
330         <para>
331             The <classname>Zend_InfoCard</classname> component was designed to allow for
332             growth in the information card standard through the use of a modular
333             architecture. At this time, many of these hooks are unused and can be
334             ignored, but there is one class that should be written for
335             any serious information card implementation: the
336             <classname>Zend_InfoCard</classname> adapter.
337         </para>
339         <para>
340             The <classname>Zend_InfoCard</classname> adapter is used as a callback
341             mechanism within the component to perform various tasks, such as
342             storing and retrieving Assertion IDs for information cards when they
343             are processed by the component. While storing the assertion IDs of
344             submitted information cards is not necessary, failing to do so opens
345             up the possibility of the authentication scheme being compromised
346             through a replay attack.
347         </para>
349         <para>
350             To prevent this, one must implement the
351             <classname>Zend_InfoCard_Adapter_Interface</classname> and set an
352             instance of this interface prior to calling either the
353             <methodname>process()</methodname> (standalone) or
354             <methodname>authenticate()</methodname> method as a <classname>Zend_Auth</classname>
355             adapter. To set this interface, the <methodname>setAdapter()</methodname> method should
356             be used. In the example below, we set a <classname>Zend_InfoCard</classname> adapter and
357             use it in our application:
358         </para>
360         <programlisting language="php"><![CDATA[
361 class myAdapter implements Zend_InfoCard_Adapter_Interface
363     public function storeAssertion($assertionURI,
364                                    $assertionID,
365                                    $conditions)
366     {
367         /* Store the assertion and its conditions by ID and URI */
368     }
370     public function retrieveAssertion($assertionURI, $assertionID)
371     {
372         /* Retrieve the assertion by URI and ID */
373     }
375     public function removeAssertion($assertionURI, $assertionID)
376     {
377         /* Delete a given assertion by URI/ID */
378     }
381 $adapter  = new myAdapter();
383 $infoCard = new Zend_InfoCard();
384 $infoCard->addCertificatePair(SSL_PRIVATE, SSL_PUB);
385 $infoCard->setAdapter($adapter);
387 $claims = $infoCard->process($_POST['xmlToken']);
388 ]]></programlisting>
389     </sect2>
390 </sect1>
391 <!--
392 vim:se ts=4 sw=4 et: