Pubcookie: Single Authentication Point for Web Applications

    There are many solutions that allow one way or another to implement the technology of single sign-on (Single Sign On). Single sign-on refers to the situation when you log in once on some dedicated authorization server (or just on your machine), you get access to all available network resources without additional authorization.

    We are now gradually refactoring our internal intranet services, which have often developed spontaneously, and are considering various technologies, the use of which can make our internal infrastructure more convenient and safer.

    SSO technologies, as a rule, are rather complicated, however, if we restrict ourselves to the task of single sign-on only for a set of web applications, there is a relatively simple solution that allows you to realize this opportunity without changing or slightly changing the application code. This solution is called Pubcookie , and it will be discussed.



    If we use Pubcookie, then when we enter a protected resource, we will automatically be redirected to a special dedicated login server, on which we log in and automatically go back. At the same time, we do not need to change anything in the protected application; it, as before, gets the name of the current user from REMOTE_USER.

    Let's see how you can configure this mechanism.

    Scheme of work

    The following components are involved in the authentication process:

    1. Client browser
    2. An application server on which an application requiring authentication is deployed, in our case Apache with the Pubookie module and, in fact, the protected application;
    3. The login server, in our case, is again Apache with a standard authentication application and our settings for this application;
    4. Actually, the authentication service.


    Authentication is as follows:

    1. A custom browser requests a specific resource from an application server configured to use Pubcookie.
    2. The Pubcookie module installed on the application server intercepts the request and verifies that it is not connected to a valid current session and does not contain information from the login server (the so-called granting cookie) to create a new session.
      Upon successful verification, the module generates a response containing a redirect and two cookies: a presession cookie for the application and a granting request cookie for the login server. Both cookies contain, among other information, a random number generated by the module. All cookies are encrypted.
    3. The client browser performs a redirect (granting request) to the login server with a granting request cookie. The request data allows the access server to determine the application server for which authentication is requested, the URL of the original request, the type of authorization, etc.
    4. The login server decodes the granting request cookie and interprets the contents. The server generates a login form and sends it to the client.
    5. The user enters their username and password into the form and sends it to the login server;
    6. The login server receives the username and password and sends them to the authentication service used for verification.
    7. The login server receives the verification result from the authentication service.
    8. If the verification is successful, the login server generates a response containing a redirect and two new cookies. The first, a granting cookie, is for an application server and contains a verified username and additional information, including the random number generated in step 2, signed by the private key of the access server and encrypted with the symmetric key used on the application server and access server. The second, login cookie, is intended for the login server and is used in case of subsequent visits of the user to it.
    9. The user browser re-requests the protected resource from the application server. The request contains a granting cookie and a presession cookie.
    10. The pubcookie module on the application server intercepts the request, decrypts the granting cookie, verifies the signature, and compares the random number in the granting cookie with the same number in the presession cookie. If everything converges, the username is passed to the application and the application processes the request. A session cookie is also generated for subsequent access to protected resources. The response generated by the application is sent to the user.


    If in step 4 the granting request also contains a valid login cookie (set in step 8), steps 5, 6 and 7 are skipped and the login server goes directly to step 8, generating a granting cookie using the username obtained from the login cookie. Thus, we get an element of Single Sign On technology for a set of web applications: you do not need to log in for each web application, just enter your username and password once.

    Assembly

    We will consider for Ubuntu, under FreeBSD it also does not cause problems:

    Download the distribution kit from www.pubcookie.org . Before assembling, we make two patches:

    1. The configure patch for a problem with APXS:

    3783c3783
    <   APACHE_PREFIX=`$APXS -q PREFIX`
    ---
    >   APACHE_PREFIX="/usr/share/apache2"
    


    Here, by hammering, you can probably do it more correctly.

    2. Patch src / index.cgi.c for UTF-8 encoding:

    461c461
    <     print_header (p, "Content-Type: text/html; charset=ISO-8859-1\n");
    ---
    >     print_header (p, "Content-Type: text/html; charset=utf-8\n");
    


    When configuring, specify the assembly of the module and cgi-application to enter:

    $./configure --enable-apache --with-apxs=/usr/bin/apxs2 --enable-login
    


    Then we collect, preferably in a deb package.

    Key and certificate generation

    . Https is used to work with protected resources. Well, that's why they are protected.

    We generate two pairs of keys.

    The first is the SSL key pair, used by the apache for SSL and the key server (about it below):

    $ openssl req -new -x509 -out server.crt -newkey rsa:1024 -nodes -keyout server.key
    


    The second is the granting key pair, for signing and checking granting cookies: The

    $ openssl req -new -x509 -out granting.crt -newkey rsa:1024 -nodes -keyout granting.key
    


    example is purely demo, we use self-signed certificates, in reality it’s more complicated. Accordingly, we generate a toy CA bundle:

    $ cp server.crt ca-bundle.crt
    


    As a result, we get the files: server.crt, server.key, granting.crt, granting.key, ca-bundle.crt.

    Setting up the login server.

    Let the server be called access.techart.intranet.

    The key server and the authentication application running the web server are running on the access server.

    The key server distributes symmetric keys used to encrypt the contents of the cookies. It runs under xinetd, respectively, we prescribe it there:

    service keyserver
    {
      type                   = UNLISTED
      protocol             = tcp
      port                   = 2222
      disable              = no
      socket_type           = stream
      wait                  = no
      user                  = root
      group                 = tty
      server                = /usr/local/pubcookie/keyserver
    }
    


    After restarting xinetd, the server is available on port 2222.

    The authentication application is a regular CGI application that must be accessible via https. Accordingly, for it it is necessary to configure virtual host: It remains to configure pubcookie. Edit the file / usr / local / pubcookie / config:

    
      ServerName login.techart.intranet
      DocumentRoot /usr/local/pubcookie/login
      DirectoryIndex index.cgi
      AddHandler cgi-script cgi
      
        Options FoolowSymLinks
        Options +ExecCGI
        AllowOverride None
      
      SSLEngine on
      SSLCertificateFile /usr/local/pubcookie/keys/server.crt
      SSLCertificateKeyFile /usr/local/pubcookie/keys/server.key
    




    # Уровень детализации логов
    logging_level: 1
    # Используемый сервис аутентификации. 
    # В нашем примере мы используем пользовательский скрипт auth.php, 
    # который обращается к базе данных.
    basic_verifier: verify_fork
    verify_exe: /usr/local/pubcookie/auth.php
    # Пара ключей SSL
    ssl_key_file: /usr/local/pubcookie/keys/server.key
    ssl_cert_file: /usr/local/pubcookie/keys/server.crt
    # Пара granting ключей 
    granting_key_file: /usr/local/pubcookie/keys/granting.key
    granting_cert_file: /usr/local/pubcookie/keys/granting.crt 
    # Логин-сервер (CGI)
    login_uri: https://access.techart.intranet/
    login_host: access.techart.intranet
    enterprise_domain: .techart.intranet
    logout_prog: /logout/index.cgi
    # Сервер ключей
    keymgt_uri: localhost:2222
    ssl_ca_file: /usr/local/pubcookie/keys/ca-bundle.crt
    # Срок жизни сессии
    default_l_expire: 8h
    # Параметры шаблонов логин-сервера, в частности, сообщение о закрытии сессии.
    app_logout_string-app1.techart.intranet-app1: Разлогинились из app1
    


    In this example, we use verify_fork mode when an arbitrary external program is used as the authentication service, returning a normal or erroneous termination code depending on whether the user was identified. In this case, the program reads the username and password from stdin.

    In our case, this is a php script that can, for example, access a database or a text file, while other modes are supported, for example, working with LDAP and Kerberos.

    Now we generate a key that allows the login server to connect to the key server:

    $ sudo keyclient -P access.techart.intranet
    


    The generated key will be written to keys/access.techart.intranet. This operation must be performed for each host using Pubcookie.

    After performing all these manipulations at access.techart.intranetwe should see the login form.

    Setting up the application server.

    On the application server, we configure the pubcookie configuration file in the same way as on the access server. In addition, you need to connect the mod_pubcookie module to Apache.

    To do this, create a file /etc/apache2/mods-available/pubcookie.conf:

    PubcookieGrantingCertFile /usr/local/pubcookie/keys/granting.crt
    PubcookieSessionKeyFile /usr/local/pubcookie/keys/server.key
    PubcookieSessionCertFile /usr/local/pubcookie/keys/server.crt
    PubcookieKeyDir /usr/local/pubcookie/keys/
    PubcookieLogin https://access.techart.intranet/
    PubcookieLoginMethod POST
    PubcookieDomain .techart.intranet
    PubcookieEncryption AES
    PubcookieAuthTypeNames EGNetID
    


    Then everything is as usual:

    /etc/apache2/mods-available/pubcookie.load:
    LoadModule pubcookie_module /usr/lib/apache2/modules/mod_pubcookie.so
    $ sudo a2enmod pubcookie
    $ sudo service restart apache2
    


    Now we configure the application itself: In this case, we closed access to the entire application, however we could prescribe authentication options for a specific subdirectory, put them in , etc. Setting this option allows the application to get the name of the current user from REMOTE_USER. We restart Apache, and if everything went fine, then when you go to app1.techart.intranet

    
      ServerName app1.techart.intranet
      
        AuthType EGNetID
        require valid-user
        PubcookieAppID app1
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        AllowOverride AuthConfig
        Order allow,deny
        allow from all
      
      SSLEngine on
      SSLCertificateFile    /usr/local/pubcookie/keys/server.cert
      SSLCertificateKeyFile /usr/local/pubcookie/keys/server.key
    


    .htaccess

    AllowOverride AuthConfig

    we should be redirected to login.techart.intranet , where we log in and automatically return.

    Virtual hosts

    All of the above works for virtual hosts tied to a dedicated IP. To work with name-based virtual hosts, SNI support is required in OpenSSL, (since version 0.9.8j) and in Apache (since 2.2.12). In addition, SNI is not supported on IE versions lower than 7.

    For this configuration, the Common Name field should contain a list of hosts used. Edit openssl.cnf and regenerate the key set.

    [req_distinguished_name]
    0.commonName      = Common Name (eg, YOUR name)
    0.commonName_default    = app1.techart.intranet
    0.commonName_max    = 64
    1.commonName      = Common Name (eg, YOUR name)
    1.commonName_default    = app2.techart.intranet
    1.commonName_max    = 64
    ...
    


    In the description of the virtual host in Apache, we write:

    SLCipherSuite HIGH
    SSLProtocol all -SSLv2
    


    and restart apache.

    Configure access server user interface

    The appearance of the login form and service pages of the login server can be configured using the templates that are in the login_templates directory. To use UTF-8 you need to patch index.cgi.c.

    Configuring logout

    Closing a session can be performed both in a separate application and on a login server. The easiest way to do this on the login server is to create a subdirectory logoutwith .htaccessone directive:

    PubcookieEndSession redirect
    


    Total.

    In general, the mechanism is quite simple, the main difficulty in setting up is not so much with Pubcookie as with OpenSSL.

    Accordingly, in the case of implementation, the most important thing is to correctly configure the basic key / certificate management infrastructure.

    At the same time, in a situation where there are a lot of legacy applications on the intranet, using Pubcookie allows you to implement centralized access control for them with minimal effort.

    A few links:


    Also popular now: