
SAML
****

The SAML backend allows users to authenticate with any provider that
supports the SAML 2.0 protocol (commonly used for corporate or
academic single sign on).

The SAML backend for python-social-auth allows your web app to act as
a SAML Service Provider. You can configure one or more SAML Identity
Providers that users can use for authentication. For example, if your
users are students, you could enable Harvard and MIT as identity
providers, so that students of either of those two universities can
use their campus login to access your app.


Required Dependency
===================

You must install python-saml 2.1.3 or higher in order to use this
backend.


Required Configuration
======================

At a minimum, you must add the following to your project's settings:

* "SOCIAL_AUTH_SAML_SP_ENTITY_ID": The SAML Entity ID for your app.
  This should be a URL that includes a domain name you own. It doesn't
  matter what the URL points to. Example: "http://saml.yoursite.com"

* "SOCIAL_AUTH_SAML_SP_PUBLIC_CERT": The X.509 certificate string
  for the key pair that your app will use. You can generate a new
  self- signed key pair with:

     openssl req -new -x509 -days 3652 -nodes -out saml.crt -keyout saml.key

  The contents of "saml.crt" should then be used as the value of this
  setting (you can omit the first and last lines, which aren't
  required).

* "SOCIAL_AUTH_SAML_SP_PRIVATE_KEY": The private key to be used by
  your app. If you used the example openssl command given above, set
  this to the contents of "saml.key" (again, you can omit the first
  and last lines).

* "SOCIAL_AUTH_SAML_ORG_INFO": A dictionary that contains
  information about your app. You must specify values for English at a
  minimum. Each language's entry should specify a "name" (not shown to
  the user), a "displayname" (shown to the user), and a URL. See the
  following example:

     {
         "en-US": {
             "name": "example",
             "displayname": "Example Inc.",
             "url": "http://example.com",
         }
     }

* "SOCIAL_AUTH_SAML_TECHNICAL_CONTACT": A dictionary with two
  values, "givenName" and "emailAddress", describing the name and
  email of a technical contact responsible for your app. Example:

     {"givenName": "Tech Gal", "emailAddress": "technical@example.com"}

* "SOCIAL_AUTH_SAML_TECHNICAL_CONTACT": A dictionary with two
  values, "givenName" and "emailAddress", describing the name and
  email of a support contact for your app. Example:

     SOCIAL_AUTH_SAML_SUPPORT_CONTACT = {
         "givenName": "Support Guy",
         "emailAddress": "support@example.com",
     }

* "SOCIAL_AUTH_SAML_ENABLED_IDPS": The most important setting. List
  the Entity ID, SSO URL, and x.509 public key certificate for each
  provider that your app wants to support. The SSO URL must support
  the "HTTP-Redirect" binding. You can get these values from the
  provider's XML metadata. Here's an example, for TestShib (the values
  come from TestShib's metadata):

     {
         "testshib": {
             "entity_id": "https://idp.testshib.org/idp/shibboleth",
             "url": "https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO",
             "x509cert": "MIIEDjCCAvagAwIBAgIBADA ... 8Bbnl+ev0peYzxFyF5sQA==",
         }
     }


Basic Usage
===========

* Set all of the required configuration variables described above.

* Generate the SAML XML metadata for your app. The best way to do
  this is to create a new view/page/URL in your app that will call the
  backend's "generate_metadata_xml()" method. Here's an example of how
  to do this in Django:

     def saml_metadata_view(request):
         complete_url = reverse('social:complete', args=("saml", ))
         saml_backend = load_backend(
             load_strategy(request),
             "saml",
             redirect_uri=complete_url,
         )
         metadata, errors = saml_backend.generate_metadata_xml()
         if not errors:
             return HttpResponse(content=metadata, content_type='text/xml')

* Download the metadata for your app that was generated by the above
  method, and send it to each Identity Provider (IdP) that you wish to
  use. Each IdP must install and configure your metadata on their
  system before it will work.

* Now everything is set! To allow users to login with any given IdP,
  you need to give them a link to the python-social-auth
  "begin"/"auth" URL and include an "idp" query parameter that
  specifies the name of the IdP to use. This is needed since the
  backend supports multiple IdPs. The names of the IdPs are the keys
  used in the "SOCIAL_AUTH_SAML_ENABLED_IDPS" setting.

  Django example:

     # In view:
     context['testshib_url'] = u"{base}?{params}".format(
         base=reverse('social:begin', kwargs={'backend': 'saml'}),
         params=urllib.urlencode({'next': '/home', 'idp': 'testshib'})
     )
     # In template:
     <a href="{{ testshib_url }}">TestShib Login</a>
     # Result:
     <a href="/login/saml/?next=%2Fhome&amp;idp=testshib">TestShib Login</a>

* Testing with the TestShib provider is recommended, as it is known
  to work well.


Advanced Settings
=================

* "SOCIAL_AUTH_SAML_SP_EXTRA": This can be set to a dict, and any
  key/value pairs specified here will be passed to the underlying
  "python-saml" library configuration's "sp" setting. Refer to the
  "python-saml" documentation for details.

* "SOCIAL_AUTH_SAML_SECURITY_CONFIG": This can be set to a dict, and
  any key/value pairs specified here will be passed to the underlying
  "python-saml" library configuration's "security" setting. Two useful
  keys that you can set are "metadataCacheDuration" and
  "metadataValidUntil", which control the expiry time of your XML
  metadata. By default, a cache duration of 10 days will be used,
  which means that IdPs are allowed to cache your metadata for up to
  10 days, but no longer. "metadataCacheDuration" must be specified as
  an ISO 8601 duration string (e.g. *P1D* for one day).


Advanced Usage
==============

You can subclass the "SAMLAuth" backend to provide custom
functionality. In particular, there are two methods that are designed
for subclasses to override:

* "get_idp(self, idp_name)": Given the name of an IdP, return an
  instance of "SAMLIdentityProvider" with the details of the IdP.
  Override this method if you wish to use some other method for
  configuring the available identity providers, such as fetching them
  at runtime from another server, or using a list of providers from a
  Shibboleth federation.

* "_check_entitlements(self, idp, attributes)": This method gets
  called during the login process and is where you can decide to
  accept or reject a user based on the user's SAML attributes. For
  example, you can restrict access to your application to only accept
  users who belong to a certain department. After inspecting the
  passed attributes parameter, do nothing to allow the user to login,
  or raise "social.exceptions.AuthForbidden" to reject the user.
