Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question : Multiple tenant SP has to offer ACS dynamically #364

Open
Malshtur opened this issue Mar 2, 2023 · 5 comments
Open

Question : Multiple tenant SP has to offer ACS dynamically #364

Malshtur opened this issue Mar 2, 2023 · 5 comments
Labels
Documentation Issues that document features and specific configuration/use cases

Comments

@Malshtur
Copy link

Malshtur commented Mar 2, 2023

Hello,

I am working to port SAML to a multi tenant application where each tenant has its own database. So every tenant manage its own users, objects, etc.

The issue I am trying to resolve has to do with our authentication scheme requiring to specify what tenant the user authenticates to. I have considered the three following approaches :

  • Use RelayState : I would rather have all the informations packed in the AuthnRequest and Response. Security can be an issue and it feels somehow not natural.
  • Use different AssertionConsumerService : At metadata level it is an issue. The application could create a new tenant leading to obsolete metadata not referencing the new ACS conresponding to the new tenant. Each tenant creation leads to metadata changes. Not acceptable in my case.
  • Use different AssertionConsumerServiceUrl : in AuthnRequest with mandatory signature and checking that urls are pertinent offers me the flexibility I hope to have. It would lead to the least amount of modification in configuration. No metadata modification

The latter is my preffered way to go but I can't wrap my finger around if it is possible with djangosaml2. Could you point me in the right direction if you support it ? If it is not the case I am only trying to find how to do it at pysaml2 level but I have no luck so far.

Thanks for your time.

@peppelinux
Copy link
Member

Yes, option 3 is very good

you just have to inherit https://github.com/IdentityPython/djangosaml2/blob/master/djangosaml2/views.py#L408 and then you can do overload of the method post_login, custom_redirect or whatever

then you have to map your new ACS to a specific urls (urls.py of your project) and also map it in the metadata, defining its url/webpath in the pysaml2 configuration, here (to get signed metadata automatically):

https://github.com/IdentityPython/djangosaml2/blob/master/docs/source/contents/setup.rst#pysaml2-specific-files-and-configuration

@peppelinux peppelinux added the Documentation Issues that document features and specific configuration/use cases label Mar 2, 2023
@Malshtur
Copy link
Author

Malshtur commented Mar 2, 2023

Thanks for your reactivity and the details, truly fast !

Just to be sure we are talking about the same thing, in saml-core :
AssertionConsumerServiceURL [Optional] Specifies by value the location to which the <Response> message MUST be returned to the requester. The responder MUST ensure by some means that the value specified is in fact associated with the requester. [SAMLMeta] provides one possible mechanism; signing the enclosing <AuthnRequest> message is another. This attribute is mutually exclusive with the AssertionConsumerServiceIndex attribute and is typically accompanied by the ProtocolBinding attribute.

From your response, I guess that it would lead to metadata modification on SP side and to update them on the IDP too. This is problematic in many deployment. So that is why I wanted to use the second option : signing the enclosing AuthnRequest and have the AssertionConsumerServiceUrl dynamically set in the request without changing the metadata.

I hope that I am a bit clearer and please forgive me if I did not understand you the first time.

EDIT: Did you mention the hook or overload to do something like selecting the tenant right after reponse is received in order to pass it to the application level ?

EDIT 2 : For clarity, what I was thinking is having a new AssertionConsumerService without altering the in metadata as offers the AssertionConsumerServiceUrl field in AuthnRequest.

@peppelinux
Copy link
Member

for the security of the solution the IDP should only response to a known ACS, taken from the metadata of the requester

@Malshtur
Copy link
Author

Malshtur commented Mar 3, 2023

In general, i completly agree but if and only if the AuthnRequest is signed then the underlying security is the same because it is based on the same cryptographic keys.

The only case i could think of is that the underlying SP is vulnerable to injections that could lead to sign an AuthnRequest with a malicious AssertionConsumerServiceUrl. This could also modify metadata nonetheless.

The standard allows both as I mentionned above, but if I were to use djangosaml2 as you explained I have to share metadata dynamically between SP and IDP to refresh the list of AssertionConsumerService, right ?

@peppelinux
Copy link
Member

right

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation Issues that document features and specific configuration/use cases
Projects
None yet
Development

No branches or pull requests

2 participants