Net-SPID
view release on metacpan or search on metacpan
lib/Net/SPID/SAML/IdP.pm view on Meta::CPAN
package Net::SPID::SAML::IdP;
$Net::SPID::SAML::IdP::VERSION = '0.15';
use Moo;
has '_spid' => (is => 'ro', required => 1, weak_ref => 1); # Net::SPID::SAML
has 'xml' => (is => 'ro', required => 1);
has 'entityID' => (is => 'ro', required => 1);
has 'cert' => (is => 'ro', required => 1);
has 'sso_urls' => (is => 'ro', default => sub { {} });
has 'sloreq_urls' => (is => 'ro', default => sub { {} });
has 'slores_urls' => (is => 'ro', default => sub { {} });
use Carp;
use Crypt::OpenSSL::X509;
use Mojo::XMLSig;
use XML::XPath;
sub new_from_xml {
my ($class, %args) = @_;
my $xpath = XML::XPath->new(xml => $args{xml});
$xpath->set_namespace('md', 'urn:oasis:names:tc:SAML:2.0:metadata');
$xpath->set_namespace('ds', 'http://www.w3.org/2000/09/xmldsig#');
if ($xpath->findnodes('/md:EntityDescriptor/dsig:Signature')->size > 0) {
# TODO: validate certificate against a known CA
Mojo::XMLSig::verify($args{xml})
or croak "Signature verification failed";
}
$args{entityID} = $xpath->findvalue('/md:EntityDescriptor/@entityID')->value;
$args{sso_urls} //= {};
for my $sso ($xpath->findnodes('/md:EntityDescriptor/md:IDPSSODescriptor/md:SingleSignOnService')){
my $binding = $sso->getAttribute('Binding');
$args{sso_urls}{$binding} = $sso->getAttribute('Location');
}
$args{sloreq_urls} //= {};
$args{slores_urls} //= {};
for my $slo ($xpath->findnodes('/md:EntityDescriptor/md:IDPSSODescriptor/md:SingleLogoutService')) {
my $binding = $slo->getAttribute('Binding');
$args{sloreq_urls}{$binding} = $slo->getAttribute('Location');
$args{slores_urls}{$binding} = $slo->getAttribute('Location') // $slo->getAttribute('ResponseLocation');
}
for my $certnode ($xpath->findnodes('/md:EntityDescriptor/md:IDPSSODescriptor/md:KeyDescriptor[@use="signing"]/ds:KeyInfo/ds:X509Data/ds:X509Certificate/text()')) {
my $cert = $certnode->getValue;
# rewrap the base64 data from the metadata; it may not
# be wrapped at 64 characters as PEM requires
$cert =~ s/\s//g;
$cert = join "\n", $cert =~ /.{1,64}/gs;
# form a PEM certificate
$args{cert} = Crypt::OpenSSL::X509->new_from_string(
"-----BEGIN CERTIFICATE-----\n$cert\n-----END CERTIFICATE-----\n",
Crypt::OpenSSL::X509::FORMAT_PEM,
);
}
return $class->new(%args);
}
sub authnrequest {
my ($self, %args) = @_;
return Net::SPID::SAML::Out::AuthnRequest->new(
_spid => $self->_spid,
_idp => $self,
%args,
);
}
sub logoutrequest {
my ($self, %args) = @_;
return Net::SPID::SAML::Out::LogoutRequest->new(
_spid => $self->_spid,
_idp => $self,
%args,
);
}
sub logoutresponse {
( run in 0.842 second using v1.01-cache-2.11-cpan-71847e10f99 )