-
Notifications
You must be signed in to change notification settings - Fork 49
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
Multi-tenant configuration while using JIT provisioning #215
Comments
Hey @jeremylivingston, As I also mentioned in this #56 (comment), the hook you mentioned is not created for this purpose. The hook is created to help with selecting an specific metadata URL for the user based on their organization (or team, in your case), rather than trying to return all the metadata URLs at once (which is possible BTW and the signature will be checked against all the certificates passed, and you can do it by using What you can do is this:
I created an entire mapping structure for teams, projects, users and orgs to handle the mapping, but there are other ways. |
@mostafa Thank you for the quick reply! Much appreciated. Just to make sure I'm understanding, it sounds like you're suggesting that I use the This makes sense, but does that imply that there's no way to filter down the metadata configuration file to be used in a scenario where the user does not yet exist? Ideally, I'd like to have a single config that I am using for authentication requests to mitigate the performance issues that you mentioned. If the user does not yet exist, it seems that there may not be a way to filter down the list of metadata config files. Is that correct? |
@jeremylivingston Glad I could help. Use |
@mostafa yes, I understand that part. My issue is that in an IDP-initiated flow, these triggers happen after the metadata configuration is retrieved. So since the user has not yet been created, there's no way for me to filter down the metadata configs to the correct one for the organization. Is there a way to accomplish this? |
@jeremylivingston |
@mostafa Thanks for writing that up! So in my case where there is no user_id yet (IDP-initiated flow where the user isn't yet created), are you saying that I should return something other than the user_id from the In my case, I should be able to read the Entity ID from the |
Here is some example code that illustrates the issue: # Configured for `TRIGGER.GET_USER_ID_FROM_SAML_RESPONSE`
def get_user_id_from_saml_response(saml_response: str, user_id: Optional[str]) -> Optional[str]:
# At this point we are in an IDP-initiated flow for a new user. There is no way to retrieve the user
# since they don't exist in our system. We *could* retrieve the organization by its entity ID in the
# SAML response, but that seems to go against the spirit of this trigger.
try:
email = None
root = ElementTree.fromstring(saml_response)
# Get the email address from the provided SAML response
for tag in root.iter(tag='{urn:oasis:names:tc:SAML:2.0:assertion}Attribute'):
if 'email' in tag.attrib['Name']:
for attribute_value in tag.iter(tag='{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue'):
email = attribute_value.text
break
# We didn't find an email address in the SAML response
if not email:
return None
return User.objects.get(email=email).id
except ObjectDoesNotExist:
# We don't have this user in our system
return None
# Configured for `TRIGGER.GET_METADATA_AUTO_CONF_URLS`
def get_saml_url_by_user_id(user_id: Optional[str] = None):
# Since we are only able to provide a user ID to this function, we only have one way to look up a
# metadata config URL. If we had the ability to pass different fields into this trigger (or even the
# SAML response), we could look up the configuration by other elements like the entity ID or
# organization ID
try:
# We don't have a user_id since the user is not created, so we have no way to narrow down the config
if not user_id:
raise Exception("No user provided, so we are unable to retrieve the metadata config URL")
# Get the SAML config by the user_id
saml_config = SamlConfig.objects.get(user_id=user_id)
return [{"url": saml_config.url, "should_sign_response": True}]
except ObjectDoesNotExist as exc:
raise Exception("No SAML config found for the provided user_id.") As you can see, if we had access to the full SAML response in the |
I see where the confusion is. In this context, the user ID (the user identifier) doesn't mean the |
@mostafa Ah, that's helpful. Thanks! Unfortunately, this still doesn't fully solve the problem for me. In my case, I'm not able to narrow down an organization/team based on a user's email domain. We often have multiple teams with the same company or email domain that have different tenants and SAML configurations. I think that my best path forward would be to return the entity ID from the get_user_id_from_saml_response function and then use that to look up the associated team in my system. I don't see another way to accomplish what I'm trying to do (unless you have other ideas!). Thanks again for all of your help. |
@jeremylivingston |
@mostafa Yes, unfortunately the multiple teams in our setup have no semblance of a shared organization configuration. If one part of the organization has an account (with SSO) and the other one does too, they never communicate or manage each other's users. For this reason, I think we need to stick with using the entity ID to determine which organization's config to use. |
Fair enough! I suppose this is resolved. Feel free to re-open it if you have further questions related to this issue. |
Thank you, @mostafa! |
I am currently running into limitations with the existing triggers in a scenario where a new user attempts to authentication via an IDP-initiated flow with multiple tenants/IDPs on the backend.
Details of my scenario:
GET_USER_ID_FROM_SAML_RESPONSE
cannot find a user since they do not exist.GET_METADATA_AUTO_CONF_URLS
to pull the organization's specific metadata file.One option would be to return a different ID (the team ID instead of the user ID) from the
GET_USER_ID_FROM_SAML_RESPONSE
call, then use that downstream, but it seems like this could have unintended side effects.Is there a recommended approach for how to handle this situation? Should we consider adding another trigger type or even passing the SAML response into
GET_METADATA_AUTO_CONF_URLS
so it can pull the proper configuration file?The text was updated successfully, but these errors were encountered: