Google-SAML-Response

 view release on metacpan or  search on metacpan

lib/Google/SAML/Response.pm  view on Meta::CPAN


    foreach my $required ( qw/ request key login / ) {
        if ( exists $params->{ $required } ) {
            $self->{ $required } = $params->{ $required };
        }
        else {
            confess "You need to provide the $required parameter!";
        }
    }

    my $request = Google::SAML::Request->new_from_string( $self->{ request } );

    if ( $request && $self->_load_key ) {
        $self->{ service_url }   = $request->AssertionConsumerServiceURL;
        $self->{ request_id }    = $request->ID;
        $self->{ ttl }           = ( exists $params->{ ttl } ) ? $params->{ ttl } : 60*2;
        $self->{ canonicalizer } = exists $params->{ canonicalizer }
                                    ? $params->{ canonicalizer }
                                    : 'XML::CanonicalizeXML';

        return $self;
    }
    else {
        return;
    }
}


sub _load_dsa_key {
    my $self     = shift;
    my $key_text = shift;

    eval {
        require Crypt::OpenSSL::DSA;
    };

    confess 'Crypt::OpenSSL::DSA needs to be installed so that we can handle DSA keys.' if $@;

    my $dsa_key = Crypt::OpenSSL::DSA->read_priv_key_str( $key_text );

    if ( $dsa_key ) {
        $self->{ key_obj } = $dsa_key;
        my $g = encode_base64( $dsa_key->get_g, '' );
        my $p = encode_base64( $dsa_key->get_p, '' );
        my $q = encode_base64( $dsa_key->get_q, '' );
        my $y = encode_base64( $dsa_key->get_pub_key, '' );

        $self->{ KeyInfo }  = "<KeyInfo><KeyValue><DSAKeyValue><P>$p</P><Q>$q</Q><G>$g</G><Y>$y</Y></DSAKeyValue></KeyValue></KeyInfo>";
        $self->{ key_type } = 'dsa';
    }
    else {
        confess 'did not get a new Crypt::OpenSSL::RSA object';
    }
}


sub _load_rsa_key {
    my $self     = shift;
    my $key_text = shift;

    my $rsa_key = Crypt::OpenSSL::RSA->new_private_key( $key_text );

    if ( $rsa_key ) {
        $self->{ key_obj } = $rsa_key;

        my $big_num = ( $rsa_key->get_key_parameters )[ 1 ];
        my $bin = $big_num->to_bin;
        my $exp = encode_base64( $bin, '' );

        $big_num = ( $rsa_key->get_key_parameters )[ 0 ];
        $bin = $big_num->to_bin;
        my $mod = encode_base64( $bin, '' );
        $self->{ KeyInfo }  = "<KeyInfo><KeyValue><RSAKeyValue><Modulus>$mod</Modulus><Exponent>$exp</Exponent></RSAKeyValue></KeyValue></KeyInfo>";
        $self->{ key_type } = 'rsa';
    }
    else {
        confess 'did not get a new Crypt::OpenSSL::RSA object';
    }
}


sub _load_key {
    my $self = shift;

    my $file = $self->{ key };

    if ( open my $KEY, '<', $file ) {
        my $text = '';
        local $/ = undef;
        $text = <$KEY>;
        close $KEY;

        if ( $text =~ m/BEGIN ([DR]SA) PRIVATE KEY/ ) {
            my $key_used = $1;

            if ( $key_used eq 'RSA' ) {
                $self->_load_rsa_key( $text );
            }
            else {
                $self->_load_dsa_key( $text );
            }

            return 1;
        }
        else {
            confess "Could not detect type of key $file.";
        }
    }
    else {
        confess "Could not load key $file: $!";
    }

    return;
}


=head2 get_response_xml

Generate the signed response xml and return it as a string

The method does what the w3c tells us to do (L<http://www.w3.org/TR/xmldsig-core/#sec-CoreGeneration>):



( run in 0.742 second using v1.01-cache-2.11-cpan-13bb782fe5a )