| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.openid.provider">
- <title>Zend_OpenId_Provider</title>
- <para>
- <classname>Zend_OpenId_Provider</classname> can be used to implement OpenID
- servers. This chapter provides examples that demonstrate how to
- build a very basic server. However, for implementation of a production OpenID
- server (such as <ulink url="http://www.myopenid.com">www.myopenid.com</ulink>) you
- may have to deal with more complex issues.
- </para>
- <sect2 id="zend.openid.provider.start">
- <title>Quick start</title>
- <para>
- The following example includes code for creating a user account
- using <classname>Zend_OpenId_Provider::register</classname>. The link element with
- <command>rel="openid.server"</command> points to our own server script. If you
- submit this identity to an OpenID-enabled site, it will perform
- authentication on this server.
- </para>
- <para>
- The code before the <html> tag is just a trick that automatically
- creates a user account. You won't need such code when using real
- identities.
- </para>
- <example id="zend.openid.provider.example-1">
- <title>The Identity</title>
- <programlisting language="php"><![CDATA[
- <?php
- // Set up test identity
- define("TEST_SERVER", Zend_OpenId::absoluteURL("example-8.php"));
- define("TEST_ID", Zend_OpenId::selfURL());
- define("TEST_PASSWORD", "123");
- $server = new Zend_OpenId_Provider();
- if (!$server->hasUser(TEST_ID)) {
- $server->register(TEST_ID, TEST_PASSWORD);
- }
- ?>
- <html><head>
- <link rel="openid.server" href="<?php echo TEST_SERVER;?>" />
- </head><body>
- <?php echo TEST_ID;?>
- </body></html>
- ]]></programlisting>
- </example>
- <para>
- The following identity server script handles two kinds of requests
- from OpenID-enabled sites (for association and authentication). Both of
- them are handled by the same method:
- <classname>Zend_OpenId_Provider::handle</classname>. The two arguments to the
- <classname>Zend_OpenId_Provider</classname> constructor are <acronym>URL</acronym>s of
- login and trust pages, which ask for input from the end user.
- </para>
- <para>
- On success, the method <classname>Zend_OpenId_Provider::handle</classname>
- returns a string that should be passed back to the OpenID-enabled site. On
- failure, it returns <constant>FALSE</constant>. This example will return an
- <acronym>HTTP</acronym> 403 response if
- <classname>Zend_OpenId_Provider::handle</classname> fails. You will get this response if
- you open this script with a web browser, because it sends a non-OpenID conforming
- request.
- </para>
- <example id="zend.openid.provider.example-2">
- <title>Simple Identity Provider</title>
- <programlisting language="php"><![CDATA[
- $server = new Zend_OpenId_Provider("example-8-login.php",
- "example-8-trust.php");
- $ret = $server->handle();
- if (is_string($ret)) {
- echo $ret;
- } else if ($ret !== true) {
- header('HTTP/1.0 403 Forbidden');
- echo 'Forbidden';
- }
- ]]></programlisting>
- </example>
- <note>
- <para>
- It is a good idea to use a secure connection (HTTPS) for these scripts-
- especially for the following interactive scripts- to prevent password
- disclosure.
- </para>
- </note>
- <para>
- The following script implements a login screen for an identity
- server using <classname>Zend_OpenId_Provider</classname> and redirects to this page when
- a required user has not yet logged in. On this page, a user will enter his password
- to login.
- </para>
- <para>
- You should use the password "123" that was used in the identity script above.
- </para>
- <para>
- On submit, the script calls <classname>Zend_OpenId_Provider::login</classname>
- with the accepted user's identity and password, then redirects back
- to the main identity provider's script. On success, the
- <classname>Zend_OpenId_Provider::login</classname> establishes a session between the
- user and the identity provider and stores the information about
- the user, who is now logged in. All following requests from the same user won't
- require a login procedure- even if they come from another OpenID enabled
- web site.
- </para>
- <note>
- <para>
- Note that this session is between end-user and identity provider
- only. OpenID enabled sites know nothing about it.
- </para>
- </note>
- <example id="zend.openid.provider.example-3">
- <title>Simple Login Screen</title>
- <programlisting language="php"><![CDATA[
- <?php
- $server = new Zend_OpenId_Provider();
- if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
- isset($_POST['openid_action']) &&
- $_POST['openid_action'] === 'login' &&
- isset($_POST['openid_identifier']) &&
- isset($_POST['openid_password'])) {
- $server->login($_POST['openid_identifier'],
- $_POST['openid_password']);
- Zend_OpenId::redirect("example-8.php", $_GET);
- }
- ?>
- <html>
- <body>
- <form method="post">
- <fieldset>
- <legend>OpenID Login</legend>
- <table border=0>
- <tr>
- <td>Name:</td>
- <td>
- <input type="text"
- name="openid_identifier"
- value="<?php echo htmlspecialchars($_GET['openid_identity']);?>">
- </td>
- </tr>
- <tr>
- <td>Password:</td>
- <td>
- <input type="text"
- name="openid_password"
- value="">
- </td>
- </tr>
- <tr>
- <td> </td>
- <td>
- <input type="submit"
- name="openid_action"
- value="login">
- </td>
- </tr>
- </table>
- </fieldset>
- </form>
- </body>
- </html>
- ]]></programlisting>
- </example>
- <para>
- The fact that the user is now logged in doesn't mean that the
- authentication must necessarily succeed. The user may decide not to trust
- particular OpenID enabled sites. The following trust screen allows the
- end user to make that choice. This choice may either be made only for current
- requests or forever. In the second case, information about
- trusted/untrusted sites is stored in an internal database, and all
- following authentication requests from this site will be handled
- automatically without user interaction.
- </para>
- <example id="zend.openid.provider.example-4">
- <title>Simple Trust Screen</title>
- <programlisting language="php"><![CDATA[
- <?php
- $server = new Zend_OpenId_Provider();
- if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
- isset($_POST['openid_action']) &&
- $_POST['openid_action'] === 'trust') {
- if (isset($_POST['allow'])) {
- if (isset($_POST['forever'])) {
- $server->allowSite($server->getSiteRoot($_GET));
- }
- $server->respondToConsumer($_GET);
- } else if (isset($_POST['deny'])) {
- if (isset($_POST['forever'])) {
- $server->denySite($server->getSiteRoot($_GET));
- }
- Zend_OpenId::redirect($_GET['openid_return_to'],
- array('openid.mode'=>'cancel'));
- }
- }
- ?>
- <html>
- <body>
- <p>A site identifying as
- <a href="<?php echo htmlspecialchars($server->getSiteRoot($_GET));?>">
- <?php echo htmlspecialchars($server->getSiteRoot($_GET));?>
- </a>
- has asked us for confirmation that
- <a href="<?php echo htmlspecialchars($server->getLoggedInUser());?>">
- <?php echo htmlspecialchars($server->getLoggedInUser());?>
- </a>
- is your identity URL.
- </p>
- <form method="post">
- <input type="checkbox" name="forever">
- <label for="forever">forever</label><br>
- <input type="hidden" name="openid_action" value="trust">
- <input type="submit" name="allow" value="Allow">
- <input type="submit" name="deny" value="Deny">
- </form>
- </body>
- </html>
- ]]></programlisting>
- </example>
- <para>
- Production OpenID servers usually support the Simple Registration
- Extension that allows consumers to request some information about the user from
- the provider. In this case, the trust page can be extended to allow
- entering requested fields or selecting a specific user profile.
- </para>
- </sect2>
- <sect2 id="zend.openid.provider.all">
- <title>Combined Provide Scripts</title>
- <para>
- It is possible to combine all provider functionality in one script. In
- this case login and trust <acronym>URL</acronym>s are omitted, and
- <classname>Zend_OpenId_Provider</classname> assumes that they point to the same page
- with the additional "openid.action" <constant>GET</constant> argument.
- </para>
- <note>
- <para>
- The following example is not complete. It doesn't provide GUI code for
- the user, instead performing an automatic login and trust relationship instead.
- This is done just to simplify the example; a production server should include some
- code from previous examples.
- </para>
- </note>
- <example id="zend.openid.provider.example-5">
- <title>Everything Together</title>
- <programlisting language="php"><![CDATA[
- $server = new Zend_OpenId_Provider();
- define("TEST_ID", Zend_OpenId::absoluteURL("example-9-id.php"));
- define("TEST_PASSWORD", "123");
- if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
- isset($_GET['openid_action']) &&
- $_GET['openid_action'] === 'login') {
- $server->login(TEST_ID, TEST_PASSWORD);
- unset($_GET['openid_action']);
- Zend_OpenId::redirect(Zend_OpenId::selfUrl(), $_GET);
- } else if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
- isset($_GET['openid_action']) &&
- $_GET['openid_action'] === 'trust') {
- unset($_GET['openid_action']);
- $server->respondToConsumer($_GET);
- } else {
- $ret = $server->handle();
- if (is_string($ret)) {
- echo $ret;
- } else if ($ret !== true) {
- header('HTTP/1.0 403 Forbidden');
- echo 'Forbidden';
- }
- }
- ]]></programlisting>
- </example>
- <para>
- If you compare this example with previous examples split in to
- separate pages, you will see only the one
- difference besides the dispatch code:
- <methodname>unset($_GET['openid_action'])</methodname>. This call to
- <methodname>unset()</methodname> is necessary to route the next request to main handler.
- </para>
- </sect2>
- <sect2 id="zend.openid.provider.sreg">
- <title>Simple Registration Extension</title>
- <para>
- Again, the code before the <html> tag is just a trick to demonstrate
- functionality. It creates a new user account and associates it with a profile (nickname
- and password). Such tricks aren't needed in deployed providers where end users register
- on OpenID servers and fill in their profiles. Implementing this GUI is out of scope for
- this manual.
- </para>
- <example id="zend.openid.provider.example-6">
- <title>Identity with Profile</title>
- <programlisting language="php"><![CDATA[
- <?php
- define("TEST_SERVER", Zend_OpenId::absoluteURL("example-10.php"));
- define("TEST_ID", Zend_OpenId::selfURL());
- define("TEST_PASSWORD", "123");
- $server = new Zend_OpenId_Provider();
- if (!$server->hasUser(TEST_ID)) {
- $server->register(TEST_ID, TEST_PASSWORD);
- $server->login(TEST_ID, TEST_PASSWORD);
- $sreg = new Zend_OpenId_Extension_Sreg(array(
- 'nickname' =>'test',
- 'email' => 'test@test.com'
- ));
- $root = Zend_OpenId::absoluteURL(".");
- Zend_OpenId::normalizeUrl($root);
- $server->allowSite($root, $sreg);
- $server->logout();
- }
- ?>
- <html>
- <head>
- <link rel="openid.server" href="<?php echo TEST_SERVER;?>" />
- </head>
- <body>
- <?php echo TEST_ID;?>
- </body>
- </html>
- ]]></programlisting>
- </example>
- <para>
- You should now pass this identity to the OpenID-enabled web site (use the Simple
- Registration Extension example from the previous section), and it should use the
- following OpenID server script.
- </para>
- <para>
- This script is a variation of the script in the "Everything Together" example. It uses
- the same automatic login mechanism, but doesn't contain any code for a trust
- page. The user already trusts the example scripts forever. This trust was
- established by calling the <methodname>Zend_OpenId_Provider::allowSite()</methodname>
- method in the identity script. The same method associates the profile with the trusted
- <acronym>URL</acronym>. This profile will be returned automatically for a request from
- the trusted <acronym>URL</acronym>.
- </para>
- <para>
- To make Simple Registration Extension work, you must simply
- pass an instance of <classname>Zend_OpenId_Extension_Sreg</classname> as the second
- argument to the <methodname>Zend_OpenId_Provider::handle()</methodname> method.
- </para>
- <example id="zend.openid.provider.example-7">
- <title>Provider with SREG</title>
- <programlisting language="php"><![CDATA[
- $server = new Zend_OpenId_Provider();
- $sreg = new Zend_OpenId_Extension_Sreg();
- define("TEST_ID", Zend_OpenId::absoluteURL("example-10-id.php"));
- define("TEST_PASSWORD", "123");
- if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
- isset($_GET['openid_action']) &&
- $_GET['openid_action'] === 'login') {
- $server->login(TEST_ID, TEST_PASSWORD);
- unset($_GET['openid_action']);
- Zend_OpenId::redirect(Zend_OpenId::selfUrl(), $_GET);
- } else if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
- isset($_GET['openid_action']) &&
- $_GET['openid_action'] === 'trust') {
- echo "UNTRUSTED DATA" ;
- } else {
- $ret = $server->handle(null, $sreg);
- if (is_string($ret)) {
- echo $ret;
- } else if ($ret !== true) {
- header('HTTP/1.0 403 Forbidden');
- echo 'Forbidden';
- }
- }
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.openid.provider.else">
- <title>Anything Else?</title>
- <para>
- Building OpenID providers is much less common than building
- OpenID-enabled sites, so this manual doesn't cover all
- <classname>Zend_OpenId_Provider</classname> features exhaustively, as was done for
- <classname>Zend_OpenId_Consumer</classname>.
- </para>
- <para>
- To summamize, <classname>Zend_OpenId_Provider</classname> contains:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- A set of methods to build an end-user GUI that allows
- users to register and manage their trusted sites and profiles
- </para>
- </listitem>
- <listitem>
- <para>
- An abstract storage layer to store information about users,
- their sites and their profiles. It also stores associations between
- the provider and OpenID-enabled sites. This layer is very similar
- to that of the <classname>Zend_OpenId_Consumer</classname> class. It also uses
- file storage by default, but may used with another backend.
- </para>
- </listitem>
- <listitem>
- <para>
- An abstract user-association layer that may associate
- a user's web browser with a logged-in identity
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The <classname>Zend_OpenId_Provider</classname> class doesn't attempt to cover all
- possible features that can be implemented by OpenID servers, e.g. digital
- certificates, but it can be extended easily using
- <classname>Zend_OpenId_Extension</classname>s or by standard object-oriented extension.
- </para>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|