Closed aoiheaven closed 1 year ago
Please update your requirements to list all versions of the packages.
I suspect this is a djongo issue and not a django-auth-adfs issue. The error is related to the default user model and indicating that the id from the database is an ObjectID and not convertable to an int. Review the djongo docs to see if says anything about changing how settings.AUTH_USER_MODEL
should be set.
I suspect this is a djongo issue and not a django-auth-adfs issue. The error is related to the default user model and indicating that the id from the database is an ObjectID and not convertable to an int. Review the djongo docs to see if says anything about changing how
settings.AUTH_USER_MODEL
should be set.
Thanks for replying!
so that you mean I should create one new app to customize user model to replace AUTH_USER_MODEL
and about "id" entry should be configured as "AutoField" to bypass it, right?
I'm honestly not sure. I've never used that library before, but the docs indicate it should automatically convert the user model.
give up and migrate to sql series for extended user model. close it
Hi Sir, I got error raised: ValueError: Field 'id' expected a number but got ObjectId(...") from "get_prep_value", when I use mongodb with djongo connector. It worked well in sqlite, but seemed cannot pass validation or data store in user.full_clean()/.save() Can you help about this? I preper Mongodb if possible...
here my log:
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, callback_kwargs) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\views\generic\base.py", line 103, in view return self.dispatch(request, *args, *kwargs) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\views\generic\base.py", line 142, in dispatch return handler(request, args, kwargs) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django_auth_adfs\views.py", line 40, in get
user = authenticate(request=request, authorization_code=code) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\views\decorators\debug.py", line 42, in sensitive_variables_wrapper return func(func_args, func_kwargs) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\contrib\auth__init__.py", line 77, in authenticate user = backend.authenticate(request, credentials) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django_auth_adfs\backend.py", line 467, in authenticate user = self.process_access_token(access_token, adfs_response) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django_auth_adfs\backend.py", line 204, in process_access_token user.full_clean() File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\base.py", line 1462, in full_clean self.validate_unique(exclude=exclude) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\base.py", line 1207, in validate_unique errors = self._perform_unique_checks(unique_checks) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\base.py", line 1316, in _perform_unique_checks qs = qs.exclude(pk=model_class_pk) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\query.py", line 1428, in exclude return self._filter_or_exclude(True, args, kwargs) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\query.py", line 1438, in _filter_or_exclude clone._filter_or_exclude_inplace(negate, args, kwargs) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\query.py", line 1443, in _filter_or_exclude_inplace self._query.add_q(~Q(args, **kwargs)) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\sql\query.py", line 1532, in addq clause, = self._add_q(q_object, self.used_aliases) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\sql\query.py", line 1562, in _add_q child_clause, needed_inner = self.build_filter( File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\sql\query.py", line 1478, in build_filter condition = self.build_lookup(lookups, col, value) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\sql\query.py", line 1303, in build_lookup lookup = lookup_class(lhs, rhs) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\lookups.py", line 27, in init self.rhs = self.get_prep_lookup() File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\lookups.py", line 341, in get_prep_lookup return super().get_prep_lookup() File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\lookups.py", line 85, in get_prep_lookup return self.lhs.output_field.get_prep_value(self.rhs) File "C:\Users\harryw\web_dev\socd_env\sofa_be_django\venv\lib\site-packages\django\db\models\fields__init.py", line 2020, in get_prep_value raise e.class__( TypeError: Field 'id' expected a number but got ObjectId('636a7719d76033a24e13c120'). [08/Nov/2022 23:34:50] "GET /oauth2/callback?code=XXXXXXX
... [ { _id: ObjectId("636a714dfc1ab55037d5d827"), password: '', last_login: null, is_superuser: false, username: 'XXXXXXX', first_name: '', last_name: '', email: '', is_staff: false, is_active: true, date_joined: ISODate("2022-11-08T15:10:04.729Z") } ] ...
""" Django settings for sofa_be_django project.
Generated by 'django-admin startproject' using Django 4.0.6.
For more information on this file, see https://docs.djangoproject.com/en/4.0/topics/settings/
For the full list of settings and their values, see https://docs.djangoproject.com/en/4.0/ref/settings/ """
from pathlib import Path
Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(file).resolve().parent.parent
Quick-start development settings - unsuitable for production
See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "XXXXXXX"
SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ["127.0.0.1", "localhost", "XXXXXXX"]
AUTH SCHEME FOR SSO (AzureAD) - ADFS Authentication for Django
Ref: https://django-auth-adfs.readthedocs.io/en/latest/azure_ad_config_guide.html#step-2-configuring-settings-py
AUTHENTICATION_BACKENDS = { "django_auth_adfs.backend.AdfsAuthCodeBackend", "django_auth_adfs.backend.AdfsAccessTokenBackend",
"django.contrib.auth.backends.ModelBackend",
}
REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ( "django_auth_adfs.rest_framework.AdfsAccessTokenAuthentication", "rest_framework.authentication.SessionAuthentication", ) }
Application definition
INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "django_filters", "rest_framework", "corsheaders", "django_auth_adfs", # django-auth-adfs -> A Django authentication backend for Microsoft ADFS and Azure AD ]
MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "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",
With this you can force a user to login without using
]
ROOT_URLCONF = "sofa_be_django.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 = "sofa_be_django.wsgi.application"
Database
https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
DATABASES = { "default": { "ENGINE": "djongo", "NAME": "XXXXXXX", "CLIENT": { "host": "mongodb+srv://XXXXXXX" }, } }
Password validation
https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ]
SSO validation
Client secret is not public information. Should store it as an environment variable.
client_id = "a2a099b9-487c-4c63-a9fe-5a613d1e90e9" # 'Your client id here' client_secret = "XXXXXXX" # TODO: 'Your client secret here', need query this value from Environment! tenant_id = "43083d15-7273-40c1-b7db-39efd9ccc17a" # 'Your tenant id here'
AUTH_ADFS = { "AUDIENCE": client_id, "CLIENT_ID": client_id, "CLIENT_SECRET": client_secret, "CLAIM_MAPPING": { "first_name": "given_name", "last_name": "family_name", "email": "upn", }, "GROUPS_CLAIM": None, "MIRROR_GROUPS": False, "USERNAME_CLAIM": "upn", "TENANT_ID": tenant_id, "RELYING_PARTY_ID": client_id, "LOGIN_EXEMPT_URLS": ["^api/", "public/"], # Assuming you API is available at /api }
Configure django to redirect users to the right URL for login
LOGIN_URL = "django_auth_adfs:login" LOGIN_REDIRECT_URL = "/" LOGOUT_REDIRECT_URL = "/"
You can point login failures to a custom Django function based view for customization of the UI
CUSTOM_FAILED_RESPONSE_VIEW = "dot.path.to.custom.views.login_failed"
Internationalization
https://docs.djangoproject.com/en/4.0/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True
Static files (CSS, JavaScript, Images)
https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_URL = "static/"
Default primary key field type
https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
Record log for Hint
LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": { "verbose": {"format": "%(levelname)s %(asctime)s %(name)s %(message)s"}, }, "handlers": { "console": {"class": "logging.StreamHandler", "formatter": "verbose"}, }, "loggers": { "django_auth_adfs": { "handlers": ["console"], "level": "DEBUG", }, }, }
... path("oauth2/", include("django_auth_adfs.urls")), ...
djangorestframework django-filter demjson django-cors-headers djongo pymongo==3.12.3 pymongo[srv] gunicorn jsonfield dnspython == 2.1.0 django-auth-adfs