pennersr / django-allauth

Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication.

Home Page:https://allauth.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

how to add support for SAML federations

MichaelMenge opened this issue · comments

I want to allow authentication by all IDPs in a saml federation (e.g. DFN-AAI or eduGAIN).

I am willing to try to implement this feature myself, but I am not a programmer but a system administrator.
Therefore i would like to get feedback on how to best implement the support for SAML federations.

At the moment a manual configuration for each idp in the federation is possible, but:

  • configuring hundreds of idps and keeping them up to date is error prone.
  • the "sp" and "advanced" configuration would be duplicated for each "idp"
  • the sp-metadata for each idp would differ because of the client_id/organization slug in the sls and acs URLs.
    But some federations distributed the metadata via an aggregate file, and therefore the sp metadata must be identical
    for all idps
  • The List of hundreds of idps would clutter the "accounts/login" page

My goals are:

  • configure all IDPs with one aggregate metadata file
  • use "exclude_entity_ids" and "overwrite_mapping" to exclude or change mapping for some idps
  • create a Discovery Service (DS) / "Where are you from" Site or allow a redirect to a DS/WAYF URL
    DFN-eduGAIN-WAYF
    to help the user find the correct IDP
  • the "provider_id" should be set to the entity_id of the selected idp

Below is a skeleton example configuration

SOCIALACCOUNT_PROVIDERS = {
  "saml": {
    ...
    "APPS": [
      {
        "name": "eduGAIN"
        "client_id": "edugain"
        "settings": {
           # Default mapping
           "attribute_mapping": {
              "uid": "http://schemas.auth0.com/clientID",
              "email_verified": "http://schemas.auth0.com/email_verified",
              "email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
           },
        "federation": {
           # metadata aggregate
           "metadata_url":   "https://mds.edugain.org/edugain-v2.xml",
           # List of idp entity_ids to exclude               
           "exclude_entity_ids": [],
           # Array of entity_ids and new attribute_mapping to overwrite the default mapping
           "overwrite_mapping": [].
           "ds_url": "https://wayf.aai.dfn.de/DFN-AAI-eduGAIN/wayf/www/WAYF.php",
        },
       "sp": {
         ...
       },
      "advanced": {
        ...
      },
     }
    ]
  }
}        

I think it would make most sense to override the list_apps() adapter method:

https://docs.allauth.org/en/latest/socialaccount/adapter.html#allauth.socialaccount.adapter.DefaultSocialAccountAdapter.list_apps

By default, it reads SocialApp records from the database, as well as apps configured in settings. But, there is nothing stopping you from doing:

def list_apps(self, request, provider=None, client_id=None):
  apps = super().list_apps(request, provider=provider, client_id=client_id)
  for some_config in some_source:
    app = SocialApp(provider="saml", provider_id=...)  # convert some_config
    if client_id  and client_id != app.client_id:
      continue
    if provider and app.provider_id != provider and app.provider != provider:
      continue
    apps.append(app)
  return apps

As for this:

The List of hundreds of idps would clutter the "accounts/login" page

Isn't that just a matter of altering the login template? Though, we could streamline that with supporting app.settings['visible'] = False.

Would this approach address your needs?

@pennersr Thank you for your input. I had not considered the option to override the default adapter.

While i still think that the support for saml federations in gjango-allauth might be useful in the long run,
I agree that overriding list_apps and changing the login template is the faster and direct approach.

Ok, let's try it this way first.