{"id":25181804,"url":"https://github.com/glocktober/samlsp","last_synced_at":"2026-05-03T02:36:59.918Z","repository":{"id":270138732,"uuid":"497953532","full_name":"Glocktober/SamlSP","owner":"Glocktober","description":null,"archived":false,"fork":false,"pushed_at":"2022-06-04T19:04:19.000Z","size":34,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-09T17:33:52.540Z","etag":null,"topics":["flask","python","saml2"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Glocktober.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-30T13:23:28.000Z","updated_at":"2022-12-13T01:33:22.000Z","dependencies_parsed_at":"2024-12-28T23:02:56.840Z","dependency_job_id":null,"html_url":"https://github.com/Glocktober/SamlSP","commit_stats":null,"previous_names":["glocktober/samlsp"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Glocktober%2FSamlSP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Glocktober%2FSamlSP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Glocktober%2FSamlSP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Glocktober%2FSamlSP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Glocktober","download_url":"https://codeload.github.com/Glocktober/SamlSP/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247129851,"owners_count":20888462,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","python","saml2"],"created_at":"2025-02-09T17:28:11.156Z","updated_at":"2026-05-03T02:36:59.879Z","avatar_url":"https://github.com/Glocktober.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## SamlSP - A Python SAML Service Provider for Flask\n\nThis Blueprint allows the addition of SAML2 Service Provider functionality (authentication/authorization) into a Flask application.\n\n### Features:\n* HTTP-Redirect binding for AuthenRequests, with optional Request signing\n* HTTP-Post binding for AuthnResponse with signing verification\n  * /acs\n* Response assertions attributes are stored in the session variable\n* A metadata endpoint providing XML configuration for IdP's\n  * /metadata\n* Loads IdP metadata from file or URL\n* Single Log Out (SLO) is not supported\n\n## Installation\n\n```bash\n# pip install SamlSP\n```\nor pull from github for sample client_app.py and configuration file.\n```bash\n# git clone https://github.com/Glocktober/SamlSP.git\n```\n\n## Configuration\n\nRefer to the sample configuration file [client_config_sample.py]\n\nThe Service Provider Entity Id is a URN (and generally a URL) familiar to the IdP that identifies this Service Provider.  This is set with the `sp_id` configuration key.\n\nIf requests will be signed then `sp_key` and `sp_cert` configuration settings will need to be specified.  If these are not set, the SAMLRequests will not be signed. `sp_key` specifies the PEM formated private key associated with `sp_cert` - the X509 Public Certificate that is then included in the metadata for use by IdPs to verify the request authenticity. \n\nThe XML metadata file from the IdP can be used to simplify configuring IdP details. This is set with the `idp_metadata` config key.\n\nAlternatively an IdP with an accessible metadata URL can be directly used, with the `idp_meta_url` config key.\n\nThe `url_prefix` key is url_prefix of the Flask Blueprint and is '/' by default.  This impacts the prefix for the `/acs` (assertions consumer service) and `/metadata` URLs.\n\nThe `assertions` config key is a list of strings - the names of assertions from the IdP that will be included in the users `session['attributes']` data - if they are present in the IdPs SAMLResponse.  \n\nThese assertions can be URN's with a full namespace or simple names, depending on the IdP being used and how it's configured. Names are matched caseless, but the IdPs case is reflected in the session attributes.\n\nIf no assertions are specified than only the nameId is saved and stored as the `session['username']`\n\nThe optional `user_attr` config key is the assertion attribute that is used specify the session['username'] value. By default this is the `NameId` of the SAMLResponse, but it is not uncommon to use `email` or `uid` as the username.\n\n## Using SamlSP for Authentication\n\nYou can initate a login by protecting a Flask route with a decorator\n```python\nfrom SamlSP import SamlSP\nfrom my_config import sp_config\n# see example client_config.py on setup details\nauth = SamlSP(sp_config)\n\n@app.route('/')\n@auth.require_login\ndef index_view():\n    return f'Hello World!'\n```\nAlternativly you can explictly call login:\n```python\n@app.route('/login')\ndef login():\n    return auth.initiate_login(next='/index')\n```\nOn authentication the Flask session is updated to include the keys `username`, `nameid`, and `attributes`. The `session['username']` value is set to the value of configured `user_attr` from the SAML assertions.  `session['nameid']` is set to SAML nameId assertions regardless of the NameID format of the IdP. The `session['attributes']` value is a dict containing any assertions from the SAMLResponse that matched the config file `attributes` list.\n\nAttributes can be accessed via the `session['attributes']` key.\n```python\n@app.route('/hello')\n@auth.require_login\ndef index_view():\n    return f\"Hello {session['attributes']['givenName']}!\"\n```\nTo log out you can use `session.clear()` - which clears the entire session. If you only want to clear the SAML data, you can use `auth.unauthenticate()` - which will clear the `attributes`, `username`, and `nameID` from the users session.\n\n## notes\nThis has been tested with SimpleSamlPhp and Azure AD as well as my SamlIdp.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglocktober%2Fsamlsp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fglocktober%2Fsamlsp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglocktober%2Fsamlsp/lists"}