Coder Social home page Coder Social logo

descope / django-descope Goto Github PK

View Code? Open in Web Editor NEW
28.0 28.0 4.0 539 KB

Descope plugin for Django framework

Home Page: https://docs.descope.com

License: MIT License

Python 89.65% HTML 6.27% CSS 4.08%
app authentication descope django plugin python sdk

django-descope's People

Contributors

cleptomania avatar dependabot[bot] avatar descope[bot] avatar guyp-descope avatar omercnet 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-descope's Issues

"Add Descope Middleware after the SessionMiddleware"

I haven't tested this exhaustively, but it seems like this is somewhat misleading. The Descope Middleware needs to go after a bunch of things, not just the SessionMiddleware. I would suggest stating that it should go at the end, as the errors you get is far from obvious that that's the problem.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Repository problems

Renovate tried to run on this repository, but found these problems.

  • WARN: Unexpected range error
  • WARN: Detected empty commit - aborting git push

Edited/Blocked

These updates have been manually edited so Renovate will no longer make changes. To discard all commits and start over, click on a checkbox.

Other Branches

These updates are pending. To force PRs open, click the checkbox below.

  • fix(deps): update dependency django to v4.2.15 [security]

Detected dependencies

github-actions
.github/workflows/ci.yaml
  • actions/checkout v4
  • actions/setup-python v5
  • actions/cache v4
.github/workflows/python-publish.yaml
  • actions/checkout v4
pep621
pyproject.toml
  • poetry >=1,<2
poetry
pyproject.toml
  • python >=3.8.1,<4.0
  • Django >=3.2.19,<5.1
  • descope ^1.5.1
  • flake8 7.0.0
  • black 23.11.0
  • pre-commit 3.6.0
  • liccheck 0.9.1
  • isort 5.13.0
  • python-dotenv 1.0.1
  • tox 4.11.4
  • django-debug-toolbar 4.3.0
  • django-stubs 4.2.7

  • Check this box to trigger a request for Renovate to run again on this repository

request.session.get("user") == None

For some reason, request.session.get("user") == None inside of a view, even though I am authenticated.

I am able to sign in just fine using the scope, and logging out works as well, and Django Admin works, but the test endpoint doesn't work, I always get {} along with these logs:

dev-retrieve-front-end-1  | Validating (and refreshing) Descope session
dev-retrieve-front-end-1  | session eyJhbGciOiJSUzI1NiIsImtpZCI6IlAyT25tUmd5SFFNN3RNRU1FOG1qUEdYcmdLY2kiLCJ0eXAiOiJKV1QifQ.eyJhbXIiOlsid2ViYXV0aG4iXSwiZHJuIjoiRFMiLCJleHAiOjE2ODU5MzI2NDUsImlhdCI6MTY4NTkzMjA0NSwiaXNzIjoiUDJPbm1SZ3lIUU03dE1FTUU4bWpQR1hyZ0tjaSIsInJleHAiOiIyMDIzLTA3LTAzVDAyOjI3OjI1WiIsInJvbGVzIjpbImlzX3N0YWZmIiwiaXNfc3VwZXJ1c2VyIl0sInN1YiI6IlUyT25tbTJROVVSNWVGRlBNU3NZU0VsNHdXVjcifQ.Wc9RB4Qf3ZzdkD4I4oq_d7SgH5gw54Qq4cI-u8j3T3-BSnx-s6GV1Jz13VF07fZnzYSnV_jJRM-FnMqwL89CmdqvTrOHUSA8FDkJygthgFelHwE2_OJWFGePf4T-V6zeqWx427uoNIQFHQvbMelRaHH__dc66NbOzILZWcafx5VAdLIj5IqX-MZqVecUMiZqMTEw8q1hCbqX6lHrhZUrN_Ez47Exc173WLxd2AVy3El-OS5s6rP6y4FFXza7oUranJmEuoRXsPL_DShHV2fpnuQC3bL-gRKgY03RB3LPq7O-_VxeHIkbMDSbyFUefKP6WL05od9U_fklEwyQUj4WgQ
dev-retrieve-front-end-1  | refresh eyJhbGciOiJSUzI1NiIsImtpZCI6IlAyT25tUmd5SFFNN3RNRU1FOG1qUEdYcmdLY2kiLCJ0eXAiOiJKV1QifQ.eyJhbXIiOlsid2ViYXV0aG4iXSwiZHJuIjoiRFNSIiwiZXhwIjoxNjg4MzUxMjQ1LCJpYXQiOjE2ODU5MzIwNDUsImlzcyI6IlAyT25tUmd5SFFNN3RNRU1FOG1qUEdYcmdLY2kiLCJzdWIiOiJVMk9ubW0yUTlVUjVlRkZQTVNzWVNFbDR3V1Y3In0.U-T8qqZ-beD2TDBjtAhNuC6c2OERoekI1_8sAC9KAxr0aPq6-dGu0jJb8Nqu2lBE5R_6gaK9n2nI01j3QquWBdbhsePzcp_TVTr5GDTHYEjxMQxbXOQycfj5zmPVdJKAfd0f4GsQjOHLW-PEmX911uB5T98WIPGX2SO67eWjaOLX8Aw1DiNMqRNhA-5fOPeEXtDsP82n28e9yQU6Kv8sMbkHXp28Tmm4PsP-dPha6nGlslouY1yESofwObL_EO2jSo19Db0PIwY-0UUX3bXcLAVOMNc2knucxH6iN5cOADk5HS_Jg_ztwugp7c2ADgG4yOYBXvwAbhz8ve_AGeRzfw
dev-retrieve-front-end-1  | Starting new HTTPS connection (1): api.descope.com:443
dev-retrieve-front-end-1  | https://api.descope.com:443 "GET /v2/keys/P2OnmRgyHQM7tMEME8mjPGXrgKci HTTP/1.1" 200 None
dev-retrieve-front-end-1  | {'amr': ['webauthn'], 'drn': 'DS', 'exp': 1685932645, 'iat': 1685932045, 'iss': 'P2OnmRgyHQM7tMEME8mjPGXrgKci', 'rexp': '2023-07-03T02:27:25Z', 'roles': ['is_staff', 'is_superuser'], 'sub': 'U2Onmm2Q9UR5eFFPMSsYSEl4wWV7', 'jwt': 'eyJhbGciOiJSUzI1NiIsImtpZCI6IlAyT25tUmd5SFFNN3RNRU1FOG1qUEdYcmdLY2kiLCJ0eXAiOiJKV1QifQ.eyJhbXIiOlsid2ViYXV0aG4iXSwiZHJuIjoiRFMiLCJleHAiOjE2ODU5MzI2NDUsImlhdCI6MTY4NTkzMjA0NSwiaXNzIjoiUDJPbm1SZ3lIUU03dE1FTUU4bWpQR1hyZ0tjaSIsInJleHAiOiIyMDIzLTA3LTAzVDAyOjI3OjI1WiIsInJvbGVzIjpbImlzX3N0YWZmIiwiaXNfc3VwZXJ1c2VyIl0sInN1YiI6IlUyT25tbTJROVVSNWVGRlBNU3NZU0VsNHdXVjcifQ.Wc9RB4Qf3ZzdkD4I4oq_d7SgH5gw54Qq4cI-u8j3T3-BSnx-s6GV1Jz13VF07fZnzYSnV_jJRM-FnMqwL89CmdqvTrOHUSA8FDkJygthgFelHwE2_OJWFGePf4T-V6zeqWx427uoNIQFHQvbMelRaHH__dc66NbOzILZWcafx5VAdLIj5IqX-MZqVecUMiZqMTEw8q1hCbqX6lHrhZUrN_Ez47Exc173WLxd2AVy3El-OS5s6rP6y4FFXza7oUranJmEuoRXsPL_DShHV2fpnuQC3bL-gRKgY03RB3LPq7O-_VxeHIkbMDSbyFUefKP6WL05od9U_fklEwyQUj4WgQ', 'sessionToken': {'amr': ['webauthn'], 'drn': 'DS', 'exp': 1685932645, 'iat': 1685932045, 'iss': 'P2OnmRgyHQM7tMEME8mjPGXrgKci', 'rexp': '2023-07-03T02:27:25Z', 'roles': ['is_staff', 'is_superuser'], 'sub': 'U2Onmm2Q9UR5eFFPMSsYSEl4wWV7', 'jwt': 'eyJhbGciOiJSUzI1NiIsImtpZCI6IlAyT25tUmd5SFFNN3RNRU1FOG1qUEdYcmdLY2kiLCJ0eXAiOiJKV1QifQ.eyJhbXIiOlsid2ViYXV0aG4iXSwiZHJuIjoiRFMiLCJleHAiOjE2ODU5MzI2NDUsImlhdCI6MTY4NTkzMjA0NSwiaXNzIjoiUDJPbm1SZ3lIUU03dE1FTUU4bWpQR1hyZ0tjaSIsInJleHAiOiIyMDIzLTA3LTAzVDAyOjI3OjI1WiIsInJvbGVzIjpbImlzX3N0YWZmIiwiaXNfc3VwZXJ1c2VyIl0sInN1YiI6IlUyT25tbTJROVVSNWVGRlBNU3NZU0VsNHdXVjcifQ.Wc9RB4Qf3ZzdkD4I4oq_d7SgH5gw54Qq4cI-u8j3T3-BSnx-s6GV1Jz13VF07fZnzYSnV_jJRM-FnMqwL89CmdqvTrOHUSA8FDkJygthgFelHwE2_OJWFGePf4T-V6zeqWx427uoNIQFHQvbMelRaHH__dc66NbOzILZWcafx5VAdLIj5IqX-MZqVecUMiZqMTEw8q1hCbqX6lHrhZUrN_Ez47Exc173WLxd2AVy3El-OS5s6rP6y4FFXza7oUranJmEuoRXsPL_DShHV2fpnuQC3bL-gRKgY03RB3LPq7O-_VxeHIkbMDSbyFUefKP6WL05od9U_fklEwyQUj4WgQ'}, 'permissions': [], 'tenants': {}, 'projectId': 'P2OnmRgyHQM7tMEME8mjPGXrgKci', 'userId': 'U2Onmm2Q9UR5eFFPMSsYSEl4wWV7'}
dev-retrieve-front-end-1  | Starting new HTTPS connection (1): api.descope.com:443
dev-retrieve-front-end-1  | https://api.descope.com:443 "GET /v1/auth/me HTTP/1.1" 200 None
dev-retrieve-front-end-1  | Test view called
dev-retrieve-front-end-1  | None

Note None being returned for logger.info(request.session.get("user")) despite the logs for Descope clearly having tokens.

If I do logger.info(request.session.items()) then I get:

dict_items([('DS', None), ('DSR', 'eyJhbGciOiJSUzI1NiIsImtpZCI6IlAyT25tUmd5SFFNN3RNRU1FOG1qUEdYcmdLY2kiLCJ0eXAiOiJKV1QifQ.eyJhbXIiOlsid2ViYXV0aG4iXSwiZHJuIjoiRFNSIiwiZXhwIjoxNjg4MzUxMjQ1LCJpYXQiOjE2ODU5MzIwNDUsImlzcyI6IlAyT25tUmd5SFFNN3RNRU1FOG1qUEdYcmdLY2kiLCJzdWIiOiJVMk9ubW0yUTlVUjVlRkZQTVNzWVNFbDR3V1Y3In0.U-T8qqZ-beD2TDBjtAhNuC6c2OERoekI1_8sAC9KAxr0aPq6-dGu0jJb8Nqu2lBE5R_6gaK9n2nI01j3QquWBdbhsePzcp_TVTr5GDTHYEjxMQxbXOQycfj5zmPVdJKAfd0f4GsQjOHLW-PEmX911uB5T98WIPGX2SO67eWjaOLX8Aw1DiNMqRNhA-5fOPeEXtDsP82n28e9yQU6Kv8sMbkHXp28Tmm4PsP-dPha6nGlslouY1yESofwObL_EO2jSo19Db0PIwY-0UUX3bXcLAVOMNc2knucxH6iN5cOADk5HS_Jg_ztwugp7c2ADgG4yOYBXvwAbhz8ve_AGeRzfw'), ('_auth_user_id', '2'), ('_auth_user_backend', 'django_descope.authentication.DescopeAuthentication'), ('_auth_user_hash', '6f7fd439db311a2ac4942e643d5f1e7f91df4aafd89b348d8a0d44bf68cc243e')])

Here (hopefully) all relevant code:

views.py

import logging

from django.contrib.auth import logout
from django.http import HttpRequest, HttpResponseRedirect, JsonResponse
from django.urls import reverse
from django.views import View

logger = logging.getLogger(__name__)


class Logout(View):
    def get(self, request: HttpRequest):
        logout(request)
        return HttpResponseRedirect(reverse("index"))


class Test(View):
    def get(self, request: HttpRequest):
        logger.info("Test view called")
        logger.info(request.session.get("user"))
        return JsonResponse(request.session.get("user", {}))

urls.py

from django.urls import path
from django.views.generic import TemplateView

from .views import Test

urlpatterns = [
    path(
        "",
        TemplateView.as_view(template_name="descope_login.html"),
        name="index",
    ),
    path("test", Test.as_view(), name="test"),
]

descope_login.html

{% load descope %}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />

    <title>Descope Django</title>
    <meta name="description" content="Descope Example" />
    <meta name="author" content="Descope" />
  </head>

  <body>
    {% if user.is_authenticated %}
    <h1>Welcome {{ user.email }} you are logged in!</h1>
    <p><a href="{% url 'logout' %}">Log Out</a></p>
    {% else %} {% descope_flow "sign-up-or-in" "/" %} {% endif %}
  </body>
</html>

settings.py

from pathlib import Path

import environ

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
APPS_DIR = BASE_DIR / "app"

env = environ.Env()
environ.Env.read_env(BASE_DIR / ".env")

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/

DJANGO_ENV = env.str("DJANGO_ENV", "dev")
SECRET_KEY = env("DJANGO_SECRET_KEY")
DEBUG = env("DJANGO_DEBUG", default=False)
ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS")


# Application definition
DJANGO_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.humanize",
]

THIRD_PARTY_APPS = [
    "django_extensions",
    "django_htmx",
    "django_descope",
    # "logging_middleware",
]

if DEBUG:
    THIRD_PARTY_APPS += [
        "django_browser_reload",
        "debug_toolbar",
        "django_fastdev",
    ]

LOCAL_APPS = ["app"]

INSTALLED_APPS = LOCAL_APPS + THIRD_PARTY_APPS + DJANGO_APPS

AUTHENTICATION_BACKENDS = [
    "django_descope.authentication.DescopeAuthentication"
]


MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    # "whitenoise.middleware.WhiteNoiseMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "django_htmx.middleware.HtmxMiddleware",
    "debug_toolbar.middleware.DebugToolbarMiddleware",
    # "logging_middleware.middlewares.DjangoLoggingMiddleware",
    "django_descope.middleware.DescopeMiddleware",
]

if DEBUG:
    MIDDLEWARE += [
        "debug_toolbar.middleware.DebugToolbarMiddleware",
        "django_browser_reload.middleware.BrowserReloadMiddleware",
    ]

DEBUG_TOOLBAR_CONFIG = {
    "DISABLE_PANELS": ["debug_toolbar.panels.redirects.RedirectsPanel"],
    "SHOW_TEMPLATE_CONTEXT": True,
}

ROOT_URLCONF = "urls"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

WSGI_APPLICATION = "app.wsgi.application"


# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "OPTIONS": {"options": "-c search_path=django"},
        "NAME": env.str("POSTGRES_DB"),
        "USER": env.str("POSTGRES_USER"),
        "PASSWORD": env.str("POSTGRES_PASSWORD"),
        "HOST": "postgres",
        "PORT": "5432",
    }
}
DATABASES["default"]["ATOMIC_REQUESTS"] = True

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STATICFILES_DIRS = [BASE_DIR / "static"]
STATICFILES_FINDERS = [
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
]
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"

MEDIA_ROOT = str(APPS_DIR / "media")
MEDIA_URL = "/media/"

AUTH_PASSWORD_VALIDATORS: list = (
    []
)  # With descope, there's no need for passwords!


if DJANGO_ENV == "production":
    # Security
    CSRF_TRUSTED_ORIGINS = env.list("DJANGO_CSRF_TRUSTED_ORIGINS")
    CSRF_COOKIE_SECURE = True
    SESSION_COOKIE_SECURE = True
    SECURE_BROWSER_XSS_FILTER = True
    SECURE_CONTENT_TYPE_NOSNIFF = True

    # TODO: ssl

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
        },
    },
    "root": {
        "handlers": ["console"],
        "level": "DEBUG",
    },
}

# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/

LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_TZ = True

# Descope
DESCOPE_PROJECT_ID = env.str("DESCOPE_PROJECT_ID")

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (local>descope/renovate-config)

Latest release (1.3.1) breaks login process

Our current login process works great with release 1.3.0, but when upgrading to 1.3.1 we get the following error in the Django container logs and the user is not authenticated. Confirmed that rebuilding our containers with release 1.3.0 fixes the problem (no errors and user logs in successfully). Note that pytest (using descope test user) passes authentication with both releases.

unified_platform-portal-1  | [18/Dec/2023 13:58:50] "GET /?descope-login-flow=development-sign-up-or-iin%7C%23%7C2ZibWdAzcWHsKstpOyINKinigEx_11.end&t=093739ad7efb0a74bc889fb0cbc5a32e770dc709b6de189deed6453167ea5c3d HTTP/1.1" 200 4833
unified_platform-portal-1  | Internal Server Error: /auth/store_jwt
unified_platform-portal-1  | Traceback (most recent call last):
unified_platform-portal-1  |   File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
unified_platform-portal-1  |     response = get_response(request)
unified_platform-portal-1  |                ^^^^^^^^^^^^^^^^^^^^^
unified_platform-portal-1  |   File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
unified_platform-portal-1  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
unified_platform-portal-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
unified_platform-portal-1  |   File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
unified_platform-portal-1  |     return self.dispatch(request, *args, **kwargs)
unified_platform-portal-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
unified_platform-portal-1  |   File "/usr/local/lib/python3.11/site-packages/django/utils/decorators.py", line 46, in _wrapper
unified_platform-portal-1  |     return bound_method(*args, **kwargs)
unified_platform-portal-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
unified_platform-portal-1  |   File "/usr/local/lib/python3.11/site-packages/django/views/decorators/cache.py", line 62, in _wrapper_view_func
unified_platform-portal-1  |     response = view_func(request, *args, **kwargs)
unified_platform-portal-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
unified_platform-portal-1  |   File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 143, in dispatch
unified_platform-portal-1  |     return handler(request, *args, **kwargs)
unified_platform-portal-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
unified_platform-portal-1  |   File "/usr/local/lib/python3.11/site-packages/django_descope/views.py", line 23, in post
unified_platform-portal-1  |     add_tokens_to_request(request, session, refresh)
unified_platform-portal-1  |   File "/usr/local/lib/python3.11/site-packages/django_descope/authentication.py", line 18, in add_tokens_to_request
unified_platform-portal-1  |     session[SESSION_COOKIE_NAME] = session_token
unified_platform-portal-1  |     ~~~~~~~^^^^^^^^^^^^^^^^^^^^^
unified_platform-portal-1  | TypeError: 'WSGIRequest' object does not support item assignment
unified_platform-portal-1  | [18/Dec/2023 13:58:50] "POST /auth/store_jwt HTTP/1.1" 500 88472

How to Use with DescopeClient?

It's not entirely clear to me what to do once the user is logged in using django-descope. For instance, looking at: https://github.com/descope/python-sdk/blob/main/samples/access_key_sample_app.py as an example, how would one do:

            permission_name = "TestPermission"
            permission_presented = descope_client.validate_permissions(
                jwt_response, [permission_name]
            )
            logging.info(
                f"{permission_name} presented on the jwt: [{permission_presented}]"
            )
            role_name = "TestRole"
            role_presented = descope_client.validate_roles(jwt_response, [role_name])
            logging.info(f"{role_name} presented 

using django-descope? Should I be using the Descope Python SDK directly, and use DescopeClient separately from django-descope, or is there a better way?

How to use Django Admin?

I am not sure how to use the Django Admin with Descope. Can the example and quickstart guide be extended to explain how?

Customization of User Creation Process

The Scenario

Given that I have a custom user model, and an associated model like so:

from django.contrib.auth.models import AbstractBaseUser
from django.db import models

class Account(models.Model):
    name = models.CharField(max_length=200)
    descope_tenant = models.CharField(max_length=200, unique=True)

    def __str__(self):
        return self.name


class User(AbstractBaseUser):
    account = models.ForeignKey(Account, on_delete=models.CASCADE)

This creates a User model, with a non-nullable field relating it to the Account model, meaning that on creation of a User, an account MUST be provided. In my scenario, an Account is synonymous with a Descope tenant, and it stores the descope tenant ID.

This association can easily be created by getting the tenant the user belongs to(in this scenario, a user could never be assigned to more than one tenant) during the Django user creation and determining the Account for it, and providing that to the foreign key on the user.

The Problem

As it stands, I don't see a way to customize the user creation process within django-descope. The Django user is created during the get_user function in django-descope with the get_or_create function and is just passed the username.

Solutions

One possible solution might be to allow the user to define a callable(maybe via Django's settings.py or some function to register it?) which would get called from this function that is expected to work the same as the existing get_or_create call. There definitely may be a better solution, this was just one possibility I thought of.

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.