Giter Site home page Giter Site logo

zibasec / django-saml2-pro-auth Goto Github PK

View Code? Open in Web Editor NEW
30.0 10.0 28.0 109 KB

SAML2 authentication backend for Django wrapping OneLogin's python-saml package https://github.com/onelogin/python3-saml

License: MIT License

Python 91.08% HTML 8.92%
saml2 django-authentication django python3

django-saml2-pro-auth's Introduction

Django SAML2 Pro Auth

SAML2 authentication backend for Django


build-status-badge pypi-version-badge license-badge

pypi-pyverions-badge pypi-djverions-badge downloads-badge

Requirements

  • Python (3.6, 3.7, 3.8, 3.9)
  • Django (2.2.20, 3.0.14, 3.1.8)
  • python3-saml (>=1.9.0)

We recommend and only support patched versions of Python and Django that are still receiving updates.

Installation

pip install django-saml2-pro-auth

Prerequisites

The python3-saml package depends on the xmlsec package which requires the installation of native C libraries on your OS of choice.

You will want to follow the instructions for setting up the native dependencies on your OS of choice.

Configuration

Django Settings

Here is an example full configuration. Scroll down to read about each option

AUTHENTICATION_BACKENDS = [
      'saml2_pro_auth.auth.Backend'
]

SAML_REDIRECT = '/'

SAML_USERS_MAP = {
    "MyProvider" : {
      "email": dict(key="Email", index=0),
      "name": dict(key="Username", index=0)
    }
}


SAML_PROVIDERS = {
    "MyProvider": {
        "strict": True,
        "debug": False,
        "custom_base_path": "", # Optional, set if you are reading files from a custom location on disk
        "lowercase_urlencoding": False, # This can be set to True to enable ADFS compatibility
        "idp_initiated_auth": True, # This can be set to False to disable IdP-initiated auth
        "sp": {
            "entityId": "https://test.davila.io/sso/saml/metadata",
            "assertionConsumerService": {
                "url": "https://test.davila.io/sso/saml/?acs",
                "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
            },
            "singleLogoutService": {
                "url": "https://test.davila.io/sso/saml/?sls",
                "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            },
            "NameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
            ## For the cert/key you can place their content in
            ## the x509cert and privateKey params
            ## as single-line strings or place them in
            ## certs/sp.key and certs/sp.crt or you can supply a
            ## path via custom_base_path which should contain
            ## sp.crt and sp.key
            "x509cert": "",
            "privateKey": "",
        },
        "idp": {
            "entityId": "https://kdkdfjdfsklj.my.MyProvider.com/0f3172cf-5aa6-40f4-8023-baf9d0996cec",
            "singleSignOnService": {
                "url": "https://kdkdfjdfsklj.my.MyProvider.com/applogin/appKey/0f3172cf-5aa6-40f4-8023-baf9d0996cec/customerId/kdkdfjdfsklj",
                "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            },
            "singleLogoutService": {
                "url": "https://kdkdfjdfsklj.my.MyProvider.com/applogout",
                "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
            },
            "x509cert": open(os.path.join(BASE_DIR,'certs/MyProvider.crt'), 'r').read(),
        },
        "organization": {
            "en-US": {
                "name": "example inc",
                "displayname": "Example Incorporated",
                "url": "example.com"
            }
        },
        "contactPerson": {
            "technical": {
                "givenName": "Jane Doe",
                "emailAddress": "[email protected]"
            },
            "support": {
                "givenName": "Jane Doe",
                "emailAddress": "[email protected]"
            }
        },
        "security": {
            "nameIdEncrypted": False,
            "authnRequestsSigned": True,
            "logoutRequestSigned": False,
            "logoutResponseSigned": False,
            "signMetadata": True,
            "wantMessagesSigned": True,
            "wantAssertionsSigned": True,
            "wantAssertionsEncrypted": True,
            "wantNameId": True,
            "wantNameIdEncrypted": False,
            "wantAttributeStatement": True,
            # Algorithm that the toolkit will use on signing process. Options:
            #    'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
            #    'http://www.w3.org/2000/09/xmldsig#dsa-sha1'
            #    'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
            #    'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'
            #    'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
            "signatureAlgorithm": "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",

            # Algorithm that the toolkit will use on digest process. Options:
            #    'http://www.w3.org/2000/09/xmldsig#sha1'
            #    'http://www.w3.org/2001/04/xmlenc#sha256'
            #    'http://www.w3.org/2001/04/xmldsig-more#sha384'
            #    'http://www.w3.org/2001/04/xmlenc#sha512'
            'digestAlgorithm': "http://www.w3.org/2001/04/xmlenc#sha256"
        }

    }
}

AUTHENTICATION_BACKENDS: This is required exactly as in the example. It tells Django to use this as a valid auth mechanism.

SAML_ROUTE (optional, default=/sso/saml/): This tells Django where to do all SAML related activities. The default route is /saml/. You still need to include the source urls in your own urls.py. For example:

from django.conf import settings
from django.contrib import admin
from django.urls import include, path

import saml2_pro_auth.urls as saml_urls

import profiles.urls
import accounts.urls

from . import views

urlpatterns = [
    path('', views.HomePage.as_view(), name='home'),
    path('about/', views.AboutPage.as_view(), name='about'),
    path('users/', include(profiles.urls, namespace='profiles')),
    path('admin/', include(admin.site.urls)),
    path('', include(accounts.urls, namespace='accounts')),
    path('', include(saml_urls, namespace='saml')),
]

So first import the urls via import saml2_pro_auth.urls as saml_urls (it's up to you if you want name it or not). Then add it to your patterns via path('', include(saml_urls, namespace='saml')). This example will give you the default routes that this auth backend provides. You can also add any additional prefix to the path that you want here.

If you want to use the old function-based view URLs you can import and use those instead.

import saml2_pro_auth.function_urls as saml_urls

SAML_OVERRIDE_HOSTNAME (optional, default=""): This allows you to set a specific hostname to be used in SAML requests. The default method to is detect the hostname from the request object. This generally works unless you are behind several layers of proxies or other caching layers. For example, running Django inside a Lambda function that is fronted by API Gateway and CloudFront could pose problems. This setting lets you set the value explicitly. The value should be a simple hostname or dotted path. Do not include a full URL, port, scheme, etc.

SAML_OVERRIDE_HOSTNAME = "app.example.org"

SAML_CACHE (optional, default="default"): This lets you specify a different cache backend configuration if need you a specific type of persistent cache mechanism that differs from the CACHES["default"]. A persistent cache is required for only once SAML assertion processing to work. This is an important security mechanism and should not be bypassed. In local development environments, the local memory, dummy, or file caches will work fine. For stateless or multi-server high availability environments you will want to use a shared, persistent cache. Storing this in the Database is likely the easiest solution since the data is small and the number of requests should be minimal.

If your default cache is not using a shared persistent cache configuration you can add on and update this setting.

SAML_CACHE = "saml2_pro_auth"

CACHES = {
    'saml2_pro_auth': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'saml2_pro_auth_cache',
    }
}

SAML_REPLAY_PROTECTION (optional, default=True): This allows you to disable the only-once assertion processing protection (SAML assertion replay protection) mechanism. It currently relies on a shared persistent caching mechanism that may not be feasible in all environments. It is strongly recommend you to keep this enabled but if there are architectural reasons or there is a low risk of replay attacks then it can still be disabled.

SAML_REDIRECT (optional, default=None): This tells the auth backend where to redirect users after they've logged in via the IdP. NOTE: This is not needed for most users. Order of precedence is: SAML_REDIRECT value (if defined), RELAY_STATE provided in the SAML response, and the fallback is simply to go to the root path of your application.

SAML_USERS_MAP (required): This is a dict of user attribute mapping dicts. This is what makes it possible to map the attributes as they come from your IdP into attributes that are part of your User model in Django. There a few ways you can define this. The dict keys (the left-side) are the attributes as defined in YOUR User model, the dict values (the right-side) are the attributes as supplied by your IdP.

## Simplest Approach, when the SAML attributes supplied by the IdP are just plain strings
## This means my User model has an 'email' and 'name' attribute while my IdP passes 'Email' and 'Username' attrs
SAML_USERS_MAP = {
    "myIdp" : {
      "email": "Email",
      "name": "Username
    }
}

Sometimes, IdPs might provide values as Arrays (even when it really should just be a string). This package supports that too. For example, suppose your IdP supplied user attributes with the following data structure: {"Email": ["[email protected]"], "Username": "foo"} You simply would make the key slightly more complex where key is the key and index represents the index where the desired value is located. See below:

SAML_USERS_MAP = {
    "myIdp" : {
      "email": {"key": "Email", "index": 0},
      "name": "Username
    }

And of course, you can use the dict structure even when there IdP supplied attribute isn't an array. For example:

SAML_USERS_MAP = {
    "myIdp" : {
      "email": {"key": "Email"},
      "name": {"key": "Username"}
    }

SAML_USERS_LOOKUP_ATTRIBUTE (optional, default=("username", "NameId")): A tuple that specifies the User model field and lookup type to be used for object lookup in the database, along with the attribute to match. It defaults to matching username to the NameId sent from the IdP. If you want to match against a different database field you would update the key, if you want to use a different attribute from the IdP you would update the value.

The attribute you match on in the Django User model should have the "unique" flag set. (In the default User model in django only username has a unique contstraint in the DB, the same email could be used by multiple users)

This can also include Django field lookup extensions. By default the lookup will be performed as an exact match. If you have an identity provider that sends case sensitive emails and you are storing the email in the username field you can still match emails in your database by using username__iexact. Anything before the double underscore will be used as the field name, everything after is used in the Django Query field lookup.

Defaults to ("username", "NameId")

SAML_USERS_LOOKUP_ATTRIBUTE = ("username__iexact", "NameId")

SAML_USERS_SYNC_ATTRIBUTES (optional): Specifies if the user attributes have to be updated at each login with those received from the IdP.

Defaults to False

SAML_USERS_SYNC_ATTRIBUTES = True

SAML_USERS_STRICT_MAPPING (optional): Specifies if every user attribute defined in SAML_USER_MAP must be present in the saml response or not.

Defaults to True

SAML_USERS_STRICT_MAPPING = False

If set to False, you can optionally specify a default value in the "SAML_USER_MAP" dict and it will set the value when the attribute is not present in the IdP response object.

Example default value setting

# set default value for is_superuser and is_staff to False
SAML_USERS_STRICT_MAPPING = False
SAML_USERS_MAP = {
    "MyProvider" : {
      "email": dict(key="email", index=0),
      "username": dict(key="username", index=0),
      "is_superuser": dict(key="is_superuser", index=0, default=False),
      "is_staff": dict(key="is_staff", index=0, default=False)
    }
}

SAML_AUTO_CREATE_USERS (optional): Specifies if you want users to be automatically created if they don't already exist in the database.

Defaults to True

SAML_AUTO_CREATE_USERS = False

SAML_PROVIDER_CONFIG_TEMPLATE This is a base template to use for any SamlProvider model instances if you are using the settings model class. You can override any settings in this template to set your base configuration. This also helps you to stay DRY.

PROVIDER_CONFIG_TEMPLATE = {
    "strict": True,
    "sp": {
        "x509cert": "",
        "privateKey": "",
    },
    # No one actually sets these fields in their metadata
    # "organization": {
    #     "en-US": {
    #         "name": "",
    #         "displayname": "",
    #         "url": "",
    #     }
    # },
    # "contactPerson": {
    #     "technical": {"givenName": "", "emailAddress": ""},
    #     "support": {"givenName": "", "emailAddress": ""},
    # },
    "security": {
        "nameIdEncrypted": False,
        "authnRequestsSigned": True,
        "logoutRequestSigned": True,
        "logoutResponseSigned": True,
        "signMetadata": True,
        "wantMessagesSigned": True,
        "wantAssertionsSigned": False,
        "wantAssertionsEncrypted": False,
        "wantNameId": True,
        "wantNameIdEncrypted": False,
        "wantAttributeStatement": False,
        "signatureAlgorithm": "http://www.w3.org/2000/09/xmldsig#rsa-sha256",
        "digestAlgorithm": "http://www.w3.org/2001/04/xmlenc#sha256",
    },
}

SAML_PROVIDERS: This is an extended version of the OneLogin spec python-saml and python3-saml packages. The big difference is here you supply a dict of settings dicts where the top most key(s) must map 1:1 to the top most keys in SAML_USERS_MAP. Also, this package allows you to ref the cert/key files via open() calls. This is to allow those of you with multiple external customers to login to your platform with any N number of IdPs.

NOTE: Provider names (top level keys in the settings dict) must adhere to a slug like set of characters [\w-]+ or a-zA-Z0-9_-.

Extensions to the OneLogin settings dict spec:

  • The lowercase_urlencoding setting (default=False) can be specifed in your settings dict per provider. This allows you to support ADFS IdPs.
  • The idp_initiated_auth setting (default=True) can be specified in your settings dict per providfer This allows you to disable IdP-initiated flows on a provider-by-provider basis. You may want to consider disable IdP-initiated flows to avoid accepting unsolicited SAML assertions and eliminate a small class of vulnerabilities and potential CSRF attacks. Setting this value to False will disable IdP-initiated auth.

Class-based View Routes

Route Uses
/saml/acs/<samlp:provider>/ The Assertion Consumer Service Endpoint. This is where your IdP will be POSTing assertions.
/saml/sso/<samlp:provider>/ Use this endpoint when you want to trigger an SP-initiated login. For example, this could be the href of a "Login with ClientX Okta" button.
/saml/metadata/<samlp:provider>/ This is where the SP (ie your Django App) has metadata. Some IdPs request this to generate configuration.

The class-based views and routes use a custom path converter <samlp:provider> to create URLs from provider name strings or to automatically match a top level key of your SAML_PROVIDERS settings on requests. This also has the benefit of returning the provider settings dict and sending it to the View automatically. You must ensure that your provider names adhere to a slug like set of characters [\w-]+.

Legacy (Function-based View) Routes

Route Uses
/sso/saml/?acs&amp;provider=MyProvider The Assertion Consumer Service Endpoint. This is where your IdP will be POSTing assertions. The 'provider' query string must have a value that matches a top level key of your SAML_PROVIDERS settings.
/sso/saml/metadata?provider=MyProvider This is where the SP (ie your Django App) has metadata. Some IdPs request this to generate configuration. The 'provider' query string must have a value that matches a top level key of your SAML_PROVIDERS settings.
/sso/saml/?provider=MyProvider Use this endpoint when you want to trigger an SP-initiated login. For example, this could be the hrefof a "Login with ClientX Okta" button.

Reverse URLs

You can reference the above URLs using the standard Django {% url ... %} template tag or reverse(...) function.

{% url 'saml:metadata' provider='MyProvider' %}
{% url 'saml:sso' provider='MyProvider' %}

Or for the function-based routes.

{% url 'saml:metadata' %}?provider=MyProvider
{% url 'saml:saml2_auth' %}?acs&provider=MyProvider

Gotchas

The following are things that you may run into issue with. Here are some tips.

  • Ensure the value of the SP entityId config matches up with what you supply in your IdPs configuration.
  • Your IdP may default to particular Signature type, usually Assertion or Response are the options. Depending on how you define your SAML provider config, it will dictate what this value should be.

Wishlist and TODOs

The following are things that arent present yet but would be cool to have

  • Implement logic for Single Logout Service
  • Integration test with full on mock saml interactions to test the actual backend auth
  • Tests add coverage to views and the authenticate() get_user() methods in the auth backend
  • Models (with multi-tentant support) for idp and sp in order to facilitate management via django admin
  • Add a proper CHANGELOG to release process.

Release Process

The following release process is manual for now but may be integrated into a CI action in the future.

All code contributions are merged to the main branch through a standard pull request, test, review, merge process. At certain intervals new releases should be cut and pushed to PyPI. This is the standard process for creating new releases from the main branch.

  1. Update the version information in setup.cfg e.g., version = X.Y.Z

  2. Create a new git tag with the same version

    git tag -a -s vX.Y.Z -m 'Version X.Y.Z'
    • -s requires you to have GPG and signing properly setup.
  3. Push the tags to the remote

    git push --follow-tags origin vX.Y.Z
  4. Create the source and binary distributions and upload to PyPI.

    # runs
    # python setup.py sdist bdist_wheel
    # twine check dist/*
    tox -f build
    # upload to test pypi
    twine upload testpypi dist/*
    # upload to production pypi
    twine upload dist/*
  5. Create a release on GitHub

django-saml2-pro-auth's People

Contributors

1oglop1 avatar apreche avatar big4smk avatar erichigdon avatar fservida avatar heavensleep avatar piotrbilski avatar santiagovassallo avatar shepdelacreme avatar sphinxs avatar tecknicaltom avatar vdzs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-saml2-pro-auth's Issues

Option to use nameid as the user lookup attribute

I can't see any way to use the name id from the SAMLResponse as the lookup value for users in Django, so if the IDP doesn't supply this as a separate attribute, there is no way to match the user in Django.

Is this something that I've missed, or something that could be added through the settings? If nameid was added to the lookup map then it would make this simple, and would still provide support for custom user models in Django.

ACS's URL changed to http and fired 301 http response after login

Grettings,

First, I want to say thankyou for all your effort developing this package.

I implemented django-saml2-pro-auth and It worked in my local enviroment, but when I pushing to AWS Lambda, I checked the ACS's URL changed to http and It raise an 301 http response but It doesn't happend in my local enviroment. For example:

Local enviroment:
imagen
By the way, I use an enviroment variable to store https://localhost:8000

AWS Lambda enviroment:
imagen
In this case, You can see EntityDescriptor and AssertionConsumerService tags have "http://" but only SingleLogoutService tag keeps https:// and I repeat, I use an enviroment variable to set the server's url.

This issue fired a 301 http response and then redirects me to the same ACS's URL but with GET method but GET method isn't allowed to that URL as you can see in the next image:
imagen

I hope somebody could help with this issue.

prepare_django_request should use request.get_host()

Instead of using request.META['HTTP_HOST'], prepare_django_request should use request.get_host() so that it works properly for app servers behind a proxy. In this configuration, Django should be configured with USE_X_FORWARDED_HOST so that request.get_host() uses the value from the X-FORWARDED-HOST header instead of Host.

Make Users unique to IDP

Hi, I noticed that the user creation/lookup is solely based on the name id that the IDP provides. This could cause issues if multiple IDPs return the same NameId (be it malicious or just a bad way to generate the ids). Would it be possible to provide a way to generate the user id more dynamically? My suggestion would be to allow lookup_attr[1] in auth.py:90 to be function that takes saml_auth and final_map as arguments (and possibly the provider name?). Happy to provide a PR if you agree.

I do acknowledge that IDP providers should generally be trusted, and sometimes you even want to merge accounts that different IDPs provide, but in my case I am a bit paranoid about IDPs behaving badly.

SAML URL encoding bugs (possibly Azure only)

There is a bug in urls
Because Onelogin SP assertionConsumerService.url overrides reply url configured in IdP (Azure AD), data being POSTed to wrong url.
Causing django_saml2_pro_auth.utils.SAMLError: No provider specified in request.

Example:

settings.py

SAML_PROVIDERS = [{
    "MyProvider": {
        "strict": False,
        "debug": True,
        "sp": {
            "entityId": "https://test.app.jan",
            "assertionConsumerService": {
                "url": "http://localhost:9876/sso/saml/?acs",
                "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"

SAML Request contains

AssertionConsumerServiceURL="http://localhost:9876/sso/saml/?acs"

But django-saml2-pro-auth is expecting /sso/saml/?acs&provider=MyProvider.

I tried this workaround:
So I tried to change assertionConsumerService.url to "url": "http://localhost:9876/sso/saml/?acs&provider=MyProvider.

Hence this this has been rejected at Microsoft site as Bad Request
AADSTS75005: The request is not a valid Saml2 protocol message.

My guess was the problem of url encoding and decoding, then I changed & to %26
"url": "http://localhost:9876/sso/saml/?acs%26provider=MyProvider which did the trick for sending of request.
But plugin does not know how to decode url in SAML response Destination="http://localhost:9876/sso/saml/?acs% 26provider=MyProvider"
I guess this is partially problem of OneLogin

Access allowed for users that have is_active=False

I found that users that have is_active set to false are still allowed to login through SAML, the saml_login code in views.py doesn't check if it actually get back a user from the authenticate call, so just creating a backend that checks for is_active=False and returns None if so doesn't really work.

I propose something like this in the saml_login view.

user = authenticate(request=request)
if user is None:
    #raise exception
login(request, user)

If you'd agree I can create a pull request, or would you propose a different solution to block is_active=False users from entering through SAML?

Should the first provider be used as the default?

It seems a bit excessive to have to define which provider to use on every login attempt. Perhaps if 'provider' is not present in the GET data, it should fallback to the first provider in the settings. Any concerns with something like pull request #21?

Authentication error

@django=1.11
We get:
TypeError: authenticate() takes 0 positional arguments but 1 was given

for:
django_saml2_pro_auth/views.py line 42
user = authenticate(request=request)

Any known reason?

Support for Django 3.2+

Right now ProviderConverter raises SynchronousOnlyOperation when you try it on Django 3.2

SAML bad Request - The message of the response is not signed and the SP require it

Hello, I have a Django app that uses the package, we puted the wantMessagesSigned: True, we added this config in the admin interface as well, and we still receiving this error, I'm pretty sure the IDP sends a signature for us. Any change that we made is reflected in the application, is like the package not get the values from settings.
"security": {
"nameIdEncrypted": False,
"authnRequestsSigned": True,
"logoutRequestSigned": True,
"logoutResponseSigned": True,
"signMetadata": True,
"wantMessagesSigned": True,
"wantAssertionsSigned": True,
"wantAssertionsEncrypted": True,
"wantNameId": True,
"wantNameIdEncrypted": False,
"wantAttributeStatement": True,
"signatureAlgorithm": "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
"digestAlgorithm": "http://www.w3.org/2000/09/xmldsig#sha1",

Thank you.

SP public and private key

The python-saml plugin already is able to read public and private key from file so the setting:

"x509cert": open(os.path.join(BASE_DIR,'certs/sp.crt'), 'r').read(),
 "privateKey": open(os.path.join(BASE_DIR,'certs/sp.key'), 'r').read(),

Is not really required

saml_login does not use the 'next' parameter

Am I missing a way to redirect the user back to the page they were attempting to access? Django adds a ?next parameter when redirecting to the login page. Perhaps views.saml_login should check for that parameter in the GET data and use the value as return_to when calling auth.login? Pull request #22

Can't override default security values.

I'm trying to override security values using settings.py config file within my Django project. All my security settings are ignored and default values are being used.
I'm mostly intrested in "requestedAuthnContext" and I want to set it to "False". I've also tried to modify other parameters like nameIdEncrypted or signatureAlgorithm. All of those get ignored.

Errors in documentation, no migration path for pre v1.0 users

The documentation (the README in the project root) contains a few errors and omissions:

  • It doesn't mention that one needs to add saml2_pro_auth to the INSTALLED_APPS list
  • It refers to the function_urls, which no longer exist

This second item is causing an issue for people migrating from pre 1.0 to post 1.0: the class-based views have changed the SAML URLs, which means the SSO provider must update their settings to match the new URLs. In some organisations this can be a bit problematic due to slow formal ITIL procedures.

Not sure if this is a bug, or simply not or badly documented, but I would have guessed that setting the SAML_ROUTE setting, and including the URLs for ACS and SLS under the SAML_PROVIDERS dictionary, would result in the system using the same URLs as previously under the function-based views. This doesn't seem to work. I already had them in my settings, and they remain unchanged. What's worse: the new URLs don't seem to work either. They either result in a 404 or a 500. Before I file a separate bug for that, can someone from the team enlighten me as to whether these settings should in fact override the URLs for the class-based views as well?

KeyError at /sso/saml/

Hello! I'm having an issue with the user mapping process, because the configuration of the saml where I work doesn't return the key if the user doesn't have the atribute. So when it reaches to the point of mapping, it's possible that saml_data doesn't have one or more keys that have been specified in the SAML_USERS_MAP.

Is it possible to consider this and maybe do this process less strict by controlling if the user_key is in saml_data before asigning it?

Thank you a lot!

Add example usage to repo and update docs

Hi,
first of all I'd like to thank you for great work.

Do you have any simple example how to use this in app? I have really basic experience with Django and I'd like to use this.

Thank you

How does SAML_REDIRECT work ?

Hi,

From what I understand of the flow, the IDP is looking at my metadata endpoint and calling http://mydomain.com/sso/saml/?acs&provider=myprovider to authenticate the user.

What I want to do is redirect the user after authentication to a specific page.

I thought SAML_REDIRECT would do this but it looks like it does not work that way.

SAML_REDIRECT is only used if acs is not on the URL, since it's a elif instead of a if.

https://github.com/voxy/django-saml2-pro-auth/blob/master/src/django_saml2_pro_auth/views.py#L50

Can I have an example on how to use this setting?

Thanks a lot!

Update tested Python and Django versions

We should update the tested Python versions to include py 3.7, 3.8, and 3.9 and probably trim some of the older versions in the list. We can remove Python 2.x support altoghter and clean up any remaining 2.x backwards compatibility-isms left in the code.

Django versions should be trimmed as well 1.8, 1.10 should definitely be removed, and possibly 1.11 since it is now officially EOL.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.