From eb15002913f0765e27f005fcc0c8fd773a2c2694 Mon Sep 17 00:00:00 2001 From: Chris Andrews Date: Oct 05 2010 12:52:37 +0000 Subject: Add basic POD everywhere - passing Author tests. --- diff --git a/lib/Net/SAML2/Binding/Artifact.pm b/lib/Net/SAML2/Binding/Artifact.pm index 78841b1..f9925da 100644 --- a/lib/Net/SAML2/Binding/Artifact.pm +++ b/lib/Net/SAML2/Binding/Artifact.pm @@ -2,10 +2,43 @@ package Net::SAML2::Binding::Artifact; use strict; use warnings; +=head1 NAME + +Net::SAML2::Binding::Artifact - SOAP Artifact binding for SAML2 + +=head1 SYNOPSIS + + my $resolver = Net::SAML2::Binding::Artifact->new( + url => $art_url, + key => 'sign-private.pem', + cert => 'sign-certonly.pem', + issuer => 'http://localhost:3000', + ); + + my $response = $resolver->resolve(params->{SAMLart}); + +=head1 METHODS + +=cut + use XML::Sig; use LWP::UserAgent; use HTTP::Request::Common; +=head2 new( ... ) + +Constructor. Returns an instance of the Artifact binding configured +for the given SP issuer and IdP resolver service url. + +Arguments: + + * url - the resolver service URL + * key - path to the signing key + * cert - path to the signing certificate + * issuer - the issuing SP's identity URI + +=cut + sub new { my ($class, %args) = @_; my $self = bless {}, $class; @@ -18,6 +51,14 @@ sub new { return $self; } +=head2 resolve($artifact) + +Resolve the given artifact, which should be an opaque SAML2 artifact id. + +Returns the Artifact, or dies if there was an error. + +=cut + sub resolve { my ($self, $artifact) = @_; diff --git a/lib/Net/SAML2/Binding/POST.pm b/lib/Net/SAML2/Binding/POST.pm index 4a26780..697ac42 100644 --- a/lib/Net/SAML2/Binding/POST.pm +++ b/lib/Net/SAML2/Binding/POST.pm @@ -2,15 +2,45 @@ package Net::SAML2::Binding::POST; use strict; use warnings; +=head1 NAME + +Net::SAML2::Binding::POST - HTTP POST binding for SAML2 + +=head1 SYNOPSIS + + my $post = Net::SAML2::Binding::POST->new; + my $ret = $post->handle_response( + $saml_response + ); + +=head1 METHODS + +=cut + use XML::Sig; use MIME::Base64 qw/ decode_base64 /; +=head2 new() + +Constructor. Returns an instance of the POST binding. + +No arguments. + +=cut + sub new { my ($class, %args) = @_; my $self = bless {}, $class; return $self; } +=head2 handle_response($response) + +Decodes and verifies the response provided, which should be the raw +Base64-encoded response, from the SAMLResponse CGI parameter. + +=cut + sub handle_response { my ($self, $response) = @_; my $xml = decode_base64($response); diff --git a/lib/Net/SAML2/Binding/Redirect.pm b/lib/Net/SAML2/Binding/Redirect.pm index 0fd31ff..8bd0851 100644 --- a/lib/Net/SAML2/Binding/Redirect.pm +++ b/lib/Net/SAML2/Binding/Redirect.pm @@ -2,6 +2,29 @@ package Net::SAML2::Binding::Redirect; use strict; use warnings; +=head1 NAME + +Net::SAML2::Binding::Redirect + +=head1 SYNOPSIS + + my $redirect = Net::SAML2::Binding::Redirect->new( + key => 'sign-nopw-cert.pem', + url => $sso_url, + ); + + my $url = $redirect->sign_request($authnreq); + + # or + + my $ret = $post->handle_response( + $saml_response + ); + +=head1 METHODS + +=cut + use MIME::Base64 qw/ encode_base64 decode_base64 /; use IO::Compress::RawDeflate qw/ rawdeflate /; use IO::Uncompress::RawInflate qw/ rawinflate /; @@ -10,6 +33,17 @@ use URI::QueryParam; use Crypt::OpenSSL::RSA; use File::Slurp qw/ read_file /; +=head2 new( ... ) + +Constructor. Creates an instance of the Redirect binding. + +Arguments: + + * key - the signing key + * url - the IdP's SSO service url for the Redirect binding + +=cut + sub new { my ($class, %args) = @_; my $self = bless {}, $class; @@ -20,6 +54,17 @@ sub new { return $self; } +=head2 sign_request($request, $relaystate) + +Signs the given request, and returns the URL to which the user's +browser should be redirected. + +Accepts an optional RelayState parameter, a string which will be +returned to the requestor when the user returns from the +authentication process with the IdP. + +=cut + sub sign_request { my ($self, $request, $relaystate) = @_; @@ -43,6 +88,14 @@ sub sign_request { return $url; } +=head2 handle_response($response) + +Decode a Redirect binding URL. + +Should also verify the signature on the response. + +=cut + sub handle_response { my ($self, $response) = @_; my $deflated = decode_base64($response); @@ -50,6 +103,8 @@ sub handle_response { my $output = ''; rawinflate \$deflated => \$output; + # Should verify the response + return $output; } diff --git a/lib/Net/SAML2/IdP.pm b/lib/Net/SAML2/IdP.pm index 3818d76..2b056fd 100644 --- a/lib/Net/SAML2/IdP.pm +++ b/lib/Net/SAML2/IdP.pm @@ -2,10 +2,31 @@ package Net::SAML2::IdP; use strict; use warnings; +=head1 NAME + +Net::SAML2::IdP - SAML Identity Provider object + +=head1 SYNOPSIS + + my $idp = Net::SAML2::IdP->new_from_url($IDP); + my $sso_url = $idp->sso_url('urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'); + +=head1 METHODS + +=cut + use HTTP::Request::Common; use LWP::UserAgent; use XML::XPath; +=head2 new_from_url($url) + +Create an IdP object by retrieving the metadata at the given URL. + +Dies if the metadata can't be retrieved. + +=cut + sub new_from_url { my ($class, $url) = @_; @@ -19,6 +40,13 @@ sub new_from_url { return $class->new($xml); } +=head2 new($xml) + +Constructor. Create an IdP object using the provided metadata XML +document. + +=cut + sub new { my ($class, $xml) = @_; my $self = bless {}, $class; @@ -47,16 +75,37 @@ sub new { return $self; } +=head2 sso_url($binding) + +Returns the url for the SSO service using the given binding. Binding +name should be the full URI. + +=cut + sub sso_url { my ($self, $binding) = @_; return $self->{SSO}->{$binding}; } +=head2 slo_url($binding) + +Returns the url for the Single Logout Service using the given +binding. Binding name should be the full URI. + +=cut + sub slo_url { my ($self, $binding) = @_; return $self->{SLO}->{$binding}; } +=head2 art_url($binding) + +Returns the url for the Artifact Resolution service using the given +binding. Binding name should be the full URI. + +=cut + sub art_url { my ($self, $binding) = @_; return $self->{Art}->{$binding}; diff --git a/lib/Net/SAML2/Protocol/Assertion.pm b/lib/Net/SAML2/Protocol/Assertion.pm index 338f883..d3ec7a2 100644 --- a/lib/Net/SAML2/Protocol/Assertion.pm +++ b/lib/Net/SAML2/Protocol/Assertion.pm @@ -2,8 +2,29 @@ package Net::SAML2::Protocol::Assertion; use strict; use warnings; +=head1 NAME + +Net::SAML2::Protocol::Assertion - SAML2 assertion object + +=head1 SYNOPSIS + + my $assertion = Net::SAML2::Protocol::Assertion->new( + xml => decode_base64($SAMLResponse) + ); + +=head1 METHODS + +=cut + use XML::XPath; +=head2 new( ... ) + +Constructor. Creates an instance of the Assertion object, parsing the +given XML to find the attributes, session and nameid. + +=cut + sub new { my ($class, %args) = @_; my $self = bless {}, $class; @@ -23,21 +44,46 @@ sub new { return $self; } +=head2 attributes() + +Returns a hash of SAML attributes found in the assertion. + +=cut + sub attributes { my ($self) = @_; return $self->{attributes}; } +=head2 session() + +Returns the SAML session identifier, which may be used in a +LogoutRequest to terminate this session. + +=cut + sub session { my ($self) = @_; return $self->{session}; } +=head2 nameid() + +Returns the nameid in the Assertion. + +=cut + sub nameid { my ($self) = @_; return $self->{nameid}; } +=head2 name + +Returns the CN attribute, if provided. + +=cut + sub name { my ($self) = @_; return $self->{attributes}->{CN}; diff --git a/lib/Net/SAML2/Protocol/AuthnRequest.pm b/lib/Net/SAML2/Protocol/AuthnRequest.pm index f4dba2f..935d60a 100644 --- a/lib/Net/SAML2/Protocol/AuthnRequest.pm +++ b/lib/Net/SAML2/Protocol/AuthnRequest.pm @@ -1,8 +1,37 @@ package Net::SAML2::Protocol::AuthnRequest; use strict; use warnings; + +=head1 NAME + +Net::SAML2::Protocol::AuthnRequest - SAML2 AuthnRequest object + +=head1 SYNOPSIS + + my $authnreq = Net::SAML2::Protocol::AuthnRequest->new( + issueinstant => DateTime->now, + issuer => $self->{id}, + destination => $destination, + ); + +=head1 METHODS + +=cut + use DateTime::Format::XSD; +=head2 new( ... ) + +Constructor. Creates an instance of the AuthnRequest object. + +Arguments: + + * issueinstant - a DateTime for "now" + * issuer - the SP's identity URI + * destination - the IdP's identity URI + +=cut + sub new { my ($class, %args) = @_; my $self = bless {}, $class; @@ -14,6 +43,12 @@ sub new { return $self; } +=head2 as_xml() + +Returns the AuthnRequest as XML. + +=cut + sub as_xml { my ($self) = @_; diff --git a/lib/Net/SAML2/Protocol/LogoutRequest.pm b/lib/Net/SAML2/Protocol/LogoutRequest.pm index fb97011..69cce2f 100644 --- a/lib/Net/SAML2/Protocol/LogoutRequest.pm +++ b/lib/Net/SAML2/Protocol/LogoutRequest.pm @@ -2,6 +2,34 @@ package Net::SAML2::Protocol::LogoutRequest; use strict; use warnings; +=head1 NAME + +Net::SAML2::Protocol::LogoutRequest - the SAML2 LogoutRequest object + +=head1 SYNOPSIS + + my $logout_req = Net::SAML2::Protocol::LogoutRequest->new( + issuer => $issuer, + destination => $destination, + nameid => $nameid, + session => $session, + ); + +=head1 METHODS + +=head2 new( ... ) + +Constructor. Returns an instance of the LogoutRequest object. + +Arguments: + + * session - the session to log out + * nameid - the NameID of the user to log out + * issuer - the SP's identity URI + * destination - the IdP's identity URI + +=cut + sub new { my ($class, %args) = @_; my $self = bless {}, $class; @@ -14,6 +42,12 @@ sub new { return $self; } +=head2 as_xml() + +Returns the LogoutRequest as XML. + +=cut + sub as_xml { my ($self) = @_; diff --git a/lib/Net/SAML2/SP.pm b/lib/Net/SAML2/SP.pm index 9a4ef77..818761a 100644 --- a/lib/Net/SAML2/SP.pm +++ b/lib/Net/SAML2/SP.pm @@ -2,8 +2,36 @@ package Net::SAML2::SP; use strict; use warnings; +=head1 NAME + +Net::SAML2::SP - SAML Service Provider object + +=head1 SYNOPSIS + + my $sp = Net::SAML2::SP->new( + id => 'http://localhost:3000', + url => 'http://localhost:3000', + cert => 'sign-nopw-cert.pem', + ); + +=head1 METHODS + +=cut + use Crypt::OpenSSL::X509; +=head2 new( ... ) + +Constructor. Create an SP object. + +Arguments: + + * url - the base for all SP service URLs + * id - the SP's identity URI. + * cert - path to the signing certificate + +=cut + sub new { my ($class, %args) = @_; my $self = bless {}, $class; @@ -18,6 +46,13 @@ sub new { return $self; } +=head2 authn_request($destination) + +Returns an AuthnRequest object created by this SP, intended for the +given destination, which should be the identity URI of the IdP. + +=cut + sub authn_request { my ($self, $destination) = @_; @@ -30,6 +65,15 @@ sub authn_request { return $authnreq; } +=head2 logout_request($destination, $nameid, $session) + +Returns an AuthnRequest object created by this SP, intended for the +given destination, which should be the identity URI of the IdP. + +Also requires the nameid and session to be logged out. + +=cut + sub logout_request { my ($self, $destination, $nameid, $session) = @_; @@ -43,6 +87,12 @@ sub logout_request { return $logout_req; } +=head2 metadata + +Returns the metadata XML document for this SP. + +=cut + sub metadata { my ($self) = @_; diff --git a/t/02-create-sp.t b/t/02-create-sp.t index ef02a9d..44820ac 100644 --- a/t/02-create-sp.t +++ b/t/02-create-sp.t @@ -2,9 +2,9 @@ use Test::More; use Net::SAML2; my $sp = Net::SAML2::SP->new( - id => 'http://localhost:3000', - url => 'http://localhost:3000', - cert => 't/sign-nopw-cert.pem', + id => 'http://localhost:3000', + url => 'http://localhost:3000', + cert => 't/sign-nopw-cert.pem', ); ok($sp); ok($sp->metadata);