Package: launchkey
Python SDK for TruValidate Multifactor Authentication APIFor use in implementing TruValidate Multifactor Authentication.DescriptionUse to more easily interact with TransUnion’s TruValidate Multifactor Authentication API.A more in-depth look at this SDK can be found at the officialdocs.ExamplesCLI ExampleGo to the CLI codeFlask Webhooks ExampleGo to the Example App codeInstallation$easy_installlaunchkeyor$pipinstalllaunchkeyUsageUsing TruValidate Multifactor Authentication ClientsThe TruValidate Multifactor Authentication SDK is broken into credential based factories with access to
functionality based clients.FactoriesFactories are based on the credentials supplied. The Organization Factory uses
Organization credentials, the Directory Factory uses Directory credentials,
and the Service Factory uses Service credentials. Each factory provides clients
which are accessible to the factory. The availability is based on the hierarchy
of the entities themselves. Below is a matrix of available services for each
factory.FactoryOrganization ClientDirectory ClientService ClientOrganizationYesYesYesDirectoryNoYesYesServiceNoNoYesUtilizing Single Purpose KeysIn the case that separate encryption and signature keys are being used. The
initial key given to a factory will be used to sign requests, and any
additional keys can be added after instantiation.fromlaunchkey.factoriesimportOrganizationFactoryorganization_id="37d98bb9-ac71-44b7-9ac0-5d75e31e627a"organization_signature_private_key=open("organization_signature_private_key.key").read()organization_encryption_private_key=open("organization_encryption_private_key.key").read()organization_factory=OrganizationFactory(organization_id,organization_signature_private_key)organization_factory.add_encryption_private_key(organization_encryption_private_key)fromlaunchkey.factoriesimportDirectoryFactorydirectory_id="37d98bb9-ac71-44b7-9ac0-5d75e31e627a"directory_signature_private_key=open("directory_signature_private_key.key").read()directory_encryption_private_key=open("directory_encryption_private_key.key").read()directory_factory=DirectoryFactory(directory_id,directory_signature_private_key)directory_factory.add_encryption_private_key(directory_encryption_private_key)fromlaunchkey.factoriesimportServiceFactoryservice_id="37d98bb9-ac71-44b7-9ac0-5d75e31e627a"service_signature_private_key=open("service_signature_private_key.key").read()service_encryption_private_key=open("service_encryption_private_key.key").read()service_factory=ServiceFactory(organization_id,service_signature_private_key)service_factory.add_encryption_private_key(service_encryption_private_key)Using individual clientsfromlaunchkey.factoriesimportServiceFactory,DirectoryFactorydirectory_id="37d98bb9-ac71-44b7-9ac0-5d75e31e627a"directory_private_key=open('directory_private_key.key').read()service_id="9ecc57e0-fb0f-4971-ba12-399b630158b0"service_private_key=open('service_private_key.key').read()directory_factory=DirectoryFactory(directory_id,directory_private_key)directory_client=directory_factory.make_directory_client()service_factory=ServiceFactory(service_id,service_private_key)service_client=service_factory.make_service_client()Using a hierarchical clientfromlaunchkey.factoriesimportOrganizationFactoryorganization_id="bff1602d-a7b3-4dbe-875e-218c197e9ea6"organization_private_key=open('organization_private_key.key').read()directory_id="37d98bb9-ac71-44b7-9ac0-5d75e31e627a"service_id="9ecc57e0-fb0f-4971-ba12-399b630158b0"user="my_unique_internal_identifier"organization_factory=OrganizationFactory(organization_id,organization_private_key)directory_client=organization_factory.make_directory_client(directory_id)service_client=organization_factory.make_service_client(service_id)Linking And Managing UsersIn order to link a user you will need to start the linking process then display
the qrcode to them, give them the code, or both.link_data=directory_client.link_device(user)linking_code=link_data.codeqr_url=link_data.qrcodeIf desired you can retrieve the user’s devices and unlink then directly from
the SDKdevices=directory_client.get_linked_devices(user)directory_client.unlink_device(user,devices[0].id)You can also end all of a user’s sessionsdirectory_client.end_all_service_sessions(user)Logging A User InCreate an auth request to initiate the login processauth=service_client.authorization_request(user)auth_request_id=auth.auth_requestUsing Dynamic Policiesfromlaunchkey.entities.serviceimportAuthPolicy# Require 2 factors and don't allow any jailbroken or rooted devicespolicy=AuthPolicy(any=2,jailbreak_protection=True)# Also make it so the user can only log in from the Portland areapolicy.add_geofence(latitude=45.48805749706375,longitude=-122.70492553710936,radius=27500)auth_request_id=service_client.authorization_request(user,policy=policy)Check whether a response has been received and check whether it has been
authorizedfromlaunchkey.exceptionsimportRequestTimedOutfromtimeimportsleepresponse=Nonetry:whileresponseisNone:response=service_client.get_authorization_response(auth_request_id)ifresponseisnotNone:ifresponse.authorizedisTrue:# User accepted the auth, now create a sessionservice_client.session_start(user,auth_request_id)else:# User denied the auth requestelse:sleep(1)exceptRequestTimedOut:# The user did not respond to the request in the timeout period (5 minutes)When a user logs outservice_client.session_end(user)TOTPA user can have TOTP configured via thegenerate_user_totpmethod on theDirectoryClient.identifier="my-permanent-unique-user-identifier"configuration=directory_client.generate_user_totp(identifier)print("    Secret:    "+configuration.secret)print("    Algorithm: "+configuration.algorithm)print("    Period:    "+configuration.period)print("    Digits:    "+configuration.digits)TOTP configurations can be removed via thegenerate_user_totpmethod on theDirectoryClient.identifier="my-permanent-unique-user-identifier"directory_client.remove_user_totp(identifier)Finally codes can be validated via theverify_totpmethod on theServiceClient.identifier="my-permanent-unique-user-identifier"otp="569874"valid=service_client.verify_totp(identifier,otp)ifvalid:# Handle success scenarioelse:# Handle failure scenarioDealing with WebhooksWebhooks can be used in opposition to polling. This means we will hit your app
on either an auth response or logout request.You will use the same handle_webhook method for both login and logout.Note that request.headers must be a dictionary like object.fromflaskimportFlask,requestfromlaunchkey.entities.serviceimportAuthorizationResponse,\SessionEndRequestapp=Flask(__name__)# Path defined in your Service Callback URL value@app.route('/launchkey',methods=['POST'])deflaunchkey_webhook():package=service_client.handle_webhook(request.data,request.headers,request.method,request.path)ifisinstance(package,AuthorizationResponse):ifpackage.authorizedisTrue:# User accepted the auth, now create a sessionservice_client.session_start(user,auth_request_id)else:# User denied the authhandle_denial()elifisinstance(package,SessionEndRequest):# The package will have the user hash, so use it to log the user out# based on however you are handling itlogout_user_from_my_app(package.service_user_hash)Running TestsRunning tests is as simple as:python setup.py testValidating CodeThe TruValidate Multifactor Authentication Service SDK supports and number of python versions and has
fairly strict coding guidelines.
Tests require a number of Python versions. The best way to manage these
versions is withpyenv. You will need to register all of the versions with
pyenv. There are a couple ways to do that. An example of doing it globally is:pyenv local 3.6.13 3.7.10 3.8.9 3.9.4 pypy3.7-7.3.3Install dependencies via Pipenvpipenv install –devRun validation:pipenv run toxContributingFork itCreate your feature branch (git checkout -b my-new-feature)Conform to the following standards:PEP-8Relative imports for same level or submodulesVerify your code passes unit tests (python setup.py test)Verify your code passes tests, linting, and PEP-8 on all supported pythonversions (tox)Commit your changes (git commit -am ‘Add some feature’)Push to the branch (git push origin my-new-feature)Create new Pull RequestCHANGELOG for LaunchKey Python SDK4.0.1Updated dependencies and fixed security issue for PyLint in dev dependencies4.0.0Removed Python 2 supportRemoved Python 3.6 supportUpdated JOSE Transport to include the SDK type, SDK version, and OS version in the User Agent3.9.1Bumped urllib3 due to a security vulnerability3.9.0Updated CLI to support separate encryption and signature keysAltered JOSE transport to ensure only the designated signing key is used for signing requestsAdded theadd_encryption_private_keymethod to all factories and deprecatedadd_additional_private_keyAddedKeyTypeEnumAdded additionalkey_typeparameter toadd_service_public_keyAdded additionalkey_typeparameter toadd_directory_public_key3.8.1Fixed an issue where the SDK would improperly report which key was used when the encryption and signature keys differedFixed an issue where the SDK would fail to validate webhook signature verification if the signature key was not the one returned in the public-key endpoint3.8.0Added TOTP generate_user_totp and remove_user_totp to Directory Client and verify_totp to Service Client3.7.0Add device ID list toAuthorizationRequestobjectUpdate CLI to display device ID list upon authorization request3.6.0Bug fix to ensure that requests do not follow redirectsBug fix to ensure that public key is cached usingkidheader of JWT found within a response headerAdded Policies: ConditionalGeofence, MethodAmount, Factors, LegacyAdded Requirement enumenum34 only required on python versions < 3.4Deprecated: TimeFenceDeprecated:ServiceSecurityPolicyDeprecated:get_service_policymethod onServiceManagingBaseClientclassDeprecated:set_service_policymethod onServiceManagingBaseClientclassDeprecated:get_authorization_responsemethod onServiceClientclassDeprecated:handle_webhookmethod onServiceClientclassAdded:get_advanced_service_policymethod onServiceManagingBaseClientclassAdded:set_advanced_service_policymethod onServiceManagingBaseClientclassAdded:get_advanced_authorization_responsemethod onServiceClientclassAdded:handle_advanced_webhookmethod onServiceClientclassAdded:AdvancedAuthorizationResponseclassAdded:AuthorizationResponsePolicyclass3.5.0Added get_all_directory_sdk_keys method to Organization clientAdded integration testing suiteAdded device failure sensor typeAdded auth_methods and auth_policy attributes to the AuthorizationResponse objectAdded handle_webhook as well as DeviceLinkCompletionResponse into the DirectoryClientUpdated the OrganizationClient update_directory() method and Directory object to include a webhook_url kwarg / attributeAdded Webhook example app3.4.0Added example CLI to codebaseAdded ttl parameter to the DirectoryClient link_device methodAdded cancel_authorization_request method to the ServiceClientFixed bug in ServiceClient which prevented handling of session end webhook request data when presented as a bytearray3.3.1Updated HTTP transport to no longer use sessions due to a bug that was causing BadStatusLine exceptions on long lived connections.3.3.0Added tooling around code quality and ensured that CI build would fail without meeting expectations.Added dynamic auth TTL and title functionalityAdded dynamic auth push message body and title functionalityAdded auth busy signal error handlingAdded new auth response formatAdded auth denial context functionality3.2.0Remove PyCrypto and replace with pycryptodomex that is already required by PyJWKESTFixed geofence missing name bugAdded more expected error conditions to pydocsRemoved version lock for pytz requirementAdded 3rd party push enhancementsAdded tox config for local testing in multiple versions of PythonAdded missing response validationAdded full webhook validationCleaned up error handling and raising for webhooksSwitch RequestsTransport to use session in order to provide connection sharing between requests3.1.1Added patch method for transportsSupport for many new endpoints added involving Organization, Directory, and Service managementMoved all entity objects into their own submoduleAdded UUID validation for factory entity IDs3.0.2Improved 401 error handlingBug fix for SessionEndRequest objectService PINs bug fix3.0.1Typo and manifest fixesAdded Unauthorized status code error handlerNose version lock for test requirements3.0.0Complete revamp for new V3 LaunchKey API2.0.1Make tests run under Python 3.5+Make PEP-8 compliant (deprecated some non-PEP-8 compliant functions)1.3.0Python 3 compatibility.Ability to send policies in auth request.1.2.7Update manifest for new CHANGES file1.2.6Fix for bad build regarding CHANGES.md1.2.5Remove references to LK Identifier as the API no longer returns it.