Storing User Related SSO Data
In some SSO implementations, a unique end user identifier is created and needs to be reused in subsequent uses of the SSO. The ThirdPartyDataElements and ThirdPartyData database tables are utilized for this situation. These tables reference the end users UserID and the SSO’s VendorID to store information, and include some convenient business logic so additional database requests are not needed to fetch, set, or update the unique user values.
Creating a ThirdPartyDataElements entry
First, an element needs to be created. This can be done in the db_plan.py
file of your SSO extension. For the
incoming request to contain the data, the element names need to start with “Session.”. This is showcased in the example
db_plan file below.
from q2_sdk.core.install_steps import db_plan # from q2_sdk.core.install_steps.uux_payload import UUXPayloadScript # from q2_sdk.models.db_plan_shapes import UserPropertyFeature class DbPlan(db_plan.DbPlan): def __init__(self): """ It is often necessary to configure the database with information for an extension to run appropriately. This is your home to do so. Each of these attributes corresponds to a table (or set of tables) in the database. Instead of forcing all Antilles users to learn the database structure of Q2, we've opted for this handy abstraction. """ super().__init__() self.third_party_element_name = "Session.UserSSOIdentifier" self.ui_text_prefix = 'ExampleSSO' # Will be used for all self.ui_text_elements self.third_party_data_elements = [db_plan.ThirdPartyDataElement(self.third_party_element_name, "a unique identifier for the user")]Note
After installing the SSO in the sandbox environment, run the below q2 command to ensure that the online stack is aware of the new data element.
q2 invalidate_hq_cache -t ThirdPartyDataElements
Returning a User Config Level object
To add or update third-party data for a user, the value needs to be returned in the Q2SSOResponse
object. In
the below example, the logic will check the incoming values in the vendor_config dictionary. If the key is not present,
an UserLevelConfig
object will be created, then this is added to a UserLevelConfigList
object. The UserLevelConfigList
the object can be reused to add or update multiple pieces of data.
import uuid from q2_sdk.core.http_handlers.sso_handler import Q2SSORequestHandler, Q2SSOResponse, ResponseType from q2_sdk.hq.models.sso_response import UserLevelConfig, UserLevelConfigList from .install.db_plan import DbPlan class ExampleSSOHandler(Q2SSORequestHandler): DB_PLAN = DbPlan() def __init__(self, application, request, **kwargs): super().__init__(application, request, **kwargs) self.third_party_element_name = self.DB_PLAN.third_party_element_name async def default(self): vendor_identifier = self.vendor_configs.get(self.third_party_element_name) user_config_list = None self.logger.info(self.vendor_configs) if vendor_identifier: self.logger.info("I got an id value: %s", vendor_identifier) else: sso_id = UserLevelConfig(self.third_party_element_name, str(uuid.uuid4())) user_config_list = UserLevelConfigList(self.vendor_id, [sso_id]) response = Q2SSOResponse(ResponseType.LINK_OUT, response="http://www.q2ebanking.com", user_level_config_list=user_config_list) return response