Skip to content

Commit af3b271

Browse files
committed
Update test for Net::SAML2::Protocol::AuthnRequest
Signed-off-by: Wesley Schwengle <[email protected]>
1 parent c83527e commit af3b271

File tree

3 files changed

+229
-153
lines changed

3 files changed

+229
-153
lines changed

lib/Net/SAML2/Protocol/AuthnRequest.pm

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ has 'provider_name' => (
132132
predicate => 'has_provider_name',
133133
);
134134

135-
# RequestedAuthnContext:
136135
has 'AuthnContextClassRef' => (
137136
isa => 'ArrayRef[Str]',
138137
is => 'rw',
@@ -154,14 +153,12 @@ has 'RequestedAuthnContext_Comparison' => (
154153
has 'force_authn' => (
155154
isa => 'Bool',
156155
is => 'ro',
157-
required => 0,
158156
predicate => 'has_force_authn',
159157
);
160158

161159
has 'is_passive' => (
162160
isa => 'Bool',
163161
is => 'ro',
164-
required => 0,
165162
predicate => 'has_is_passive',
166163
);
167164

@@ -226,21 +223,17 @@ sub as_xml {
226223
my @opts = qw(
227224
assertion_url assertion_index protocol_binding
228225
attribute_index provider_name destination
229-
issuer_namequalifier issuer_format force_authn
230-
is_passive
226+
force_authn is_passive
231227
);
232228

233229
foreach my $opt (@opts) {
234230
my $predicate = 'has_' . $opt;
235-
next unless $self->$predicate;
231+
next if !$self->can($predicate) || !$self->$predicate;
236232

237233
my $val = $self->$opt;
238234
if ($opt eq 'protocol_binding') {
239235
$req_atts{ $att_map{$opt} } = $protocol_bindings{$val};
240236
}
241-
elsif (any { $opt eq $_ } qw(issuer_namequalifier issuer_format)) {
242-
$issuer_attrs{ $att_map{$opt} } = $val;
243-
}
244237
elsif (any { $opt eq $_ } qw(force_authn is_passive)) {
245238
$req_atts{ $att_map{$opt} } = ( $val ? 'true' : 'false' );
246239
}
@@ -249,6 +242,14 @@ sub as_xml {
249242
}
250243
}
251244

245+
foreach my $opt (qw(issuer_namequalifier issuer_format)) {
246+
my $predicate = 'has_' . $opt;
247+
next if !$self->can($predicate) || !$self->$predicate;
248+
249+
my $val = $self->$opt;
250+
$issuer_attrs{ $att_map{$opt} } = $val;
251+
}
252+
252253
$x->startTag([$samlp, 'AuthnRequest'], %req_atts);
253254
$x->dataElement([$saml, 'Issuer'], $self->issuer, %issuer_attrs);
254255

t/09-authn-request.t

Lines changed: 171 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -6,145 +6,182 @@ use Test::Net::SAML2;
66
use Net::SAML2::Protocol::AuthnRequest;
77
use Net::SAML2::XML::Sig;
88

9-
my $ar = Net::SAML2::Protocol::AuthnRequest->new(
10-
issuer => 'http://some/sp',
11-
destination => 'http://some/idp',
12-
nameid_format => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
13-
nameid_allow_create => 1,
14-
);
15-
16-
isa_ok($ar, "Net::SAML2::Protocol::AuthnRequest");
17-
189
my $override
1910
= Sub::Override->override(
2011
'Net::SAML2::Protocol::AuthnRequest::issue_instant' =>
2112
sub { return 'myissueinstant' });
2213

23-
my $xml = $ar->as_xml;
24-
25-
my $xp = get_xpath(
26-
$xml,
27-
samlp => 'urn:oasis:names:tc:SAML:2.0:protocol',
28-
saml => 'urn:oasis:names:tc:SAML:2.0:assertion',
29-
);
30-
31-
test_xml_attribute_ok($xp, '/samlp:AuthnRequest/@ID', qr/^NETSAML2_/);
32-
33-
test_xml_attribute_ok($xp,
34-
'/samlp:AuthnRequest/@IssueInstant',
35-
'myissueinstant'
36-
);
37-
38-
test_xml_attribute_ok(
39-
$xp,
40-
'/samlp:AuthnRequest/samlp:NameIDPolicy/@Format',
41-
'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
42-
);
43-
44-
test_xml_attribute_ok($xp,
45-
'/samlp:AuthnRequest/samlp:NameIDPolicy/@AllowCreate', '1');
46-
47-
test_xml_attribute_exists($xp, '/samlp:AuthnRequest/@ForceAuthn', 0);
48-
49-
test_xml_attribute_exists($xp, '/samlp:AuthnRequest/@IsPassive', 0);
50-
51-
my $signer = Net::SAML2::XML::Sig->new({
52-
key => 't/sign-nopw-cert.pem',
53-
cert => 't/sign-nopw-cert.pem',
54-
});
55-
56-
isa_ok($signer, "Net::SAML2::XML::Sig");
57-
58-
my $signed = $signer->sign($xml);
59-
ok($signed);
60-
61-
my $verify = $signer->verify($signed);
62-
ok($verify);
63-
64-
$ar = Net::SAML2::Protocol::AuthnRequest->new(
65-
issuer => 'http://some/sp',
66-
destination => 'http://some/idp',
67-
nameid_format => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
68-
nameid_allow_create => 1,
69-
force_authn => '1',
70-
is_passive => '1'
71-
72-
);
73-
74-
isa_ok($ar, "Net::SAML2::Protocol::AuthnRequest");
75-
76-
$xml = $ar->as_xml;
77-
78-
$xp = get_xpath(
79-
$xml,
80-
samlp => 'urn:oasis:names:tc:SAML:2.0:protocol',
81-
saml => 'urn:oasis:names:tc:SAML:2.0:assertion',
82-
);
83-
84-
test_xml_attribute_exists($xp, '/samlp:AuthnRequest/@ForceAuthn', 1);
85-
test_xml_attribute_ok($xp, '/samlp:AuthnRequest/@ForceAuthn', 'true');
86-
87-
test_xml_attribute_exists($xp, '/samlp:AuthnRequest/@IsPassive', 1);
88-
test_xml_attribute_ok($xp, '/samlp:AuthnRequest/@IsPassive', 'true');
89-
90-
$ar = Net::SAML2::Protocol::AuthnRequest->new(
91-
issuer => 'http://some/sp',
92-
destination => 'http://some/idp',
93-
nameid_format => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
94-
nameid_allow_create => 1,
95-
force_authn => '0',
96-
is_passive => '0'
97-
98-
);
99-
100-
isa_ok($ar, "Net::SAML2::Protocol::AuthnRequest");
101-
102-
$xml = $ar->as_xml;
103-
104-
$xp = get_xpath(
105-
$xml,
106-
samlp => 'urn:oasis:names:tc:SAML:2.0:protocol',
107-
saml => 'urn:oasis:names:tc:SAML:2.0:assertion',
108-
);
109-
110-
test_xml_attribute_exists($xp, '/samlp:AuthnRequest/@ForceAuthn', 1);
111-
test_xml_attribute_ok($xp, '/samlp:AuthnRequest/@ForceAuthn', 'false');
112-
113-
test_xml_attribute_exists($xp, '/samlp:AuthnRequest/@IsPassive', 1);
114-
test_xml_attribute_ok($xp, '/samlp:AuthnRequest/@IsPassive', 'false');
115-
116-
my $sp = net_saml2_sp(
117-
authnreq_signed => 0,
118-
want_assertions_signed => 0,
119-
slo_url_post => '/sls-post-response',
120-
slo_url_soap => '/slo-soap',
121-
);
122-
123-
my %params = (
124-
force_authn => 1,
125-
is_passive => 0,
126-
);
127-
128-
my $req = $sp->authn_request(
129-
$sp->id,
130-
'',
131-
%params,
132-
);
133-
134-
$xml = $req->as_xml;
135-
136-
$xp = get_xpath(
137-
$xml,
138-
samlp => 'urn:oasis:names:tc:SAML:2.0:protocol',
139-
saml => 'urn:oasis:names:tc:SAML:2.0:assertion',
140-
);
141-
142-
test_xml_attribute_exists($xp, '/samlp:AuthnRequest/@ForceAuthn', 1);
143-
test_xml_attribute_ok($xp, '/samlp:AuthnRequest/@ForceAuthn', 'true');
144-
145-
test_xml_attribute_exists($xp, '/samlp:AuthnRequest/@IsPassive', 1);
146-
test_xml_attribute_ok($xp, '/samlp:AuthnRequest/@IsPassive', 'false');
14+
$override->override('Net::SAML2::Protocol::AuthnRequest::_build_id' =>
15+
sub { return 'NETSAML2_fake_id' });
16+
17+
{
18+
my ($ar, $xp) = net_saml2_authnreq(
19+
nameid => 'mynameid',
20+
nameid_format =>
21+
'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
22+
nameid_allow_create => 1,
23+
issuer_namequalifier => 'bar',
24+
issuer_format => 'foo',
25+
);
26+
27+
my %attributes = (
28+
Destination => 'http://some/idp',
29+
ID => 'NETSAML2_fake_id',
30+
IssueInstant => 'myissueinstant',
31+
Version => '2.0',
32+
);
33+
34+
test_node_attributes_ok($xp, '/samlp:AuthnRequest', \%attributes);
35+
36+
my $node = get_single_node_ok($xp, '/samlp:AuthnRequest/saml:Issuer');
37+
is($node->textContent, 'http://some/sp', '... and has the correct value');
38+
is($node->getAttribute('Format'), 'foo', '.. and Format attribute is ok');
39+
is($node->getAttribute('NameQualifier'),
40+
'bar', ".. and NameQualifier attribute is ok");
41+
42+
test_xml_attribute_ok($xp,
43+
'/samlp:AuthnRequest/saml:Subject/saml:NameID/@NameQualifier',
44+
'mynameid');
45+
46+
%attributes = (
47+
Format => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
48+
AllowCreate => 1,
49+
);
50+
51+
test_node_attributes_ok($xp, '/samlp:AuthnRequest/samlp:NameIDPolicy',
52+
\%attributes);
53+
54+
ok(!$xp->exists('/samlp:AuthnRequest/samlp:RequestedAuthnContext'),
55+
"We don't have RequestedAuthnContext");
56+
57+
### TODO: Does this really belong here?
58+
my $signer = Net::SAML2::XML::Sig->new(
59+
{
60+
key => 't/sign-nopw-cert.pem',
61+
cert => 't/sign-nopw-cert.pem',
62+
}
63+
);
64+
65+
isa_ok($signer, "Net::SAML2::XML::Sig");
66+
67+
my $signed = $signer->sign($xp->getContextNode->toString);
68+
ok($signed, "Signed with XML::Sig");
69+
70+
my $verify = $signer->verify($signed);
71+
ok($verify, "Verified with XML::Sig");
72+
### END TODO
73+
}
74+
75+
76+
{
77+
my ($ar, $xp) = net_saml2_authnreq(
78+
force_authn => '1',
79+
is_passive => '1'
80+
);
81+
my %attributes = (
82+
Destination => ignore(),
83+
ForceAuthn => 'true',
84+
ID => ignore(),
85+
IsPassive => 'true',
86+
IssueInstant => 'myissueinstant',
87+
Version => '2.0',
88+
);
89+
test_node_attributes_ok($xp, '/samlp:AuthnRequest', \%attributes);
90+
}
91+
92+
{
93+
my ($ar, $xp) = net_saml2_authnreq(
94+
force_authn => '0',
95+
is_passive => '0'
96+
);
97+
98+
my %attributes = (
99+
Destination => ignore(),
100+
ID => ignore(),
101+
IssueInstant => ignore(),
102+
Version => ignore(),
103+
ForceAuthn => 'false',
104+
IsPassive => 'false',
105+
);
106+
test_node_attributes_ok($xp, '/samlp:AuthnRequest', \%attributes);
107+
}
108+
109+
{
110+
111+
my ($ar, $xp) = net_saml2_authnreq(
112+
assertion_url => 'https://foo.bar/assertion',
113+
assertion_index => 1,
114+
attribute_index => 42,
115+
protocol_binding => 'HTTP-POST',
116+
);
117+
118+
my %attributes = (
119+
Destination => ignore(),
120+
ID => ignore(),
121+
IssueInstant => ignore(),
122+
Version => ignore(),
123+
AssertionConsumerServiceURL => 'https://foo.bar/assertion',
124+
AssertionConsumerServiceIndex => 1,
125+
AttributeConsumingServiceIndex => 42,
126+
ProtocolBinding => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
127+
);
128+
129+
test_node_attributes_ok($xp, '/samlp:AuthnRequest', \%attributes);
130+
131+
}
132+
133+
{
134+
my ($ar, $xp) = net_saml2_authnreq(AuthnContextClassRef => [qw(foo bar)],);
135+
136+
my @nodes
137+
= $xp->findnodes(
138+
'/samlp:AuthnRequest/samlp:RequestedAuthnContext/saml:AuthnContextClassRef'
139+
);
140+
is(@nodes, 2, "and has two AuthnContextClassRef nodes");
141+
142+
is($nodes[0]->textContent(),
143+
"foo", "... and the correct content for node 1");
144+
is($nodes[1]->textContent(),
145+
"bar", "... and the correct content for node 2");
146+
}
147+
148+
{
149+
my ($ar, $xp) = net_saml2_authnreq(AuthnContextDeclRef => [qw(foo bar)],);
150+
151+
my @nodes
152+
= $xp->findnodes(
153+
'/samlp:AuthnRequest/samlp:RequestedAuthnContext/saml:AuthnContextDeclRef'
154+
);
155+
is(@nodes, 2, "and has two AuthnContextDeclRef nodes");
156+
157+
is($nodes[0]->textContent(),
158+
"foo", "... and the correct content for node 1");
159+
is($nodes[1]->textContent(),
160+
"bar", "... and the correct content for node 2");
161+
}
162+
163+
{
164+
165+
my $sp = net_saml2_sp(
166+
authnreq_signed => 0,
167+
want_assertions_signed => 0,
168+
slo_url_post => '/sls-post-response',
169+
slo_url_soap => '/slo-soap',
170+
);
171+
172+
my %params = (
173+
force_authn => 1,
174+
is_passive => 0,
175+
);
176+
177+
my $req = $sp->authn_request($sp->id, '', %params,);
178+
179+
my $xp = get_xpath(
180+
$req->as_xml,
181+
samlp => 'urn:oasis:names:tc:SAML:2.0:protocol',
182+
saml => 'urn:oasis:names:tc:SAML:2.0:assertion',
183+
);
184+
}
147185

148-
$xml = $ar->as_xml;
149186

150187
done_testing;

0 commit comments

Comments
 (0)