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:
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.