Net-SAML2

 view release on metacpan or  search on metacpan

lib/Net/SAML2/Binding/POST.pm  view on Meta::CPAN

has 'key'  => (isa => 'Str', is => 'ro', required => 0, predicate => 'has_key');
has 'insecure_trust_embedded_cert' => (isa => 'Bool', is => 'ro', default => 0);


sub handle_response {
    my ($self, $response) = @_;

    unless ($self->cacert
         || $self->cert_text
         || $self->insecure_trust_embedded_cert) {
        croak(
            "Net::SAML2::Binding::POST::handle_response requires 'cacert' "
          . "or 'cert_text' on the binding to verify SAML response "
          . "signatures. To explicitly disable signature verification "
          . "(test/dev only), pass insecure_trust_embedded_cert => 1 to new()."
        );
    }

    # unpack and check the signature
    my $xml = decode_base64($response);

    $self->verify_xml(
        $xml,
        no_xml_declaration => 1,
        $self->cert_text ? (
            cert_text => $self->cert_text
        ) : (),
        $self->cacert ? (
            cacert => $self->cacert
        ) : (),

    );
    return $xml;
}


sub sign_xml {
    my ($self, $request) = @_;

    croak("Need to have a cert specified") unless $self->has_cert;
    croak("Need to have a key specified") unless $self->has_key;

    my $signer = XML::Sig->new({
                        key => $self->key,
                        cert => $self->cert,
                        no_xml_declaration => 1,
                    }
                );

    my $signed_message = $signer->sign($request);

    # saml-schema-protocol-2.0.xsd Schema hack
    #
    # The real fix here is to fix XML::Sig to accept a XPATH to
    # place the signature in the correct location.  Or use XML::LibXML
    # here to do so
    #
    # The protocol schema defines a sequence which requires the order
    # of the child elements in a Protocol based message:
    #
    # The dsig:Signature (should it exist) MUST follow the saml:Issuer
    #
    # 1: saml:Issuer
    # 2: dsig:Signature
    #
    # Seems like an oversight in the SAML schema specifiation but...

    $signed_message =~ s!(<dsig:Signature.*?</dsig:Signature>)!!s;
    my $signature = $1;
    $signed_message =~ s/(<\/saml\d*:Issuer>)/$1$signature/;

    my $encoded_request = encode_base64($signed_message, "\n");

    return $encoded_request;

}
__PACKAGE__->meta->make_immutable;

__END__

=pod

=encoding UTF-8

=head1 NAME

Net::SAML2::Binding::POST - HTTP POST binding for SAML

=head1 VERSION

version 0.88

=head1 SYNOPSIS

  my $post = Net::SAML2::Binding::POST->new(
    cacert => '/path/to/ca-cert.pem'
  );
  my $xml = $post->handle_response(
    $saml_response
  );

=head1 METHODS

=head2 new( )

Constructor. Returns an instance of the POST binding.

Arguments:

=over

=item B<cacert>

path to the CA certificate for verification

B<Notice>: when C<handle_response> is called, at least one of
C<cacert> or C<cert_text> must have been supplied at construction,
unless C<insecure_trust_embedded_cert> is set. Without a trust anchor
the binding accepts whatever signing certificate the response embeds
in its KeyInfo block, which is equivalent to no signature checking
at all.

=item B<cert>

path to a certificate that is added to the signed XML.  It needs to be the
certificate that includes the public key related to the B<key>

=item B<cert_text>



( run in 1.831 second using v1.01-cache-2.11-cpan-5fbc6bb55f2 )