Skip to content

Commit e8fb008

Browse files
authored
Merge pull request #112 from timlegge/master
Sync changes with the wiki page and clean up indents
2 parents 764eb88 + c1b25f9 commit e8fb008

File tree

1 file changed

+91
-96
lines changed

1 file changed

+91
-96
lines changed

TUTORIAL.md

Lines changed: 91 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,23 @@ In the case of Forwiki.org mentioned above it has a login function that is calle
1515
The metadata is provided by the Identity Provider (IdP). Net::SAML2:IdP->new_from_url or Net::SAML2IdP->new_from_xml will take the metadata in the from specified and parse the metadata returning a Net::SAML2::IdP object
1616

1717
```
18-
my $idp = Net::SAML2::IdP->new_from_url(
19-
url => $metadata, # URL where the xml is located
20-
cacert => $cacert, # Filename of the Identity Providers CACert
21-
ssl_opts => # Optional options supported by LWP::Protocol::https
22-
{
23-
SSL_ca_file => '/your/directory/cacert.pem',
24-
SSL_ca_path => '/etc/ssl/certs',
25-
verify_hostname => 1,
26-
}
27-
28-
);
29-
```
18+
my $idp = Net::SAML2::IdP->new_from_url(
19+
url => $metadata, # URL where the xml is located
20+
cacert => $cacert, # Filename of the Identity Providers CACert
21+
ssl_opts => # Optional options supported by LWP::Protocol::https
22+
{
23+
SSL_ca_file => '/your/directory/cacert.pem',
24+
SSL_ca_path => '/etc/ssl/certs',
25+
verify_hostname => 1,
26+
}
27+
);
3028
31-
or
29+
# or
3230
33-
```
34-
my $idp = Net::SAML2::IdP->new_from_xml(
35-
xml => $metadata_string, # xml as a string
36-
cacert => $cacert, # Filename of the Identity Providers CACert
37-
);
31+
my $idp = Net::SAML2::IdP->new_from_xml(
32+
xml => $metadata_string, # xml as a string
33+
cacert => $cacert, # Filename of the Identity Providers CACert
34+
);
3835
```
3936

4037
The IdP object contains the Identity Providers settings that were parse from the metadata and are then used for the rest of the calls.
@@ -94,14 +91,14 @@ There are two methods to create the Authentication Request.
9491
However, it is better to use new() here because it makes tracking the AuthnRequest ID easier for later verification.
9592

9693
```
97-
my $authnreq = Net::SAML2::Protocol::AuthnRequest->new(
98-
issuer => $issuer,
99-
destination => $idp->sso_url('urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'),
100-
provider_name => $provider_name,
101-
);
94+
my $authnreq = Net::SAML2::Protocol::AuthnRequest->new(
95+
issuer => $issuer,
96+
destination => $idp->sso_url('urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'),
97+
provider_name => $provider_name,
98+
);
10299
103-
# Store the request's id for later verification
104-
my saml_request_id = $authnreq->id
100+
# Store the request's id for later verification
101+
my saml_request_id = $authnreq->id
105102
```
106103

107104
The **issuer** is the identifier that the web application uses to identify itself to the SAML2 Identity Provider. You will need to specify that identifier in the setup of your chosen Identity provider (GSuite, Azure, OneLogin, KeyCloak, etc)
@@ -113,16 +110,16 @@ The **destination** is set to the IdP's Single Sign-On Url that was parsed from
113110
The Net::SAML2::Protocol::AuthnRequest contains:
114111

115112
```
116-
$VAR1 = bless( {
117-
'issue_instant' => '2021-02-06T20:04:33Z',
118-
'RequestedAuthnContext_Comparison' => 'exact',
119-
'issuer' => bless( do{\(my $o = 'http://localhost:3000')}, 'URI::http' ),
120-
'id' => 'NETSAML2_2b0619fe11c985257aafeceec7de69b2',
121-
'destination' => bless( do{\(my $o = 'http://sso.dev.venda.com/opensso')}, 'URI::http' ),
122-
'AuthnContextClassRef' => [],
123-
'nameidpolicy_format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
124-
'AuthnContextDeclRef' => []
125-
}, 'Net::SAML2::Protocol::AuthnRequest' );
113+
$VAR1 = bless( {
114+
'issue_instant' => '2021-02-06T20:04:33Z',
115+
'RequestedAuthnContext_Comparison' => 'exact',
116+
'issuer' => bless( do{\(my $o = 'http://localhost:3000')}, 'URI::http' ),
117+
'id' => 'NETSAML2_2b0619fe11c985257aafeceec7de69b2',
118+
'destination' => bless( do{\(my $o = 'http://sso.dev.venda.com/opensso')}, 'URI::http' ),
119+
'AuthnContextClassRef' => [],
120+
'nameidpolicy_format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
121+
'AuthnContextDeclRef' => []
122+
}, 'Net::SAML2::Protocol::AuthnRequest' );
126123
```
127124
and produces the following XML:
128125

@@ -167,13 +164,13 @@ The Net::SAML2::Binding::Redirect is used to create the redirect URL that will b
167164
In addition, it could be used to process a redirect from the IdP to process a LoginRequest or LogoutResponse.
168165

169166
```
170-
my $redirect = Net::SAML2::Binding::Redirect->new(
171-
key => $sp_signing_cert,
172-
cert => $idp->cert('signing'),
173-
param => 'SAMLRequest',
174-
# The ssl_url destination for redirect
175-
url => $idp->sso_url('urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'),
176-
);
167+
my $redirect = Net::SAML2::Binding::Redirect->new(
168+
key => $sp_signing_cert,
169+
cert => $idp->cert('signing'),
170+
param => 'SAMLRequest',
171+
# The ssl_url destination for redirect
172+
url => $idp->sso_url('urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'),
173+
);
177174
```
178175

179176
**Note:** This is an odd one. The cert parameter here is the IdP's signing certificate.
@@ -185,12 +182,12 @@ In Net::SAML2::Binding::Redirect->Verify() the IdP's signing certificate is used
185182
the creation of the Net::SAML2::Binding::Redirect results in:
186183

187184
```
188-
$VAR1 = bless( {
189-
'param' => 'SAMLRequest',
190-
'url' => bless( do{\(my $o = 'http://sso.dev.venda.com/opensso/SSORedirect/metaAlias/idp')}, 'URI::http' ),
191-
'cert' => [
192-
{
193-
'signing' => '-----BEGIN CERTIFICATE-----
185+
$VAR1 = bless( {
186+
'param' => 'SAMLRequest',
187+
'url' => bless( do{\(my $o = 'http://sso.dev.venda.com/opensso/SSORedirect/metaAlias/idp')}, 'URI::http' ),
188+
'cert' => [
189+
{
190+
'signing' => '-----BEGIN CERTIFICATE-----
194191
MIIDFTCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQUFADA3MQswCQYDVQQGEwJVUzEO
195192
MAwGA1UECgwFbG9jYWwxCzAJBgNVBAsMAmN0MQswCQYDVQQDDAJDQTAeFw0xMDEw
196193
MDYxMjM4MTRaFw0xMTEwMDYxMjM4MTRaMFcxCzAJBgNVBAYTAlVTMQ4wDAYDVQQK
@@ -210,10 +207,10 @@ WPp/0bQqdAAUzkJZPpUGUN1sTXPJexYT6na7XvLd6mvO1g+WDk6aZnW/zcT3T9tL
210207
Iavyic/p4gZtXckweq+VTn9CdZp6ZTQtVw==
211208
-----END CERTIFICATE-----
212209
'
213-
}
214-
],
215-
'key' => 't/sign-nopw-cert.pem'
216-
}, 'Net::SAML2::Binding::Redirect' );
210+
}
211+
],
212+
'key' => 't/sign-nopw-cert.pem'
213+
}, 'Net::SAML2::Binding::Redirect' );
217214
```
218215

219216
#### key
@@ -233,7 +230,7 @@ The **url** is the the Single Sign On URL that was specified in the Identity Pro
233230
The URL is created by calling the sign function of the Net::SAML2::Binding::Redirect object with the xml version of the AuthnRequest.
234231

235232
```
236-
my $url = $redirect->sign($authnreq->as_xml);
233+
my $url = $redirect->sign($authnreq->as_xml);
237234
238235
```
239236
The signed URL is that results is:
@@ -249,18 +246,18 @@ At this point the web application needs to redirect the user's browser to the UR
249246
Using a browser add-on like **SAML Message Decoder** you should be able to view the fields in the SAML2 request that the browser sent.
250247

251248
```
252-
<saml2p:AuthnRequest
253-
Destination="http://sso.dev.venda.com/opensso"
254-
IssueInstant="2021-02-06T20:07:01Z"
255-
ID="NETSAML2_8b051f5fadfc747def3a8972df2c4984"
256-
Version="2.0"
257-
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
258-
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
259-
<saml2:Issuer>http://localhost:3000</saml2:Issuer>
260-
<saml2p:NameIDPolicy
261-
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
262-
</saml2p:NameIDPolicy>
263-
</saml2p:AuthnRequest>
249+
<saml2p:AuthnRequest
250+
Destination="http://sso.dev.venda.com/opensso"
251+
IssueInstant="2021-02-06T20:07:01Z"
252+
ID="NETSAML2_8b051f5fadfc747def3a8972df2c4984"
253+
Version="2.0"
254+
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
255+
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
256+
<saml2:Issuer>http://localhost:3000</saml2:Issuer>
257+
<saml2p:NameIDPolicy
258+
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
259+
</saml2p:NameIDPolicy>
260+
</saml2p:AuthnRequest>
264261
```
265262

266263
At this stage it is important for you to have the Service Provider SAML2 settings at the Identity Provider set correctly to match the values sent in the **AuthnRequest**
@@ -308,9 +305,9 @@ The security of SAML2 responses depends on trust in the Identity Provider. Trus
308305
```
309306
this results in:
310307
```
311-
$VAR1 = bless( {
312-
'cacert' => 't/cacert.pem'
313-
}, 'Net::SAML2::Binding::POST' );
308+
$VAR1 = bless( {
309+
'cacert' => 't/cacert.pem'
310+
}, 'Net::SAML2::Binding::POST' );
314311
```
315312

316313
### Handle the response
@@ -327,17 +324,17 @@ The handle_response() of the Net::SAML2::Binding::POST object processes the resp
327324

328325
handle_response is pretty short but does a couple of important things:
329326

330-
1. Calls XML::Sig to verify the signatures in the $saml_response XML
327+
1. Calls Net::SAML2::XML::Sig (XML::Sig) to verify the signatures in the $saml_response XML
331328
2. Verifies that the certificate that signed the XML was signed by the $cacert
332329

333330
### Get the Assertion from the SAMLResponse XML
334331

335332
The SAMLResponse is base64 encoded XML. The Net::SAML2::Protocol::Assertion->new_from_xml processes the full XML and create the Net::SAML2::Protocol::Assertion containing the assertion.
336333

337334
```
338-
my $assertion = Net::SAML2::Protocol::Assertion->new_from_xml(
339-
xml => decode_base64($saml_response)
340-
);
335+
my $assertion = Net::SAML2::Protocol::Assertion->new_from_xml(
336+
xml => decode_base64($saml_response)
337+
);
341338
```
342339

343340
### Validating the Assertion
@@ -349,11 +346,11 @@ As it is a point in time assertion, you need to verify the validity of the NotBe
349346
For the $saml_request_id you need to retrieve it from wherever it was stored during the creation of the Net::SAML2::Protocol::AuthnRequest. Foswiki.org SamlLoginContrib for instance had stored it in the user session.
350347

351348
```
352-
my $issuer = $Foswiki::cfg{Saml}{issuer};
353-
my $saml_request_id = $this->getAndClearSessionValue('saml_request_id');
349+
my $issuer = $Foswiki::cfg{Saml}{issuer};
350+
my $saml_request_id = $this->getAndClearSessionValue('saml_request_id');
354351
355-
# $assertion->valid() checks the dates and the audience
356-
my $valid = $assertion->valid($issuer, $saml_request_id);
352+
# $assertion->valid() checks the dates and the audience
353+
my $valid = $assertion->valid($issuer, $saml_request_id);
357354
```
358355

359356
The call to $assertion->valid validates the following for the assertion:
@@ -376,24 +373,24 @@ The nameid is the Identity Providers canonical userid that can be considered to
376373
An example assertion attributes returned by GSuite could look like:
377374

378375
```
379-
$VAR1 = {
380-
'title' => [
381-
'Net::SAML2 Maintainer'
382-
],
383-
'fname' => [
384-
'Timothy'
385-
],
386-
'lname' => [
387-
'Legge'
388-
],
389-
'Email' => [
390-
391-
],
392-
'phone' => [
393-
'4328675309',
394-
'4325551212'
395-
]
396-
};
376+
$VAR1 = {
377+
'title' => [
378+
'Net::SAML2 Maintainer'
379+
],
380+
'fname' => [
381+
'Timothy'
382+
],
383+
'lname' => [
384+
'Legge'
385+
],
386+
'Email' => [
387+
388+
],
389+
'phone' => [
390+
'4328675309',
391+
'4325551212'
392+
]
393+
};
397394
```
398395
The assertion attributes are very specific to the combination of the Identity Provider and the SAML2 configuration. It can include any user specific values that can be accessed or transformed during the setup. It can also contain groups.
399396

@@ -611,7 +608,6 @@ this results in the following XML
611608
ISvnu1/xomsSS+aenG5toWmhoJIKFbfhQkpnBlgGD5+12Cxn2jHpgv15262ZZIJS
612609
WPp/0bQqdAAUzkJZPpUGUN1sTXPJexYT6na7XvLd6mvO1g+WDk6aZnW/zcT3T9tL
613610
Iavyic/p4gZtXckweq+VTn9CdZp6ZTQtVw==
614-
615611
</ds:X509Certificate>
616612
</ds:X509Data>
617613
</ds:KeyInfo>
@@ -641,4 +637,3 @@ this results in the following XML
641637
</md:EntityDescriptor>
642638
643639
```
644-

0 commit comments

Comments
 (0)