Net-SAML2
view release on metacpan or search on metacpan
TUTORIAL.md view on Meta::CPAN
In Net::SAML2::Binding::Redirect->Verify() the IdP's signing certificate is used to verify a Redirect from the IdP.
the creation of the Net::SAML2::Binding::Redirect results in:
```
$VAR1 = bless( {
'param' => 'SAMLRequest',
'url' => bless( do{\(my $o = 'http://sso.dev.venda.com/opensso/SSORedirect/metaAlias/idp')}, 'URI::http' ),
'cert' => [
{
'signing' => '-----BEGIN CERTIFICATE-----
MIIDFTCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQUFADA3MQswCQYDVQQGEwJVUzEO
MAwGA1UECgwFbG9jYWwxCzAJBgNVBAsMAmN0MQswCQYDVQQDDAJDQTAeFw0xMDEw
MDYxMjM4MTRaFw0xMTEwMDYxMjM4MTRaMFcxCzAJBgNVBAYTAlVTMQ4wDAYDVQQK
DAVsb2NhbDELMAkGA1UECwwCY3QxDTALBgNVBAMMBHNhbWwxHDAaBgkqhkiG9w0B
CQEWDXNhbWxAY3QubG9jYWwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMhu
pJZpvu1m6ys+IrWrm3pK+onwRAYCyrgQ0RyK2cHbVLFbjBqTjKnt+PiVbnZPZUTs
tkV9oijZGQvaMy9ingJursICUQzmOfYRDm4s9gFJJOHUGYnItRhp4uj3EoWWyX8I
6Mr+g3/vNgNFvD5S9L7Hk1mSw8SnPlblZAWlFUwXAgMBAAGjgY8wgYwwDAYDVR0T
AQH/BAIwADAxBglghkgBhvhCAQ0EJBYiUnVieS9PcGVuU1NMIEdlbmVyYXRlZCBD
ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUGy/iPd7PVObrF+lK4+ZShcbStLYwCwYDVR0P
BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDANBgkqhkiG9w0B
AQUFAAOCAQEAYoYq3Rc6jC7f8DnKxDHntHxH91F5mfp8Y3j7ALcRG/mrzkMhvxU2
O2qmh4aHzZBoY1EU9VjrVgyPJPAjFQVC+OjIE46Gavh5wobzYmVGeFLOa9NhPv50
h3EOw1eCda3VwcvStWw1OhT8cpEGqgJJVAcjwcm4VBtWjodxRn3E4zBr/xxzR1HU
ISvnu1/xomsSS+aenG5toWmhoJIKFbfhQkpnBlgGD5+12Cxn2jHpgv15262ZZIJS
WPp/0bQqdAAUzkJZPpUGUN1sTXPJexYT6na7XvLd6mvO1g+WDk6aZnW/zcT3T9tL
Iavyic/p4gZtXckweq+VTn9CdZp6ZTQtVw==
-----END CERTIFICATE-----
'
}
],
'key' => 't/sign-nopw-cert.pem'
}, 'Net::SAML2::Binding::Redirect' );
```
#### key
The **key** is the absolute filename of the Service Provider's private key that should be used to sign the AuthnRequest that is being sent to the Identity Provider.
#### cert
The **cert** is the IdP signing cert as included in the Net::SAML2::IdP object. It is used for the verify of a Redirect from the IdP.
#### url
The **url** is the the Single Sign On URL that was specified in the Identity Provider's metadata.
## Sign the AuthnRequest and generate the URL
The URL is created by calling the sign function of the Net::SAML2::Binding::Redirect object with the xml version of the AuthnRequest.
```
my $url = $redirect->sign($authnreq->as_xml);
```
The signed URL is that results is:
```
$VAR1 = 'http://sso.dev.venda.com/opensso/SSORedirect/metaAlias/idp?SAMLRequest=fZFfS4RQEMXf%2BxRy39Xrv9wGFRYsWKglaumhl5j0ioLea8641Lfvagu1EPt6OHPOb2YywqEPR9jO3Oon9TErYudFTdQZnYvQk8LZlbnY3x6etw%2F34dtNXMcSqybB5Po9SYOmwUSGMTbBRkYyRWsnmtVOE6NmmyDDwJWhK9...
```
## Redirect to the user's browser to the URL
At this point the web application needs to redirect the user's browser to the URL. The Identity Provider will receive the XML at the sso_url that was defined in the metadata:
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.
```
<saml2p:AuthnRequest
Destination="http://sso.dev.venda.com/opensso"
IssueInstant="2021-02-06T20:07:01Z"
ID="NETSAML2_8b051f5fadfc747def3a8972df2c4984"
Version="2.0"
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:Issuer>http://localhost:3000</saml2:Issuer>
<saml2p:NameIDPolicy
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
</saml2p:NameIDPolicy>
</saml2p:AuthnRequest>
```
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**
**Issuer** is also known as the **Entity ID**
You should get the Identity Provider's login page at this point. If you do not, you need to review the AuthnRequest settings and the Service Providers settings to ensure that they match. It is often useful to use a separate browser to avoid automat...
## Step 2: Processing the SAMLResponse
After the successful login at the Identity provider it will perform a HTTP POST request via the user's browser to the Service Providers's ACS URL. This can be a separate URL handled by the Web Application or the same login URL that the user accessed...
### Your application specific items
There are a few things to think about for handling the response and mapping it to a user in your application:
1. Not accidentally passing through values from a previous login. If your application sets session values during the processing the response specifically clear those values before you start processing.
2. SAMLResponse shown in the URL - Do you really want the user to see this? If not delete it from the response after you have it in a variable to use.
3. Mapping your application user to the nameid returned. You may need to provide a mapper to do things like remove @cpan.org from timlegge@cpan.org for example if your application expects timlegge to be the username.
4. Following your application's logic to generate the session token that indicates that the user is logged in.
### Extract the SAMLResponse from the HTTP Response
This will be different depending on your web application and how it handles POST responses. Foswiki's SAMLLoginContrib for instance does the following:
```
my $saml_response = $query->param('SAMLResponse');
if (defined $saml_response) {
$this->samlCallback($saml_response, $query, $session);
}
```
Basically the $query in this case contains the POST to the web application and if there is a SAMLResponse parameter in the $query it passes the response to the callback function to handle the response.
### Create the POST object to process response
The security of SAML2 responses depends on trust in the Identity Provider. Trust is implemented by signed XML in the response to the request. The XML is signed by the Identity Provider with a private key that can be verified with the CACert provide...
TUTORIAL.md view on Meta::CPAN
'nameid' => 'timlegge@cpan.org',
'destination' => 'https://net-saml2.local/logout',
'issue_instant' => '2022-01-29T00:32:40Z',
'issuer' => bless( do{\(my $o = 'http://keycloak.local/')}, 'URI::http' ),
'session' => '_4f6b29af-0e3c-4970-4f40-9609-fe9843ca1dc0'
}, 'Net::SAML2::Protocol::LogoutRequest' );
```
The logout response should be sent to the IdP by the SP after the local user's session has been invalidated. The LogoutResponse is created by creating the Net::SAML2::Protocol::LogoutResponse object with the correct values. The response_to is the i...
```
my $logoutresponse = Net::SAML2::Protocol::LogoutResponse->new(
issuer => $logoutrequest->{destination},
destination => $logoutrequest->{issuer},
status => "urn:oasis:names:tc:SAML:2.0:status:Success",
response_to => $logoutrequest->{id},
);
```
Once you have created the LogoutResponse you sign the XML version of the LogoutResponse using the Net::SAML2::Binding::Redirect. This results in a URL that the SP must use in a GET request to inform the IdP that the session was properly invalidated ...
```
my $logoutrequestsigned = $redirect->sign($logoutresponse->as_xml);
```
## Step 5: Generating the Service Provider (SP) Metadata (Optional)
Some Identity Providers allow you to import a XML file that has the Service Provider settings. This allows you to ensure that the settings defined in your application are the same as those configured as the Service Provider settings in Identity Prov...
### Create the Service Provider (SP)
Typically an application will provide a method to request a copy of the SP metadata based on the configuration used in the application. This can be on the configuration page or an actual URI like:
login/saml?metadata=1
As it is an optional function and all web applications are different you need to find a place to integrate it into your application if you choose to implement.
```
my $sp = Net::SAML2::SP->new(
id => $provider_name,
url => $issuer,
cert => $sp_signing_cert,
key => $sp_signing_key,
cacert => $cacert,
org_contact => 'timlegge@cpan.org',
org_name => 'Net::SAML2',
org_url => 'https://metacpan.org/pod/Net::SAML2',
org_display_name => 'Net::SAML2',
authnreq_signed => '0', # Optional
want_assertions_signed => '0', # Optional
);
my $xml = $sp->metatdata();
return $xml;
```
this results in the following XML
```
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
entityID="http://localhost:3000">
<md:SPSSODescriptor WantAssertionsSigned="0"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"
AuthnRequestsSigned="0"
errorURL="http://localhost:3000/saml/error">
<md:KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIDFTCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQUFADA3MQswCQYDVQQGEwJVUzEO
MAwGA1UECgwFbG9jYWwxCzAJBgNVBAsMAmN0MQswCQYDVQQDDAJDQTAeFw0xMDEw
MDYxMjM4MTRaFw0xMTEwMDYxMjM4MTRaMFcxCzAJBgNVBAYTAlVTMQ4wDAYDVQQK
DAVsb2NhbDELMAkGA1UECwwCY3QxDTALBgNVBAMMBHNhbWwxHDAaBgkqhkiG9w0B
CQEWDXNhbWxAY3QubG9jYWwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMhu
pJZpvu1m6ys+IrWrm3pK+onwRAYCyrgQ0RyK2cHbVLFbjBqTjKnt+PiVbnZPZUTs
tkV9oijZGQvaMy9ingJursICUQzmOfYRDm4s9gFJJOHUGYnItRhp4uj3EoWWyX8I
6Mr+g3/vNgNFvD5S9L7Hk1mSw8SnPlblZAWlFUwXAgMBAAGjgY8wgYwwDAYDVR0T
AQH/BAIwADAxBglghkgBhvhCAQ0EJBYiUnVieS9PcGVuU1NMIEdlbmVyYXRlZCBD
ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUGy/iPd7PVObrF+lK4+ZShcbStLYwCwYDVR0P
BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDANBgkqhkiG9w0B
AQUFAAOCAQEAYoYq3Rc6jC7f8DnKxDHntHxH91F5mfp8Y3j7ALcRG/mrzkMhvxU2
O2qmh4aHzZBoY1EU9VjrVgyPJPAjFQVC+OjIE46Gavh5wobzYmVGeFLOa9NhPv50
h3EOw1eCda3VwcvStWw1OhT8cpEGqgJJVAcjwcm4VBtWjodxRn3E4zBr/xxzR1HU
ISvnu1/xomsSS+aenG5toWmhoJIKFbfhQkpnBlgGD5+12Cxn2jHpgv15262ZZIJS
WPp/0bQqdAAUzkJZPpUGUN1sTXPJexYT6na7XvLd6mvO1g+WDk6aZnW/zcT3T9tL
Iavyic/p4gZtXckweq+VTn9CdZp6ZTQtVw==
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://localhost:3000/saml/slo-soap" />
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://localhost:3000/saml/sls-redirect-response" />
<md:AssertionConsumerService isDefault="true"
Location="http://localhost:3000/saml/consumer-post"
index="1"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" />
<md:AssertionConsumerService index="2"
Location="http://localhost:3000/saml/consumer-artifact"
isDefault="false"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" />
</md:SPSSODescriptor>
<md:Organization>
<md:OrganizationName xml:lang="en">Net::SAML2</md:OrganizationName>
<md:OrganizationDisplayName xml:lang="en">Net::SAML2</md:OrganizationDisplayName>
<md:OrganizationURL xml:lang="en">https://metacpan.org/pod/Net::SAML2</md:OrganizationURL>
</md:Organization>
<md:ContactPerson contactType="other">
<md:Company>Net::SAML2</md:Company>
<md:EmailAddress>timlegge@cpan.org</md:EmailAddress>
</md:ContactPerson>
</md:EntityDescriptor>
```
( run in 0.973 second using v1.01-cache-2.11-cpan-5a3173703d6 )