I'll explain what I needed/have implemented, and you can decide if that maps to your problem domain. We have a cloud application accessed by multiple Clients. Each Client has multiple administrators and multiple non-admin users. Client A's data/users must be fully separated from Client B's data/users (except that there are globally unique login identifiers). All this is built on standard Django password-based authentication, with a custom multi-tenancy implementation.
- In addition, individual non-admin users can use django-social-auth to login via one of several Social Networks.
- In addition, a Client's admins can configure multiple SAML IdPs for SSO. This works out of the box using django-social-auth's SAML backend.
- In addition, a Client's admins can configure multiple OIDC Identity Providers for SSO. Since the django-social-auth OIDC backend only supports one Identity Provider, I wrapped it with a layer more-or-less inspired by the SAML backend to allow for multiple Identity Providers.
I model both the SAML IdPs and OIDC Identity Providers using a single Django model. In principle, this layer is extensible to accomodate any behaviour differences between different implementations. That said, to this point, everything works with completely standard protocol handling.
Now, I'm really just a noob as far as all this is concerned, however, I added the following features which seemed essential to me:
- Social Network authentication can be disabled by a Client's admins using a hook into django-social-auth's pipeline.
- Both the SAML and OIDC SSO implementations are "sandboxed" to the given Client.The idea being that a breach of Client A's authentication setup must not be allowed to compromise Client B.
I'm sure there are clever folk out there who could prove that these extras were not needed, but hey ho.