Lemonldap::NG::Portal::CDC - Manage SAML Common Domain Cookie


Lemonldap-NG-Portal documentation Contained in the Lemonldap-NG-Portal distribution.

Index


Code Index:

NAME

Top

Lemonldap::NG::Portal::CDC - Manage SAML Common Domain Cookie

SYNOPSIS

Top

  use Lemonldap::NG::Portal::CDC;

  my $portal = new Lemonldap::NG::Portal::CDC();

  $portal->process();

  # Write here HTML to manage errors and confirmation messages

DESCRIPTION

Top

Lemonldap::NG::Portal::CDC - Manage SAML Common Domain Cookie

See Lemonldap::NG::Portal::SharedConf for a complete example of use of Lemonldap::Portal::* libraries.

METHODS

Top

process

Main method.

SEE ALSO

Top

Lemonldap::NG::Handler, Lemonldap::NG::Portal::SharedConf, CGI, http://lemonldap-ng.org/

AUTHOR

Top

Clement Oudot, <clement@oodo.net>

BUG REPORT

Top

Use OW2 system to report bug or ask for features: http://jira.ow2.org

DOWNLOAD

Top

Lemonldap::NG is available at http://forge.objectweb.org/project/showfiles.php?group_id=274

COPYRIGHT AND LICENSE

Top


Lemonldap-NG-Portal documentation Contained in the Lemonldap-NG-Portal distribution.

## @file
# Module for SAML Common Domain Cookie Support

## @class Lemonldap::NG::Portal::CDC
# Class for SAML Common Domain Cookie Support
package Lemonldap::NG::Portal::CDC;

use strict;
use warnings;
use MIME::Base64;
use Lemonldap::NG::Portal::SharedConf;    # inherits
use Lemonldap::NG::Portal::_SAML;         # inherits

our $VERSION = '1.0.0';
our @ISA = qw(Lemonldap::NG::Portal::_SAML Lemonldap::NG::Portal::SharedConf);

## @method int process()
# Main method to process CDC requests
# @return portal error code
sub process {
    my $self       = shift;
    my $cdc_idp    = "";
    my $cdc_cookie = "";

    # Default values
    my $cdc_name   = $self->{samlCommonDomainCookieName}   || '_saml_idp';
    my $cdc_domain = $self->{samlCommonDomainCookieDomain} || $ENV{'HTTP_HOST'};

    $self->lmLog( "[CDC] Cookie name: $cdc_name",   'debug' );
    $self->lmLog( "[CDC] Domain name: $cdc_domain", 'debug' );

    # Request parameter
    my $action = $self->param('action') || "";    # What we do
    my $idp = $self->param('idp');                # IDP ID in write mode

    # Control URL
    my $control_url = $self->_sub('controlUrlOrigin');
    unless ( $control_url == PE_OK ) {
        $self->lmLog( "[CDC] Bad URL", 'error' );
        return $control_url;
    }

    # Get cookie
    my %cookies = fetch CGI::Cookie;
    $cdc_cookie = $cookies{$cdc_name} if %cookies;
    $cdc_cookie &&= $cdc_cookie->value;

    if ($cdc_cookie) {
        $self->lmLog( "[CDC] Cookie found with value $cdc_cookie", 'debug' );
    }

    # Write request
    # Called in an iFrame
    # Get or build common domain cookie
    # Append IDP to common domain cookie
    if ( $action eq 'write' ) {

        $self->lmLog( "[CDC] Write request detected", 'debug' );

        # Check IDP value
        unless ($idp) {
            $self->lmLog( "[CDC] No IDP given", 'error' );
            return PE_SAML_ERROR;
        }

        # Add IDP value
        $self->lmLog( "[CDC] Will add IDP $idp to IDP list", 'debug' );

        my $encoded_idp = encode_base64( $idp, '' );

        # Remove IDP value if already present
        $cdc_cookie =~ s/$encoded_idp(\s+)?//g;

        # Add a space separator
        $cdc_cookie .= ( $cdc_cookie ? " " : "" );
        $cdc_cookie .= $encoded_idp;

        $self->lmLog( "[CDC] Build cookie $cdc_name with value $cdc_cookie",
            'debug' );

        # Build cookie
        push @{ $self->{cookie} }, $self->cookie(
            -name     => $cdc_name,
            -value    => $cdc_cookie,
            -domain   => $cdc_domain,
            -path     => "/",                         # See SAML protocol
            -secure   => 1,                           # See SAML protocol
            -httponly => $self->{httpOnly},
            -expires  => $self->{cookieExpiration},
        );
    }

    # Read request
    # Get last IDP from domain cookie
    # Return on SP with idp as parameter

    elsif ( $action eq 'read' ) {

        $self->lmLog( "[CDC] Read request detected", 'debug' );

        # Get last IDP from cookie
        if ($cdc_cookie) {
            $cdc_idp = decode_base64( ( split /\s+/, $cdc_cookie )[-1] );
            $self->lmLog( "[CDC] Get value $cdc_idp", 'debug' );
        }
        else {
            $self->lmLog( "[CDC] No cookie, set a default value", 'debug' );
            $cdc_idp = 'notfound';
        }
    }

    # Redirect if needed
    if ( $self->{urldc} ) {

        # Add CDC IDP in return URL if needed
        # olStyleUrl can be set to 1 to use & instead of ;
        $self->{urldc} .= (
            $cdc_idp
            ? (
                $self->{urldc} =~ /\?/
                ? ( $self->{oldStyleUrl} ? '&' : ';' ) . 'idp=' . $cdc_idp
                : '?idp=' . $cdc_idp
              )
            : ''
        );

        # Redirect
        $self->_sub('autoRedirect');

    }

    if ($cdc_cookie) {

        # Parse cookie to display it if not redirected
        my @cdc_values =
          map( decode_base64($_), ( split( /\s+/, $cdc_cookie ) ) );
        $self->{cdc_values} = \@cdc_values;
    }

    return PE_OK;
}

1;

__END__