{"id":6398,"date":"2020-05-11T09:44:56","date_gmt":"2020-05-11T14:44:56","guid":{"rendered":"https:\/\/www.rushworth.us\/lisa\/?p=6398"},"modified":"2020-05-11T11:11:32","modified_gmt":"2020-05-11T16:11:32","slug":"ldap-auth-python-flask","status":"publish","type":"post","link":"https:\/\/www.rushworth.us\/lisa\/?p=6398","title":{"rendered":"LDAP Authentication: Python Flask"},"content":{"rendered":"<p>This is a quick python script showing how the <a href=\"https:\/\/flask-ldap3-login.readthedocs.io\" target=\"_blank\" rel=\"noopener noreferrer\">flask-ldap3-login module<\/a> can be used to authenticate and gather user attribute values<\/p>\n<pre class=\"code panel\" data-language=\"code-python\"><span class=\"code-keyword\">from<\/span> flask_ldap3_login <span class=\"code-keyword\">import<\/span> LDAP3LoginManager\r\n<span class=\"code-keyword\">from<\/span> ldap3 <span class=\"code-keyword\">import<\/span> Tls\r\n<span class=\"code-keyword\">import<\/span> ssl\r\n\r\nconfig = <span class=\"code-object\">dict<\/span>()\r\n\r\nconfig[<span class=\"code-quote\">'LDAP_HOST'<\/span>] = <span class=\"code-quote\">'ad.example.com'<\/span>\r\n\r\n<span class=\"code-comment\"># Use SSL unless you are debugging a problem. Clear text port <span class=\"code-keyword\">is<\/span> 389 <span class=\"code-keyword\">and<\/span> tls_ctx needs to be removed <span class=\"code-keyword\">from<\/span> add_server call\r\n<\/span>config[<span class=\"code-quote\">'LDAP_USE_SSL'<\/span>] = <span class=\"code-keyword\"><span class=\"code-object\">True<\/span><\/span>\r\nconfig[<span class=\"code-quote\">'LDAP_PORT'<\/span>] = 636\r\n\r\n<span class=\"code-comment\"># Base DN\r\n<\/span>config[<span class=\"code-quote\">'LDAP_BASE_DN'<\/span>] = <span class=\"code-quote\">'dc=example,dc=com'<\/span>\r\n\r\n<span class=\"code-comment\"># User Base DN, prepended to Base DN\r\n<\/span>config[<span class=\"code-quote\">'LDAP_USER_DN'<\/span>] = <span class=\"code-quote\">'ou=UserDN'<\/span>\r\n\r\n<span class=\"code-comment\"># Groups Base DN, prepended to Base DN\r\n<\/span>config[<span class=\"code-quote\">'LDAP_GROUP_DN'<\/span>] = <span class=\"code-quote\">'ou=SecurityGroupDN'<\/span>\r\n\r\n<span class=\"code-comment\"># Server will be manually added to establish SSL\r\n<\/span>config[<span class=\"code-quote\">'LDAP_ADD_SERVER'<\/span>] = <span class=\"code-keyword\"><span class=\"code-object\">False<\/span><\/span>\r\n\r\n<span class=\"code-comment\"># Domain component of userprincipal name\r\n<\/span>config[<span class=\"code-quote\">'LDAP_BIND_DIRECT_SUFFIX'<\/span>] = <span class=\"code-quote\">'@example.com'<\/span>\r\n\r\n<span class=\"code-comment\"># Search scope needs to be subtree\r\n<\/span>config[<span class=\"code-quote\">'LDAP_USER_SEARCH_SCOPE'<\/span>] = <span class=\"code-quote\">\"SUBTREE\"<\/span>\r\n\r\n<span class=\"code-comment\"># Attributes to <span class=\"code-keyword\">return<\/span>\r\n<\/span>config[<span class=\"code-quote\">'LDAP_GET_USER_ATTRIBUTES'<\/span>] = (<span class=\"code-quote\">\"mail\"<\/span>, <span class=\"code-quote\">\"givenName\"<\/span>, <span class=\"code-quote\">\"sn\"<\/span>)\r\n\r\n<span class=\"code-comment\"># Setup a LDAP3 Login Manager.\r\n<\/span>ldap_manager = LDAP3LoginManager()\r\n\r\n<span class=\"code-comment\"># Init the mamager <span class=\"code-keyword\">with<\/span> the config since we aren't using an app\r\n<\/span>ldap_manager.init_config(config)\r\n\r\n<span class=\"code-comment\"># TLS settings to establish trust without validating CA issuance chain. \r\n<\/span><span class=\"code-comment\"># Can use CERT_REQUIRED <span class=\"code-keyword\">and<\/span> ca_certs_file <span class=\"code-keyword\">with<\/span> path to cacerts that includes issuing chain\r\n<\/span>tls_ctx = Tls(\r\n    validate=ssl.CERT_NONE,\r\n    version=ssl.PROTOCOL_TLSv1,\r\n    valid_names=[\r\n        <span class=\"code-quote\">'ad.example.com'<\/span>,\r\n    ]\r\n)\r\n\r\nldap_manager.add_server(\r\n    config.get(<span class=\"code-quote\">'LDAP_HOST'<\/span>),\r\n    config.get(<span class=\"code-quote\">'LDAP_PORT'<\/span>),\r\n    config.get(<span class=\"code-quote\">'LDAP_USE_SSL'<\/span>),\r\n    tls_ctx=tls_ctx\r\n)\r\n\r\n<span class=\"code-comment\"># Validate credentials\r\n<\/span>response = ldap_manager.authenticate_direct_credentials(<span class=\"code-quote\">'e0012345'<\/span>, <span class=\"code-quote\">'P@s5w0rdG03sH3re'<\/span>)\r\n<span class=\"code-object\">print<\/span>(response.status)\r\n<span class=\"code-object\">print<\/span>(response.user_info)\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This is a quick python script showing how the flask-ldap3-login module can be used to authenticate and gather user attribute values from flask_ldap3_login import LDAP3LoginManager from ldap3 import Tls import ssl config = dict() config[&#8216;LDAP_HOST&#8217;] = &#8216;ad.example.com&#8217; # Use SSL unless you are debugging a problem. Clear text port is 389 and tls_ctx needs to &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33],"tags":[295,303],"class_list":["post-6398","post","type-post","status-publish","format-standard","hentry","category-coding","tag-authentication","tag-ldap"],"_links":{"self":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/6398","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6398"}],"version-history":[{"count":2,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/6398\/revisions"}],"predecessor-version":[{"id":6421,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/6398\/revisions\/6421"}],"wp:attachment":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}