summaryrefslogtreecommitdiffstats
path: root/docs/lasso-book
diff options
context:
space:
mode:
authorNicolas Clapies <nclapies@entrouvert.com>2006-12-20 12:53:25 +0000
committerNicolas Clapies <nclapies@entrouvert.com>2006-12-20 12:53:25 +0000
commitb13136af8a5e7e2e61ccd4e0a388f963b25f24d1 (patch)
tree258914b6c406c3e023fc92f9c1f5475afe285d0b /docs/lasso-book
parent13f707bf30acd26ae9c6fac5321d0accd47a5b90 (diff)
downloadlasso-b13136af8a5e7e2e61ccd4e0a388f963b25f24d1.tar.gz
lasso-b13136af8a5e7e2e61ccd4e0a388f963b25f24d1.tar.xz
lasso-b13136af8a5e7e2e61ccd4e0a388f963b25f24d1.zip
Added SAML2 PHP documentation. Need to complete with some Login and Logout details. Need to add description of Name Id Management profile.
Diffstat (limited to 'docs/lasso-book')
-rw-r--r--docs/lasso-book/Makefile.am6
-rw-r--r--docs/lasso-book/writing-a-saml2-php-sp.txt415
2 files changed, 419 insertions, 2 deletions
diff --git a/docs/lasso-book/Makefile.am b/docs/lasso-book/Makefile.am
index f887828b..33421f94 100644
--- a/docs/lasso-book/Makefile.am
+++ b/docs/lasso-book/Makefile.am
@@ -11,9 +11,11 @@ LASSOBOOK_FILES = book.rst common-knowledge.rst getting-lasso.rst \
liberty-architecture.rst other-profiles.rst preface.rst \
single-sign-on.rst
-SP_DOC_FILES = writing-a-c-sp.txt writing-a-php-sp.txt writing-a-java-sp.txt
+SP_DOC_FILES = writing-a-c-sp.txt writing-a-php-sp.txt writing-a-java-sp.txt \
+ writing-a-saml2-php-sp.txt
-SP_DOC_HTML = writing-a-c-sp.html writing-a-php-sp.html writing-a-java-sp.html
+SP_DOC_HTML = writing-a-c-sp.html writing-a-php-sp.html writing-a-java-sp.html \
+ writing-a-saml2-php-sp.html
if HAVE_REST2HTML
doc_DATA = $(SP_DOC_HTML) book.html
diff --git a/docs/lasso-book/writing-a-saml2-php-sp.txt b/docs/lasso-book/writing-a-saml2-php-sp.txt
new file mode 100644
index 00000000..fcb31167
--- /dev/null
+++ b/docs/lasso-book/writing-a-saml2-php-sp.txt
@@ -0,0 +1,415 @@
+=========================================
+Writing a SAML2 service Provider in PHP
+=========================================
+
+:author Nicolas Clapiès
+:contact: nclapies@entrouvert.com
+:date: $Date$
+:revision: $Revision$
+:copyright: Copyright © 2005, 2006 Entr'ouvert
+
+.. contents:: Table of Contents
+.. section-numbering::
+
+
+Lasso PHP Binding Basics
+========================
+
+Lasso functions are available from the Lasso PHP extension.
+
+There are two ways to load this extension.
+
+This first one is to add the line::
+
+ extension = lasso.so
+
+in your ``php.ini`` configuration file, which can be found in something like
+``/etc/php4/apache2/php.ini`` (if you're using apache2 and php4 on Debian,
+otherwise you may need to adapt the path to your local configuration).
+
+
+The other way is to load it dynamically, like::
+
+ if (!extension_loaded('lasso')) {
+ $prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
+ dl($prefix . 'lasso.' . PHP_SHLIB_SUFFIX);
+ }
+
+You can easily include this code every time you need lasso.
+
+
+The first thing to do is to call ``lasso_init()``. Similarly, the last thing
+should be to call ``lasso_shutdown()``.
+
+Once ``lasso_init()`` is called. The smallest and useless Lasso project will
+therefore be::
+
+ lasso_init();
+ print("Hello world.\n");
+ lasso_shutdown();
+
+If your PHP code is used in HTML script environment, it could be difficult to
+call ``lasso_shutdown()``, this is not mandatory.
+
+
+SAML2 and Lasso profiles
+========================
+
+Lasso provides the necessary functions to implement SAML2 profiles,
+as defined in the `SAML2 Profiles Specification`_. They
+are:
+
+- Single Sign-On
+- Single Logout
+- Name Identifier Management
+
+Each profile maps to a Lasso object : Single Sign-on profile is implemented by
+``LassoLogin`` object, Single Logout profile is implemented by ``LassoLogout``
+object.
+
+Those are initialised with data known about identity and service providers,
+available in a ``LassoServer`` object.
+
+The ``LassoServer`` object may be created as follows::
+
+ lasso_init();
+ $server = new LassoServer("sp-metadata.xml", "sp-private-key.pem",
+ NULL, "sp-crt.pem");
+ $server->addProvider(LASSO_PROVIDER_ROLE_IDP, "idp-metadata.xml",
+ "idp-public-key.pem", "ca-crt.pem");
+ lasso_shutdown();
+
+- ``sp-metadata.xml`` is the Liberty metadata file for the service provider
+- ``idp-metadata.xml`` is the Liberty metadata file for the identity provider
+- ``sp-private-key.pem`` is the service provider private key; used to sign
+ documents
+- ``sp-crt.pem`` is the service provider certificate; sent inside signed
+ documents
+- ``idp-public-key.pem`` is the identity provider public key; used to verify
+ signature in documents sent by the identity provider
+- ``ca-crt.pem`` is the certificate of the certification authority used by the
+ identity provider.
+
+It is of course possible to have several calls to the ``addProvider`` method of
+an instantiated ``LassoServer`` object if there are more than one identity provider.
+
+.. note:: Figures in the previously referred Binding and Profiles specification
+ document are quite helpful in figuring out the message passing.
+
+Serialisation
+-------------
+
+``LassoServer`` objects can be serialised into a XML formatted string::
+
+ $dump = $server->dump();
+
+It is then really easy to get back properly constructed objects::
+
+ $server = LassoServer::newFromDump($dump);
+
+.. warning:: The server dump only contains the file names, not the actual file
+ contents. Files should not be moved afterwards.
+
+
+Liberty Metadata Files
+======================
+
+Providers are described by metadata containing an ``entityID`` and various
+normative URLs for supported profiles ::
+
+ <?xml version="1.0"?>
+ <EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ entityID="http://sp.example.com/liberty/metadata">
+
+ <SPSSODescriptor
+ AuthnRequestsSigned="true"
+ protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+
+ <KeyDescriptor use="signing">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:KeyValue></ds:KeyValue>
+ </ds:KeyInfo>
+ </KeyDescriptor>
+
+ <SingleLogoutService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
+ Location="https://sp.example.com/liberty/singleLogoutSoap" />
+
+ <ManageNameIDService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
+ Location="https://sp.example.com/liberty/nameIdManagmentSoap" />
+
+ <AssertionConsumerService index="0" isDefault="true"
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
+ Location="https://sp.example.com/liberty/assertionConsumerServiceArtifact" />
+
+ </SPSSODescriptor>
+
+ <Organization>
+ <OrganizationName xml:lang="en"></OrganizationName>
+ </Organization>
+
+ </EntityDescriptor>
+
+``SingleLogoutService`` entry allows to define method and url supported where
+service provider wants to receive single logout requests. In previous metadata
+example, service provider receives SOAP single logout requests on the
+url ``https://sp.example.com/liberty/singleLogoutSoap``.
+
+``ManageNameIDService`` entry allows to define method and url supported where
+service provider wants to receive name id management requests. In previous metadata
+example, service provider receives SOAP name id management requests on the
+url ``http://sp.example.com/liberty/nameIdManagmentSoap``.
+
+``AssertionConsumerService`` entry allows to define method and url supported where
+service provider wants to receive assertion consumer responses. In previous metadata
+example, service provider consume assertions responses on the
+url ``https://sp.example.com/liberty/assertionConsumerServicePost``.
+
+
+Single Sign-On and Federation Profile
+=====================================
+
+.. warning:: The source code presented in this section has for sole purpose
+ to explain the different steps necessary to implement this
+ profile; they notably lack proper error checking. See `Proper
+ Error Checking`_ for details on error checking.
+
+
+As a first step the user points its browser to the service provider to the
+login URL; the service provider must then respond with an HTTP 302 Redirect
+response, pointing the user browser to the identity provider single sign on
+service.
+
+.. note:: the login URL is not normative; any name will do.
+
+
+``$server`` is a instantiated ``LassoServer`` as seen earlier and
+``$idpEntityId`` is a string with the idp entity Id (the string must
+match a entityID defined in the metadata file).
+
+::
+
+
+
+ $entityIdList = $server->providerIds;
+ $idpEntityId = $entityIdList->getItem(0);
+
+ $lassoLogin = new LassoLogin($server);
+ $lassoLogin->initAuthnRequest($idpEntityId, LASSO_HTTP_METHOD_REDIRECT);
+
+ $lassoRequest = $lassoLogin->request;
+ $lassoRequest->ProtocolBinding = LASSO_SAML2_METADATA_BINDING_POST;
+
+ $lassoNameIdPolicy = $lassoRequest->NameIDPolicy;
+ $lassoNameIdPolicy->Format = LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT;
+ $lassoNameIdPolicy->AllowCreate = TRUE;
+
+ $lassoLogin->buildAuthnRequestMsg();
+
+
+You can now redirect the user to the URL defined in ``$lassoLogin->msgUrl``; for
+example::
+
+ header("Location: ".$lassoLogin->msgUrl);
+
+
+The user then logs in on the identity provider which ultimately redirects back
+to the service provider; to the assertion consumer URL. A SAML artifact is
+passed in the query parameter.
+
+.. note:: the assertion consumer URL is defined by Liberty; it must be declared
+ in the ``AssertionConsumerServiceURL`` element of the metadata file.
+
+::
+
+ $lassoLogin = new LassoLogin($server);
+ $lassoLogin->initRequest($query_string, LASSO_HTTP_METHOD_ARTIFACT_GET);
+ $lassoLogin->buildRequestMsg();
+
+The service provider must check this artifact using a SOAP request to the
+identity provider. The URL is ``$lassoLogin->msgUrl`` while the
+request is ``$lassoLogin->msgBody``. The request must succeed with
+an HTTP 200 status code; let's consider its content is put in the ``$answer``,
+the next statement would be::
+
+ $lassoLogin->processResponseMsg($answer);
+
+The users are defined by a ``nameIdentifier`` (accessible through
+``$lassoLogin->nameIdentifier``). Those typically map to users
+and sessions in some database on the service provider. If existing; the
+session should probably contains a ``session_dump`` element and the user a
+``identity_dump`` element. See `Database Considerations`_ below for more
+information.
+
+It is now time to get them out of the database and apply them to the ``login``
+object.
+
+::
+
+ if ($session_dump != NULL) {
+ $lassoLogin->setSessionFromDump($session_dump);
+ }
+ if ($identity_dump != NULL) {
+ $lassoLogin->setIdentityFromDump($identity_dump);
+ }
+ $lassoLogin->acceptSso();
+
+After ``lassoLogin->acceptSso()`` the session and the identity are updated (or
+created) and should then be saved. If the identity has not recognised by the
+service provider an account will probably have to be created on the service
+provider; this is a good opportunity to ask the user for more information.
+
+You can get respective dumps like this::
+
+ if ($lassoLogin->isIdentityDirty) {
+ $lassoIdentity = $lassoLogin->identity;
+ $lassoIdentityDump = $lassoIdentity->dump();
+ }
+
+ if ($lassoLogin->isSessionDirty) {
+ $lassoSession = $lassoLogin->session;
+ $lassoSessionDump = $lassoSession->dump();
+ }
+
+ /* code to store $identity_dump and $session_dump */
+
+
+A success web page can be displayed.
+
+
+Single Logout Profile
+=====================
+
+There are different single logout profiles; some initiated on the identity
+provider, others initiated on the service provider, using either HTTP redirects
+or SOAP requests.
+
+This part is about a logout using SOAP and initiated on the service provider.
+
+::
+
+ $lassoLogout = new LassoLogout($server);
+
+
+Identity and session dumps should be restored to prepare the logout request.
+
+::
+
+ if ($session_dump != NULL) {
+ $lassoLogout->setSessionFromDump($session_dump);
+ }
+ if ($identity_dump != NULL) {
+ $lassoLogout->setIdentityFromDump($identity_dump);
+ }
+
+ $lassoLogout->initRequest($idpProviderId, LASSO_HTTP_METHOD_SOAP);
+ $lassoLogout->buildRequestMsg();
+
+
+The service provider must then make a SOAP request to the identity provider;
+``$msgUrl`` and ``$msgBody``. You should then pass the answer to Lasso::
+
+ $lassoLogout->processResponseMsg($answer));
+
+And save back session and user dump; the process is similar as the one at the
+end of the single sign on profile.
+
+
+Proper Error Checking
+=====================
+
+Most Lasso functions raise PHP error (fatal) or warning (non-fatal).
+
+It is strongly advised to code an user error handler::
+
+ function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars) {
+ print("No: ".$errno." - ".$errmsg." at ".$filename.", line: ".$linenum."\n");
+ }
+
+and to set up the script to use it::
+
+ set_error_handler("userErrorHandler");
+
+Most Lasso functions returns 0 on success and a negative number on failure. It
+is strongly advised to check this return code on each call. If the error raise a
+PHP warning, the code resume after the call to the error handler function.
+
+::
+
+ $lrv = $lassoLogin->processResponseMsg($responseMsg);
+ if ($lrv > 0) {
+ print("Lasso Error: ".$lrv."\n");
+ /* handling error; most probably bailing out */
+ }
+
+
+Database Considerations
+=======================
+
+Lasso has been designed to let the service provider keep on using existing
+databases. Typically there is already a table describing users; just add an
+identity dump column to the existing table:
+
+======= ======================================== ==============
+User Id existing data (name, address...) Identity dump
+======= ======================================== ==============
+1 ... <Identity> ...
+2 ... <Identity> ...
+======= ======================================== ==============
+
+Mapping between existing users and name identifiers sent by the identity
+provider can be done with a simple table.
+
+=============== =======
+Name Identifier User Id
+=============== =======
+AQWWRRS... 1
+CGFASDE... 2
+YYSSSDS... 1
+=============== =======
+
+.. note:: A separate table is needed because one user Id could map
+ to several name identifiers; in case there are several identity
+ providers.
+
+Sessions are also commonly stored in databases; just add a session dump column
+to the existing session table:
+
+========== ================= =============
+Session Id misc session data Session dump
+========== ================= =============
+6744066 ... <Session> ...
+3338824 ... <Session> ...
+========== ================= =============
+
+Likewise sessions should be mapped to name identifiers.
+
+=============== ==========
+Name Identifier Session Id
+=============== ==========
+AQWWRRS... 3338824
+=============== ==========
+
+
+API Reference
+=============
+
+- LassoLogin_
+- LassoLogout_
+- LassoIdentity_
+- LassoServer_
+- LassoSession_
+
+
+.. _SAML2 Profiles Specification:
+ http://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf
+
+.. _LassoLogin: /documentation/api-reference/lassologin.html
+.. _LassoLogout: /documentation/api-reference/lassologout.html
+.. _LassoIdentity: /documentation/api-reference/lassoidentity.html
+.. _LassoServer: /documentation/api-reference/lassoserver.html
+.. _LassoSession: /documentation/api-reference/lassosession.html
+