Net-SAML2

 view release on metacpan or  search on metacpan

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

    my ($self, $request) = @_;

    my $saml = _get_saml_from_soap($request);
    my @errors;
    if (defined $saml) {
        foreach my $cert (@{$self->idp_cert}) {
            my $success = try {
                $self->verify_xml(
                    $saml,
                    cert_text => $cert,
                    cacert    => $self->cacert
                );
                return 1;
            }
            catch { push (@errors, $_); return 0; };
            return $saml if $success;
        }

        if (@errors) {
            croak "Unable to verify XML with the given certificates: "
            . join(", ", @errors);
        }
    }

    return;
}

sub _get_saml_from_soap {
    my $soap  = shift;
    my $dom   = no_comments($soap);
    my $parser = XML::LibXML::XPathContext->new($dom);
    $parser->registerNs('soap-env', 'http://schemas.xmlsoap.org/soap/envelope/');
    $parser->registerNs('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol');
    my $set = $parser->findnodes('/soap-env:Envelope/soap-env:Body/*');
    if ($set->size) {
        return $set->get_node(1)->toString();
    }
    return;
}


sub create_soap_envelope {
    my ($self, $message) = @_;

    # sign the message
    my $sig = Net::SAML2::XML::Sig->new({
        x509 => 1,
        key  => $self->key,
        cert => $self->cert,
        exclusive => 1,
        no_xml_declaration => 1,
    });
    my $signed_message = $sig->sign($message);

    # OpenSSO ArtifactResolve hack
    #
    # OpenSSO's ArtifactResolve parser is completely hateful. It demands that
    # the order of child elements in an ArtifactResolve message be:
    #
    # 1: saml:Issuer
    # 2: dsig:Signature
    # 3: samlp:Artifact
    #
    # Really.
    #
    if ($signed_message =~ /ArtifactResolve/) {
        $signed_message =~ s!(<dsig:Signature.*?</dsig:Signature>)!!s;
        my $signature = $1;
        $signed_message =~ s/(<\/saml:Issuer>)/$1$signature/;
    }

    # test verify
    my $ret = $sig->verify($signed_message);
    die "failed to sign" unless $ret;

    my $soap = <<"SOAP";
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body>$signed_message</SOAP-ENV:Body></SOAP-ENV:Envelope>
SOAP
    return $soap;
}

__PACKAGE__->meta->make_immutable;

__END__

=pod

=encoding UTF-8

=head1 NAME

Net::SAML2::Binding::SOAP - SOAP binding for SAML

=head1 VERSION

version 0.85

=head1 SYNOPSIS

    my $soap = Net::SAML2::Binding::SOAP->new(
        url      => $idp_url,
        key      => $key,
        cert     => $cert,
        idp_cert => $idp_cert,
    );

    my $response = $soap->request($req);

Note that LWP::UserAgent maybe used which means that environment variables
may affect the use of https see:

=over

=item * L<PERL_LWP_SSL_CA_FILE and HTTPS_CA_FILE|https://metacpan.org/pod/LWP::UserAgent#SSL_ca_file-=%3E-$path>

=item * L<PERL_LWP_SSL_CA_PATH and HTTPS_CA_DIR|https://metacpan.org/pod/LWP::UserAgent#SSL_ca_path-=%3E-$path>

=back

=head1 METHODS

=head2 new( ... )

Constructor. Returns an instance of the SOAP binding configured for
the given IdP service url.

Arguments:



( run in 0.991 second using v1.01-cache-2.11-cpan-5a3173703d6 )