inventree / InvenTree

Open Source Inventory Management System
https://docs.inventree.org
MIT License
4.19k stars 754 forks source link

DataError at /accounts/microsoft/login/callback/ - value too long for type character varying(200) #5036

Closed MartinLoeper closed 1 year ago

MartinLoeper commented 1 year ago

Please verify that this bug has NOT been raised before.

Describe the bug*

I want to log in via the social provider microsoft graph. After my initial login, I get the following django error:

value too long for type character varying(200)

Django Version: 3.2.18
Exception Type: DataError
Exception Value: value too long for type character varying(200)
Exception Location: /home/inventree/env/lib/python3.9/site-packages/django/db/backends/utils.py, line 84, in _execute

Steps to Reproduce

  1. Login with admin user using normal login
  2. Connect account with social provider using settings -> account
  3. Logout
  4. Login using Microsoft Graph social provider
  5. Exception after redirect from Microsoft

Expected behaviour

Login via social provider succeeds

Deployment Method

Version Information

Version Information:

InvenTree-Version: 0.11.2 Django Version: 3.2.18 Commit Hash: 4868194a0 Commit Date: 25/05/2023 Database: postgresql Debug-Mode: True Deployed using Docker: False Active plugins: [{'name': 'InvenTreeBarcode', 'slug': 'inventreebarcode', 'version': '2.0.0'}, {'name': 'InvenTreeCoreNotificationsPlugin', 'slug': 'inventreecorenotificationsplugin', 'version': '1.0.0'}, {'name': 'CupsLabels', 'slug': 'cups', 'version': '0.1.0'}]

Please verify if you can reproduce this bug on the demo site.

Relevant log output

No response

SchrodingersGat commented 1 year ago

Can you look at the error logs to provide some more information about this particular error?

MartinLoeper commented 1 year ago

Sure, what kind of information shall I attach?

SchrodingersGat commented 1 year ago

The full error-log / traceback would be great. Make sure there's no identifiable information in there.

MartinLoeper commented 1 year ago

I somehow cannot see the error in the Admin panel, but I can see details when Debug mode is enabled:

Environment:

Request Method: GET
Request URL: http://my.inventry.app/accounts/microsoft/login/callback/?code=XXXXXXXXXXXXXXXXXXXXXXXX&state=i01pheUCZg0k&session_state=9de8bec3-fe32-4572-906a-8b714d5ecdb6

Django Version: 3.2.18
Python Version: 3.9.2
Installed Applications:
['django.contrib.admin',
 'build.apps.BuildConfig',
 'common.apps.CommonConfig',
 'company.apps.CompanyConfig',
 'label.apps.LabelConfig',
 'order.apps.OrderConfig',
 'part.apps.PartConfig',
 'report.apps.ReportConfig',
 'stock.apps.StockConfig',
 'users.apps.UsersConfig',
 'plugin.apps.PluginAppConfig',
 'InvenTree.apps.InvenTreeConfig',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'user_sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.sites',
 'maintenance_mode',
 'django_filters',
 'rest_framework',
 'rest_framework.authtoken',
 'corsheaders',
 'crispy_forms',
 'import_export',
 'django_cleanup.apps.CleanupConfig',
 'mptt',
 'markdownify',
 'djmoney',
 'djmoney.contrib.exchange',
 'error_report',
 'django_q',
 'formtools',
 'dbbackup',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'django_otp',
 'django_otp.plugins.otp_totp',
 'django_otp.plugins.otp_static',
 'allauth_2fa',
 'django_ical',
 'sslserver',
 'allauth.socialaccount.providers.microsoft']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'x_forwarded_for.middleware.XForwardedForMiddleware',
 'user_sessions.middleware.SessionMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'InvenTree.middleware.InvenTreeRemoteUserMiddleware',
 'django_otp.middleware.OTPMiddleware',
 'InvenTree.middleware.CustomAllauthTwoFactorMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'InvenTree.middleware.AuthRequiredMiddleware',
 'InvenTree.middleware.Check2FAMiddleware',
 'maintenance_mode.middleware.MaintenanceModeMiddleware',
 'InvenTree.middleware.InvenTreeExceptionProcessor']

Traceback (most recent call last):
  File "/home/inventree/env/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/inventree/env/lib/python3.9/site-packages/allauth/socialaccount/providers/oauth2/views.py", line 81, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/inventree/env/lib/python3.9/site-packages/allauth/socialaccount/providers/oauth2/views.py", line 158, in dispatch
    return complete_social_login(request, login)
  File "/home/inventree/env/lib/python3.9/site-packages/allauth/socialaccount/helpers.py", line 160, in complete_social_login
    return _complete_social_login(request, sociallogin)
  File "/home/inventree/env/lib/python3.9/site-packages/allauth/socialaccount/helpers.py", line 175, in _complete_social_login
    ret = _login_social_account(request, sociallogin)
  File "/home/inventree/env/lib/python3.9/site-packages/allauth/socialaccount/helpers.py", line 53, in _login_social_account
    return perform_login(
  File "/home/inventree/env/lib/python3.9/site-packages/allauth/account/utils.py", line 171, in perform_login
    adapter.login(request, user)
  File "/home/inventree/env/lib/python3.9/site-packages/allauth_2fa/adapter.py", line 25, in login
    view = request.resolver_match.func.view_class()

During handling of the above exception ('function' object has no attribute 'view_class'), another exception occurred:
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)

The above exception (value too long for type character varying(200)
) was the direct cause of the following exception:
  File "/home/inventree/env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/inventree/env/lib/python3.9/site-packages/django/core/handlers/base.py", line 183, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/inventree/env/lib/python3.9/site-packages/django/core/handlers/base.py", line 339, in process_exception_by_middleware
    response = middleware_method(request, exception)
  File "/home/inventree/src/InvenTree/InvenTree/middleware.py", line 168, in process_exception
    return super().process_exception(request, exception)
  File "/home/inventree/env/lib/python3.9/site-packages/error_report/middleware.py", line 27, in process_exception
    error = Error.objects.create(
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/models/query.py", line 453, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/models/base.py", line 739, in save
    self.save_base(using=using, force_insert=force_insert,
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/models/base.py", line 776, in save_base
    updated = self._save_table(
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/models/base.py", line 881, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/models/base.py", line 919, in _do_insert
    return manager._insert(
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/models/query.py", line 1270, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1416, in execute_sql
    cursor.execute(sql, params)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/backends/utils.py", line 98, in execute
    return super().execute(sql, params)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/inventree/env/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)

Exception Type: DataError at /accounts/microsoft/login/callback/
Exception Value: value too long for type character varying(200)
SchrodingersGat commented 1 year ago

Huh, interesting. It appears that the reason that you don't see the error message in the admin panel is because the creation of the error message itself is what is throwing the exception here.

I've made a new error for that specifically - https://github.com/inventree/InvenTree/issues/5038

Your particular exception is coming from the allauth lib:

image

SchrodingersGat commented 1 year ago

http://my.inventry.app/accounts/microsoft/login/callback/?code=XXXXXXXXXXXXXXXXXXXXXXXX&state=i01pheUCZg0k&session_state=9de8bec3-fe32-4572-906a-8b714d5ecdb6

Without actually providing the URL, how long is the complete callback URL (before you redacted it)?

MartinLoeper commented 1 year ago

The redacted paramter is 849 chars long. The whole URL spans 1001 chars. :open_mouth:

SchrodingersGat commented 1 year ago

I'd say that what has happened is that:

  1. The SSO application is misconfigured
  2. The resulting error message has not been stored because the URL is heck long

Point 1) is obviously what you're interested in fixing here. Can you share some (redacted) screenshots of your SSO application config in the admin interface?

MartinLoeper commented 1 year ago

That is good to know, I had no clue it might be Azure which is misconfigured. Thanks for looking into it @SchrodingersGat. Really appreciate the time and effort!!

I added InvenTree under 'Microsoft_AAD_RegisteredApps', added a client secret and a redirect url: https://inventree.xxxxx.de/accounts/microsoft/login/callback/.

I did not select any of the following options (if it matters): azure

Admin Config for Social Application "Microsoft": admin

Can you think of anything I could have misconfigured? Or anything specifically that I can attach here? The "Add a 3rd Party Account" feature under "settings -> account -> social accounts" worked. I can see my user under "Social accounts" in the admin interface.

SchrodingersGat commented 1 year ago

That looks mostly OK.. This stuff is always so hard to configure.

One thing, please try changing the name of the application from "Microsoft" to "microsoft" (note the capitalization) to exactly match the callback URL. I think that django-allauth is pretty picky about that

matmair commented 1 year ago

Microsoft is doing strict URL matching. Make sure the redirection/callback URLs are exactly what your server uses.

MartinLoeper commented 1 year ago

@matmair Thanks for pointing that out! It looks like my callback URL is correct. It was wrong initially but then Microsoft would not redirect me back since it checks whether the Azure value and the inventree value match. I also double checked that the inventree callback URL for microsoft is indeed /accounts/microsoft/login/callback/.

MartinLoeper commented 1 year ago

@SchrodingersGat I found out the root cause of the issue now! It looks like my 2FA device is the issue in the first place. Since the user already existed and was mapped onto the social provider identity, allauth tried to find an OTP device for the social login and failed.

Once I disabled 2FA for the user, everything works as expected and I can log in via Office 365. However, I guess this is only a workaround. The issue lies somewhere between allauth, allauth_2fa and inventree.

MartinLoeper commented 1 year ago

Maybe the "Enforce MFA" Login Setting was the issue not the active MFA for my user per se... Have to investigate this further...

MartinLoeper commented 1 year ago

Just checked... Looks like the presence of the MFA device (TOTP) for the user is causing the trouble - even without the "Enforce MFA" setting being active.

matmair commented 1 year ago

Maybe try removing the 2fa device, connecting with SSO and reading it. If your primary id changes your totp token will be invalid.

SchrodingersGat commented 1 year ago

@MartinLoeper did you get this worked out?

MartinLoeper commented 1 year ago

I tried recreating the totp device after the social login. It did not work. For the moment I just disabled totp devices for all users. Although this workaround works, it is not ideal as local user accounts are weakened. Don't know when I have time to look into this as I am not that knowledgeable in Python.

SchrodingersGat commented 1 year ago

@MartinLoeper the original error (value too long for type character) has been addressed. Are you happy to close this out?

MartinLoeper commented 1 year ago

@SchrodingersGat Idk if the value too long for type character is the root cause of the error. Maybe rephrase the title of this issue to something like "MFA breaks Microsoft Graph Social Login"? I dont really know why it is happening? Can you guys confirm that social login in general works for you when MFA is enabled for the user who logs in via social provider?

SchrodingersGat commented 1 year ago

Maybe I misread your previous message, I thought you had a workaround.

Can you guys confirm that social login in general works for you when MFA is enabled for the user who logs in via social provider?

I've got setups working with both Microsoft graph and google app logins.

Now that the secondary error is fixed, you should be able to get a better idea of where the process is breaking down. Please update to the latest version of InvenTree, try again, and let me know what error messages you are seeing.

github-actions[bot] commented 1 year ago

This issue seems stale. Please react to show this is still important.