{"id":34042782,"url":"https://github.com/imsweb/django-saml-sp","last_synced_at":"2026-03-27T04:09:05.349Z","repository":{"id":37484475,"uuid":"220322548","full_name":"imsweb/django-saml-sp","owner":"imsweb","description":"A Django application for running one or more SAML service providers (SP)","archived":false,"fork":false,"pushed_at":"2024-05-29T23:13:06.000Z","size":93,"stargazers_count":16,"open_issues_count":4,"forks_count":10,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-09-14T14:03:00.441Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/imsweb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-07T20:23:22.000Z","updated_at":"2025-04-09T10:15:00.000Z","dependencies_parsed_at":"2023-02-11T18:50:25.391Z","dependency_job_id":null,"html_url":"https://github.com/imsweb/django-saml-sp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/imsweb/django-saml-sp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-saml-sp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-saml-sp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-saml-sp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-saml-sp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/imsweb","download_url":"https://codeload.github.com/imsweb/django-saml-sp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-saml-sp/sbom","scorecard":{"id":486471,"data":{"date":"2025-08-11","repo":{"name":"github.com/imsweb/django-saml-sp","commit":"e1d43247845f232121cee366e9ad97f64e3e2357"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":2,"reason":"Found 6/25 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 11 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T17:57:01.216Z","repository_id":37484475,"created_at":"2025-08-19T17:57:01.216Z","updated_at":"2025-08-19T17:57:01.216Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31018555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-27T03:51:26.850Z","status":"ssl_error","status_checked_at":"2026-03-27T03:51:09.693Z","response_time":164,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2025-12-13T22:44:49.275Z","updated_at":"2026-03-27T04:09:05.344Z","avatar_url":"https://github.com/imsweb.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Installation\n\n* `pip install django-saml-sp`\n* Add `sp` to your `INSTALLED_APPS` setting\n\n## Local Test Application\n\n### Start the local SimpleSAML IdP\n\n```\ndocker run -it --rm -p 8080:8080 -p 8443:8443 \\\n-e SIMPLESAMLPHP_SP_ENTITY_ID=http://localhost:8000/sso/local/ \\\n-e SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://localhost:8000/sso/local/acs/ \\\n-e SIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE=http://localhost:8000/sso/local/slo/ \\\nkristophjunge/test-saml-idp\n```\n\n### Bootstrap and run the local SP test app\n\n```\npython manage.py migrate\npython manage.py bootstrap\npython manage.py runserver\n```\n\nThe test SAML IdP defines the following user accounts you can use for testing:\n\n| UID | Username | Password | Group | Email |\n|---|---|---|---|---|\n| 1 | user1 | user1pass | group1 | user1@example.com |\n| 2 | user2 | user2pass | group2 | user2@example.com |\n\n\n### Sustainsys Stub IdP\n\nThe bootstrap command also creates a `stub` IdP which authenticates via\nhttps://stubidp.sustainsys.com. This is a good option if you don't want to run your own\nlocal identity provider for testing.\n\n\n## Integration Guide\n\n### Django Settings\n\n* `AUTHENTICATION_BACKENDS` - By default the Django authentication system is used to authenticate and log in users. Add `sp.backends.SAMLAuthenticationBackend` to your `AUTHENTICATION_BACKENDS` setting to authenticate using Django's `User` model. The user is looked up using `User.USERNAME_FIELD` matching the SAML `nameid`, and optionally created if it doesn't already exist. See the *Field Mapping* section below for how to map SAML attributes to `User` attributes.\n* `LOGIN_REDIRECT_URL` - This is the URL users will be redirected to by default after a successful login (or verification). Optional if you set `IdP.login_redirect` or specify a `next` parameter in your login URL.\n* `LOGOUT_REDIRECT_URL` - This is the URL users will be redirected to by default after a successful logout. Optional if you set `IdP.logout_redirect` or specify a `next` parameter in your logout URL.\n* `SESSION_SERIALIZER` - By default, Django uses `django.contrib.sessions.serializers.JSONSerializer`, which does not allow for setting specific expiration dates on sessions. If you want to use the `IdP.respect_expiration` flag to let the IdP dictate when the Django session should expire, you should change this to `django.contrib.sessions.serializers.PickleSerializer`. But if you do not plan on using that feature, leave the default. *Note: Django 4.1 forward now supports datetime session exipry using the default JSONSerializer.*\n\n### SP Settings\n\n* `SP_IDP_LOADER` - Allow you to specify a custom method for the SP views to retrieve an `IdP` instance given a request and the URL path parameters.\n* `SP_AUTHENTICATE` - A custom authentication method to use for `IdP` instances that do not specify one. By default, `sp.utils.authenticate` is used (delegating to the auth backend).\n* `SP_LOGIN` - A custom login method to use for `IdP` instances that do not specify one. By default, `sp.utils.login` is used (again, delegating to the auth backend).\n* `SP_LOGOUT` - A custom logout method to use for `IdP` instances that do not specify one. By default, `sp.utils.logout` is used, which simply delegates to Django's `auth.logout`.\n* `SP_PREPARE_REQUEST` - A custom prepare_request method to use for `IdP` instances that do not specify one. By default, `sp.utils.prepare_request` is used.\n* `SP_UPDATE_USER` - A custom update_user method to use for `IdP` instances that do not specify one. By default, `sp.utils.update_user` is used, which updates user fields based on mapped SAML attributes when users are created, or when the attributes are set to always update.\n* `SP_UNIQUE_USERNAMES` - When `True` (the default), `SAMLAuthenticationBackend` will generate usernames unique to the `IdP` that authenticated them, both when associating existing users and creating new users. This prevents user accounts from being linked to multiple IDPs (and prevents spoofing if untrusted IDPs can be configured).\n\n### URLs\n\nThe application comes with a URLconf that can be included, using any path parameters you want. The `IdP` is fetched by matching any URL parameters to the `url_params` field (or by some custom means via `SP_IDP_LOADER` above). For example:\n\n```python\npath(\"\u003cprefix\u003e/sso/\u003cidp_slug\u003e/\", include(\"sp.urls\"))\n```\n\nAssuming the URL configuration above, and an `IdP` configured with `url_params={\"prefix\": \"my\", \"idp_slug\": \"local\"}`, the following URLs would be available:\n\nURL | Description\n--- | -----------\n`/my/sso/local/` | The entity ID, and metadata URL. Visiting this will produce metadata XML you can give to the IdP administrator.\n`/my/sso/local/acs/` | The Assertion Consumer Service (ACS). This is what the IdP will POST to upon a successful login.\n`/my/sso/local/slo/` | The Single Logout Service (SLO). The IdP will redirect to this URL when logging out of all SSO services.\n`/my/sso/local/login/` | URL to trigger the login sequence for this IdP. Available programmatically as `idp.get_login_url()`. Takes a `next` parameter to redirect to after login. Also takes a `reauth` parameter to force the IdP to ask for credentials again (also see the verify URL below).\n`/my/sso/local/test/` | URL to trigger an IdP login and display a test page containing all the SAML attributes passed back. Available programmatically as `idp.get_test_url()`. Does not actually perform a Django user login.\n`/my/sso/local/verify/` | URL to trigger a verification sequence for this IdP. Available programmatically as `idp.get_verify_url()`. Does not perform a Django user login, but does check that the user authenticated by the IdP matches the current `request.user`.\n`/my/sso/local/logout/` | URL to trigger the logout sequence for this IdP. Available programmatically as `idp.get_logout_url()`. Takes a `next` parameter to redirect to after logout.\n\nYou can also include `sp.urls` without any URL parameters (e.g. `path(\"sso/\", include(\"sp.urls\"))`) if only a single `IdP` is needed (it should have `url_params={}`).\n\n\n### Configuring an identity provider (IdP)\n\n1. Create an `IdP` model object, either via the Django admin or programmatically. If you have metadata from your IdP, you can enter the URL or XML now, but it is not required yet.\n2. Generate a certificate to use for SAML requests between your SP and this IdP. You may use the built-in admin action for this by going to the Django admin page for Identity Providers, checking the row(s) you want, and selecting \"Generate certificates\" from the Action dropdown. If you already have a certificate you want to use, you can paste it into the appropriate fields.\n3. Give your IdP administrator the Entity ID/Metadata URL and ACS URL, if they need to explicitly allow access or provide you attributes.\n4. At this point, if you didn't in step 1, you'll need to enter either the IdP metadata URL, or metadata XML directly. Saving will automatically trigger an import of the IdP metadata, so you should see the Last Import date update if successful. There is also an \"Import metadata\" admin action to trigger this manually.\n\nYour IdP is now ready for testing. On the admin page for your IdP object, there is a \"Test IdP\" button in the upper right corner. You can also visit the `.../test/` URL (see above) manually to initiate a test. A successful test of the IdP will show a page containing the NameID and SAML attributes provided by the IdP.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimsweb%2Fdjango-saml-sp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimsweb%2Fdjango-saml-sp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimsweb%2Fdjango-saml-sp/lists"}