{ "info": { "author": "iovation", "author_email": "", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: System :: Systems Administration :: Authentication/Directory" ], "description": "Python SDK for LaunchKey API\n============================\n\n.. image:: https://travis-ci.org/iovation/launchkey-python.svg?branch=master\n :target: https://travis-ci.org/iovation/launchkey-python\n\n.. _LaunchKey: https://launchkey.com\n\n.. _docs: https://docs.launchkey.com\n\n.. _pyenv: https://github.com/pyenv/pyenv\n\nFor use in implementing LaunchKey_.\n\n\nDescription\n-----------\n\nUse to more easily interact with iovation's LaunchKey API.\n\nA more in-depth look at this SDK can be found at the official docs_.\n\nExamples\n--------\n\nCLI Example\n***********\n\n`Go to the CLI code `_\n\nFlask Webhooks Example\n**********************\n\n`Go to the Example App code `_\n\nInstallation\n------------\n\n\n.. code-block:: bash\n\n $ easy_install launchkey\n\nor\n\n.. code-block:: bash\n\n $ pip install launchkey\n\nUsage\n-----\n\nUsing LaunchKey Clients\n***********************\n\nThe LaunchKey SDK is broken into credential based factories with access to\nfunctionality based clients.\n\n**Factories**\n\nFactories are based on the credentials supplied. The Organization Factory uses\nOrganization credentials, the Directory Factory uses Directory credentials,\nand the Service Factory uses Service credentials. Each factory provides clients\nwhich are accessible to the factory. The availability is based on the hierarchy\nof the entities themselves. Below is a matrix of available services for each\nfactory.\n\n+--------------+---------------------+------------------+----------------+\n| Factory | Organization Client | Directory Client | Service Client |\n+==============+=====================+==================+================+\n| Organization | Yes | Yes | Yes |\n+--------------+---------------------+------------------+----------------+\n| Directory | No | Yes | Yes |\n+--------------+---------------------+------------------+----------------+\n| Service | No | No | Yes |\n+--------------+---------------------+------------------+----------------+\n\n**Using individual clients**\n\n.. code-block:: python\n\n from launchkey.factories import ServiceFactory, DirectoryFactory\n\n directory_id = \"37d98bb9-ac71-44b7-9ac0-5d75e31e627a\"\n directory_private_key = open('directory_private_key.key').read()\n service_id = \"9ecc57e0-fb0f-4971-ba12-399b630158b0\"\n service_private_key = open('service_private_key.key').read()\n\n directory_factory = DirectoryFactory(directory_id, directory_private_key)\n directory_client = directory_factory.make_directory_client()\n\n service_factory = ServiceFactory(service_id, service_private_key)\n service_client = service_factory.make_service_client()\n\n**Using a hierarchical client**\n\n.. code-block:: python\n\n from launchkey.factories import OrganizationFactory\n\n organization_id = \"bff1602d-a7b3-4dbe-875e-218c197e9ea6\"\n organization_private_key = open('organization_private_key.key').read()\n directory_id = \"37d98bb9-ac71-44b7-9ac0-5d75e31e627a\"\n service_id = \"9ecc57e0-fb0f-4971-ba12-399b630158b0\"\n user = \"my_unique_internal_identifier\"\n\n organization_factory = OrganizationFactory(\n organization_id, organization_private_key)\n directory_client = organization_factory.make_directory_client(directory_id)\n service_client = organization_factory.make_service_client(service_id)\n\nLinking And Managing Users\n**************************\n\nIn order to link a user you will need to start the linking process then display\nthe qrcode to them, give them the code, or both.\n\n.. code-block:: python\n\n link_data = directory_client.link_device(user)\n linking_code = link_data.code\n qr_url = link_data.qrcode\n\nIf desired you can retrieve the user's devices and unlink then directly from\nthe SDK\n\n.. code-block:: python\n\n devices = directory_client.get_linked_devices(user)\n directory_client.unlink_device(user, devices[0].id)\n\nYou can also end all of a user's sessions\n\n.. code-block:: python\n\n directory_client.end_all_service_sessions(user)\n\nLogging A User In\n*****************\n\nCreate an auth request to initiate the login process\n\n.. code-block:: python\n\n auth = service_client.authorization_request(user)\n auth_request_id = auth.auth_request\n\nUsing Dynamic Policies\n\n.. code-block:: python\n\n from launchkey.entities.service import AuthPolicy\n # Require 2 factors and don't allow any jailbroken or rooted devices\n policy = AuthPolicy(any=2, jailbreak_protection=True)\n # Also make it so the user can only log in from the Portland area\n policy.add_geofence(\n latitude=45.48805749706375, longitude=-122.70492553710936, radius=27500)\n auth_request_id = service_client.authorization_request(user, policy=policy)\n\n\nCheck whether a response has been received and check whether it has been\nauthorized\n\n.. code-block:: python\n\n from launchkey.exceptions import RequestTimedOut\n from time import sleep\n response = None\n try:\n while response is None:\n response = service_client.get_authorization_response(auth_request_id)\n if response is not None:\n if response.authorized is True:\n # User accepted the auth, now create a session\n service_client.session_start(user, auth_request_id)\n else:\n # User denied the auth request\n else:\n sleep(1)\n except RequestTimedOut:\n # The user did not respond to the request in the timeout period (5 minutes)\n\nWhen a user logs out\n\n.. code-block:: python\n\n service_client.session_end(user)\n\nDealing with Webhooks\n*********************\n\nWebhooks can be used in opposition to polling. This means we will hit your app\non either an auth response or logout request.\n\nYou will use the same handle_webhook method for both login and logout.\n\n**Note that request.headers must be a dictionary like object.**\n\n.. code-block:: python\n\n from flask import Flask, request\n from launchkey.entities.service import AuthorizationResponse, \\\n SessionEndRequest\n\n app = Flask(__name__)\n\n # Path defined in your Service Callback URL value\n @app.route('/launchkey', methods = ['POST'])\n def launchkey_webhook():\n package = service_client.handle_webhook(request.data, request.headers,\n request.method, request.path)\n if isinstance(package, AuthorizationResponse):\n if package.authorized is True:\n # User accepted the auth, now create a session\n service_client.session_start(user, auth_request_id)\n else:\n # User denied the auth\n handle_denial()\n elif isinstance(package, SessionEndRequest):\n # The package will have the user hash, so use it to log the user out\n # based on however you are handling it\n logout_user_from_my_app(package.service_user_hash)\n\nRunning Tests\n-------------\n\nRunning tests is as simple as::\n\n python setup.py test\n\n\nValidating Code\n---------------\n\nThe LaunchKey Service SDK supports and number of python versions and has\nfairly strict coding guidelines.\nTests require a number of Python versions. The best way to manage these\nversions is with pyenv_. You will need to register all of the versions with\npyenv. There are a couple ways to do that. An example of doing it globally is::\n\n pyenv global 2.7.15 3.4.9 3.5.6 3.6.6 3.7.0 3.8-dev pypy3.5-6.0.0 pypy2.7-6.0.0\n\nInstall dependencies via Pipenv\n\n pipenv install --dev\n\nRun validation::\n\n pipenv run tox\n\nContributing\n------------\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Verify your code passes unit tests (`python setup.py test`)\n4. Verify your code passes tests, linting, and PEP-8 on all supported python\n versions (`tox`)\n5. Commit your changes (`git commit -am 'Add some feature'`)\n6. Push to the branch (`git push origin my-new-feature`)\n7. Create new Pull Request\n\n\nCHANGELOG for LaunchKey Python SDK\n==================================\n\n3.5.0\n-----\n\n* Added get_all_directory_sdk_keys method to Organization client\n* Added integration testing suite\n* Added device failure sensor type\n* Added auth_methods and auth_policy attributes to the AuthorizationResponse object\n* Added handle_webhook as well as DeviceLinkCompletionResponse into the DirectoryClient\n* Updated the OrganizationClient update_directory() method and Directory object to include a webhook_url kwarg / attribute\n* Added Webhook example app\n\n3.4.0\n-----\n\n* Added example CLI to codebase\n* Added ttl parameter to the DirectoryClient link_device method\n* Added cancel_authorization_request method to the ServiceClient\n* Fixed bug in ServiceClient which prevented handling of session end webhook request data when presented as a bytearray\n\n3.3.1\n-----\n\n* Updated HTTP transport to no longer use sessions due to a bug that was causing BadStatusLine exceptions on long lived connections.\n\n3.3.0\n-----\n\n* Added tooling around code quality and ensured that CI build would fail without meeting expectations.\n* Added dynamic auth TTL and title functionality\n* Added dynamic auth push message body and title functionality\n* Added auth busy signal error handling\n* Added new auth response format\n* Added auth denial context functionality\n\n3.2.0\n-----\n\n* Remove PyCrypto and replace with pycryptodomex that is already required by PyJWKEST\n* Fixed geofence missing name bug\n* Added more expected error conditions to pydocs\n* Removed version lock for pytz requirement\n* Added 3rd party push enhancements\n* Added tox config for local testing in multiple versions of Python\n* Added missing response validation\n* Added full webhook validation\n* Cleaned up error handling and raising for webhooks\n* Switch RequestsTransport to use session in order to provide connection sharing between requests\n\n3.1.1\n-----\n\n* Added patch method for transports\n* Support for many new endpoints added involving Organization, Directory, and Service management\n* Moved all entity objects into their own submodule\n* Added UUID validation for factory entity IDs\n\n3.0.2\n-----\n\n* Improved 401 error handling\n* Bug fix for SessionEndRequest object\n* Service PINs bug fix\n\n3.0.1\n-----\n\n* Typo and manifest fixes\n* Added Unauthorized status code error handler\n* Nose version lock for test requirements\n\n3.0.0\n-----\n\n* Complete revamp for new V3 LaunchKey API\n\n2.0.1\n-----\n\n* Make tests run under Python 3.5+\n* Make PEP-8 compliant (deprecated some non-PEP-8 compliant functions)\n\n1.3.0\n-----\n\n* Python 3 compatibility.\n* Ability to send policies in auth request.\n\n1.2.7\n-----\n\n* Update manifest for new CHANGES file\n\n1.2.6\n-----\n\n* Fix for bad build regarding CHANGES.md\n\n1.2.5\n-----\n\n* Remove references to LK Identifier as the API no longer returns it.\n\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/iovation/launchkey-python", "keywords": "launchkey security authentication iovation multifactor mfa 2fa biometric", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "launchkey", "package_url": "https://pypi.org/project/launchkey/", "platform": "", "project_url": "https://pypi.org/project/launchkey/", "project_urls": { "Administration": "https://admin.launchkey.com/", "Bug Reports": "https://github.com/iovation/launchkey-python/issues", "Documentation": "https://docs.launchkey.com/service-sdk/python/sdk-v3/", "Homepage": "https://github.com/iovation/launchkey-python" }, "release_url": "https://pypi.org/project/launchkey/3.5.0/", "requires_dist": [ "enum34 (>=1.1.6,<2.0.0)", "formencode (<2.0.0,>=1.3.1)", "pycryptodomex (>=3.4.12,<4.0.0)", "pyjwkest (>=1.3.2,<2.0.0)", "python-dateutil (<3.0.0,>=2.4.2)", "pytz", "requests (<3.0.0,>=2.5.1)", "setuptools (>=40.4.3)", "six (>=1.10.0,<2.0.0)" ], "requires_python": "", "summary": "LaunchKey Python SDK", "version": "3.5.0" }, "last_serial": 5397734, "releases": { "3.0.0": [ { "comment_text": "", "digests": { "md5": "e1246e353052c4df26e33e50699c6e86", "sha256": "5b1fc3b373475c7d51c30e78817eaae0c0163294cb2879b840c2dbdfc40a6d3a" }, "downloads": -1, "filename": "launchkey-3.0.0.tar.gz", "has_sig": false, "md5_digest": "e1246e353052c4df26e33e50699c6e86", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16167, "upload_time": "2017-03-20T23:44:10", "url": "https://files.pythonhosted.org/packages/15/1b/efb6bd0add1398053c8b65d18aeb1a271818830d08e9182000e20b083db0/launchkey-3.0.0.tar.gz" } ], "3.0.1": [ { "comment_text": "", "digests": { "md5": "6c016540e840d93d854d6b65fc318309", "sha256": "4a8fd371708bdfb8309b815254cc4d9cbabe922df35dd1ecdd8c2823885b4abf" }, "downloads": -1, "filename": "launchkey-3.0.1.tar.gz", "has_sig": false, "md5_digest": "6c016540e840d93d854d6b65fc318309", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16299, "upload_time": "2017-04-10T21:01:47", "url": "https://files.pythonhosted.org/packages/0a/15/976002d4df299024cdfcc2c0df541e626ce822ee84270620f11381442324/launchkey-3.0.1.tar.gz" } ], "3.0.2": [ { "comment_text": "", "digests": { "md5": "22389e186a168b6c869053758ea938a8", "sha256": "f06929666cdcab661c9f53078766dff14013a63dfe59c5cf25d1c14805f03b85" }, "downloads": -1, "filename": "launchkey-3.0.2.tar.gz", "has_sig": false, "md5_digest": "22389e186a168b6c869053758ea938a8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16355, "upload_time": "2017-05-09T21:04:36", "url": "https://files.pythonhosted.org/packages/9c/3e/a9eec47e0513b1423a8303e524ceb67dcb1ea52733dc13f9135f1ef6097f/launchkey-3.0.2.tar.gz" } ], "3.1.1": [ { "comment_text": "", "digests": { "md5": "f81f2ac863982ab8f4bb412127198682", "sha256": "a31185d90253dc144c28913943acb830b86ba7d4f0fd6b82c4896eca6034b1dd" }, "downloads": -1, "filename": "launchkey-3.1.1.tar.gz", "has_sig": false, "md5_digest": "f81f2ac863982ab8f4bb412127198682", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23864, "upload_time": "2017-11-08T19:33:13", "url": "https://files.pythonhosted.org/packages/de/b6/0e90f3a04e663affe1056a47a5da25ee154515e8f868726ec09d60bd8af2/launchkey-3.1.1.tar.gz" } ], "3.3.0": [ { "comment_text": "", "digests": { "md5": "d75cbc0f86ae8884fd435dbfee8c2c42", "sha256": "6cd236ed79f0f329c8e15be41285830dda4b7b785a304c59996555e9397e3c41" }, "downloads": -1, "filename": "launchkey-3.3.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "d75cbc0f86ae8884fd435dbfee8c2c42", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45320, "upload_time": "2019-01-17T21:34:10", "url": "https://files.pythonhosted.org/packages/34/b5/e9fdd3dbfe1a9ce440d637fb81be632a2a7d1505d3443e406de77d2ce5aa/launchkey-3.3.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d0ab1aadd7b1bcd2069fb950a511a362", "sha256": "e9c5ec7e99304e54b23d3a9964a5e63ff0cb48d4d745f95d7b803abca97ab068" }, "downloads": -1, "filename": "launchkey-3.3.0.tar.gz", "has_sig": false, "md5_digest": "d0ab1aadd7b1bcd2069fb950a511a362", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32939, "upload_time": "2019-01-17T21:34:11", "url": "https://files.pythonhosted.org/packages/50/30/1ed7ebacfb4ea6e9ebe600e22f06ec80d29cd9f27b0bae012059dc479699/launchkey-3.3.0.tar.gz" } ], "3.5.0": [ { "comment_text": "", "digests": { "md5": "01819c3dfe1be43cfa63a490b3159912", "sha256": "b475009f7b9b6e6b8f0788380aded41a0ad45af3818ad70d73f7131ff02a1977" }, "downloads": -1, "filename": "launchkey-3.5.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "01819c3dfe1be43cfa63a490b3159912", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 50236, "upload_time": "2019-06-13T21:05:37", "url": "https://files.pythonhosted.org/packages/09/18/bf00cb15c815cd79ce2d9927d202a04212b95f78e65746b7258ce9b8a9c7/launchkey-3.5.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "47b1023749231ca36fd6f5896f0ac2f7", "sha256": "19c95d79385c3bd635b502d3d2167c3363ac4be6adfab39a1a68f1b22b63ddc7" }, "downloads": -1, "filename": "launchkey-3.5.0.tar.gz", "has_sig": false, "md5_digest": "47b1023749231ca36fd6f5896f0ac2f7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36841, "upload_time": "2019-06-13T21:05:39", "url": "https://files.pythonhosted.org/packages/2d/fb/79a5fefb2ada13627a2650c9b91ec63825038ce50f6e2b17f591f31345c3/launchkey-3.5.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "01819c3dfe1be43cfa63a490b3159912", "sha256": "b475009f7b9b6e6b8f0788380aded41a0ad45af3818ad70d73f7131ff02a1977" }, "downloads": -1, "filename": "launchkey-3.5.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "01819c3dfe1be43cfa63a490b3159912", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 50236, "upload_time": "2019-06-13T21:05:37", "url": "https://files.pythonhosted.org/packages/09/18/bf00cb15c815cd79ce2d9927d202a04212b95f78e65746b7258ce9b8a9c7/launchkey-3.5.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "47b1023749231ca36fd6f5896f0ac2f7", "sha256": "19c95d79385c3bd635b502d3d2167c3363ac4be6adfab39a1a68f1b22b63ddc7" }, "downloads": -1, "filename": "launchkey-3.5.0.tar.gz", "has_sig": false, "md5_digest": "47b1023749231ca36fd6f5896f0ac2f7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36841, "upload_time": "2019-06-13T21:05:39", "url": "https://files.pythonhosted.org/packages/2d/fb/79a5fefb2ada13627a2650c9b91ec63825038ce50f6e2b17f591f31345c3/launchkey-3.5.0.tar.gz" } ] }