django-allauth Google login not working on iOS - django

I'm building a PWA with django and have this issue with django-allauth Google login. Everything works well on a Windows PC with Chrome and Edge. But when trying to login with Google on iOS devices, I get the social network login failure with code: 'unknown', exception: 'PermissionDenied()'
Any ideas what could be the reason or where to search for it?
EDIT
I tried to do some more debugging and got these errors (only on iOS devices!):
Internal Server Error: /accounts/google/login/callback/ Traceback
(most recent call last): File
"/home/kava/.virtualenvs/django3/lib/python3.8/site-packages/allauth/socialaccount/providers/oauth2/views.py",
line 141, in dispatch
login.state = SocialLogin.verify_and_unstash_state( File "/home/kava/.virtualenvs/django3/lib/python3.8/site-packages/allauth/socialaccount/models.py",
line 325, in verify_and_unstash_state
raise PermissionDenied() django.core.exceptions.PermissionDenied

I managed to solve the problem.
The error was caused by the line that follows if "socialaccount_state" not in request.session: in this function:
#classmethod
def verify_and_unstash_state(cls, request, verifier):
if "socialaccount_state" not in request.session:
raise PermissionDenied()
state, verifier2 = request.session.pop("socialaccount_state")
if verifier != verifier2:
raise PermissionDenied()
return state
So the problem was with the session data, more precisely, the 'socialaccount_state' was missing.
After Googling this issue in connection with iOS I found this thread.
I changed the SESSION COOKIE_SAMESITE and CSRF_COOKIE_SAMESITE to None as suggested there and it works!
Btw, if 'None' was between apostrophes, it didn't work on iOS 12 devices.

Related

Api with flask-jwt-extended with authentication problems?

I have built an api with flask-restful and flask-jwt-extended and have correctly configured the validation passages for token expiration and invalidation. However, even though it has built the token expiration and invalid validation callbacks, api does not process correctly and reports the error: Signature has expired
On the server in the cloud, we have a Centos 7 x64 of 16gb ram, running the application using gunicorn in version 19.9.0. Using the miniconda to create the applications' python environments.
In tests in the production environment, the application complains of the expired token. However in a test environment, using Ubuntu 18.04.2, x64 with 16 gb ram, using the same settings with miniconda and gunicorn, the application has no problems executing it, returning the correct message when the token expires.
My jwt.py
from flask import Blueprint, Response, json, request
from flask_jwt_extended import (JWTManager, create_access_token,
create_refresh_token, get_jwt_identity,
jwt_required)
from app.models.core import User
from .schemas import UserSchema
from .utils import send_reponse, user_roles
def configure_jwt(app):
JWT = JWTManager(app)
#JWT.expired_token_loader
def my_expired_token_callback(expired_token):
return Response(
response=json.dumps({
"message": "Expired token"
}),
status=401,
mimetype='application/json'
)
#JWT.invalid_token_loader
def my_invalid_token_callback(invalid_token):
return Response(
response=json.dumps({
"message": "Invalid token"
}),
status=422,
mimetype='application/json'
)
Error log:
[2019-05-23 15:42:02 -0300] [3745] [ERROR] Exception on /api/company [POST]
Traceback (most recent call last):
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_restful/__init__.py", line 458, in wrapper
resp = resource(*args, **kwargs)
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask/views.py", line 88, in view
return self.dispatch_request(*args, **kwargs)
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_restful/__init__.py", line 573, in dispatch_request
resp = meth(*args, **kwargs)
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 102, in wrapper
verify_jwt_in_request()
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 31, in verify_jwt_in_request
jwt_data = _decode_jwt_from_request(request_type='access')
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 266, in _decode_jwt_from_request
decoded_token = decode_token(encoded_token, csrf_token)
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/utils.py", line 107, in decode_token
allow_expired=allow_expired
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/flask_jwt_extended/tokens.py", line 138, in decode_jwt
leeway=leeway, options=options)
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/jwt/api_jwt.py", line 104, in decode
self._validate_claims(payload, merged_options, **kwargs)
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/jwt/api_jwt.py", line 134, in _validate_claims
self._validate_exp(payload, now, leeway)
File "/home/company/miniconda3/envs/api_ms/lib/python3.6/site-packages/jwt/api_jwt.py", line 175, in _validate_exp
raise ExpiredSignatureError('Signature has expired')
jwt.exceptions.ExpiredSignatureError: Signature has expired
I'm trying to understand why the application is able to correctly return the token expiration message in the test environment, where in the production environment it returns the error code 500 Internal Server Error. In addition to fixing this problem in our application.
Based on this link found inside the project repository, I discovered that the problem is related to the flask configuration option called PROPAGATE_EXCEPTIONS, which must be True.
The issue in the flask-jwt-extended repository that helped me find the answer.
This comment states that Flask Restful needs to ignore JWT and JWT Extended Exceptions and provides a simple snippet that solves the issue.
Copying the code from above link,
from flask_jwt_extended.exceptions import JWTExtendedException
from jwt.exceptions import PyJWTError
class FixedApi(Api):
def error_router(self, original_handler, e):
if not isinstance(e, PyJWTError) and not isinstance(e, JWTExtendedException) and self._has_fr_route():
try:
return self.handle_error(e)
except Exception:
pass # Fall through to original handler
return original_handler(e)

Selenium get stuck while connecting to Firefox

I'm working on a website with Python 3 and Django 1.6. I wanted to create a view, which renders a particular element from my site to a png. Therefore I use Selenium to remote control Firefox to get a specific page from my webserver and the fetching a screenshot for the response. The following code is written for this purpose:
def do_get(self, *args, **kwargs):
from pyvirtualdisplay import Display
from selenium import webdriver
import base64
display = Display(visible=0, size=(200, 100))
display.start()
browser = webdriver.Firefox()
browser.get('http://www.google.com')
response = base64.b64decode(browser.get_screenshot_as_base64())
browser.quit()
display.stop()
return HttpResponse(content=response, mimetype='image/png')
The problem is, that if I'm running the code via the python3 console directly as root everything is working fine. But my apache works with a different user without root permissions. When I try to execute the code with this user, the code is stuck in the line
browser = webdriver.Firefox()
It seems that Selenium can't connect to Firefox, when I interrupt the exection following traceback occurs:
Traceback (most recent call last):
File "test.py", line 6, in <module>
browser = webdriver.Firefox()
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/firefox/webdriver.py", line 59, in __init__
self.binary, timeout),
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/firefox/extension_connection.py", line 47, in __init__
self.binary.launch_browser(self.profile)
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/firefox/firefox_binary.py", line 60, in launch_browser
self._start_from_profile_path(self.profile.path)
File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/firefox/firefox_binary.py", line 83, in _start_from_profile_path
env=self._firefox_env).communicate()
File "/usr/lib/python3.4/subprocess.py", line 936, in communicate
stdout = _eintr_retry_call(self.stdout.read)
File "/usr/lib/python3.4/subprocess.py", line 487, in _eintr_retry_call
return func(*args)
It seems to be a user permission issue, therefore I changed the owner of the installed firefox to my apache user. I can run firefox from the console with this user, but with the webserver the problem persists. My server is running a Ubuntu 14.04 LTS instance.
Any ideas?
Are you on the latest version of Firefox? I upgraded to version 32 this morning and the webdriver plugin is no longer supported.
Mozilla support suggests using Chrome instead of downgrading :-(

Django logout not working

I seem to have the same problem as in this question: Django logout problem
Mine is a bit weirder, it works in google chrome.... but not in firefox...
this is my logout function: (in views.py)
def my_logout(request):
logger.debug("Logout called by user")
try:
# Here I do some custom stuff, like logging this action in a database and so on
# For this question it shouldn't matter... because in a try catch
# so whatever goes wrong here, logging out should work anyway
except Exception, e:
logger.info("Logging logout action error: %s" % e)
logout(request)
return HttpResponseRedirect("/")
in settings.py I have:
LOGIN_URL = '/desktop/login/'
LOGOUT_URL = '/desktop/logout/'
LOGIN_REDIRECT_URL = '/'
And in the urls.py of the app iamapps (include in the project urls as /desktop/):
url(r'^login/$', 'iamapps.views.my_login', name='iamapps.login'),
url(r'^logout/$', 'iamapps.views.my_logout', name='iamapps.logout'),
further info:
django 1.4.3 (just updated from 1.3 to 1.4 ....)
python 2.7
works in Chrome but not in Firefox 17.0.1, Linux
The fact that it does work in google chrome but does not work in firefox puzzles me the most. Seems it has something to do with firefox keeps remembering the user as being logged on...
EDIT:
I get a broken pipe.... but I seem to get it not on logging out... but going to the home view after logout....
Traceback (most recent call last):
File "/usr/lib/python2.7/wsgiref/handlers.py", line 86, in run
self.finish_response()
File "/usr/lib/python2.7/wsgiref/handlers.py", line 127, in finish_response
self.write(data)
File "/usr/lib/python2.7/wsgiref/handlers.py", line 210, in write
self.send_headers()
File "/usr/lib/python2.7/wsgiref/handlers.py", line 268, in send_headers
self.send_preamble()
File "/usr/lib/python2.7/wsgiref/handlers.py", line 192, in send_preamble
'Date: %s\r\n' % format_date_time(time.time())
File "/usr/lib/python2.7/socket.py", line 324, in write
self.flush()
File "/usr/lib/python2.7/socket.py", line 303, in flush
self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 58684)
Traceback (most recent call last):
File "/usr/lib/python2.7/SocketServer.py", line 582, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/media/storage/django/sites/iamfloraservice/parts/django/django/core/servers/basehttp.py", line 139, in __init__
super(WSGIRequestHandler, self).__init__(*args, **kwargs)
File "/usr/lib/python2.7/SocketServer.py", line 641, in __init__
self.finish()
File "/usr/lib/python2.7/SocketServer.py", line 694, in finish
self.wfile.flush()
File "/usr/lib/python2.7/socket.py", line 303, in flush
self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------
[24/Dec/2012 14:33:25] "GET / HTTP/1.1" 200 48247
Edit 2
it goes to this view after loging out and being redirected:
def home(request, template='iamfloraservice/home.html'):
logger.debug("Home view called by user %s" % request.user)
return render_to_response(template,{},context_instance=RequestContext(request))
I think the redirect with the request to this view causes the problem....
In the log sais it's still user 'michel' (beacuse the view uses the request from the redirect, and that had user michel)... however... user michel is being logged out in the mean time....
EDIT 3
because of the suggestion it's due to the logger.
unremarking the logging does not help
And it's the default logger:
import logging
logger = logging.getLogger(__name__)
EDIT 4 (30-12-2012)
My logout is from a main window where I show a logout link when a user is logged on and a login link if a user is logged out. Also it contains a toolbar, which tools are filled depending on the the user and it's membership of groups.
I think the problem is, it's reloading this main window while the cache and the user in it's request isn't cleared yet. Somehow Chrome knows how to handle this, and firefox results in a broken pipe error. Clearing the cache manually in the browser results in the correct view after reload....
a solution might be to redirect to a page without anything in it that contains users...
or find out to clear the cache on the right moment myselve....
this problem describes maybe the same... but I cannot expect users to do anything in the browser just to logout? see django 1.4 caching GET to /login/
Edit 5 (31-12-2012)
It seems it's a caching problem.... but not sure how to fix this yet.
these are my caching settings:
if not DEBUG:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}
else:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
}
But I tried without the dummycache as well
EDIT 6 (4-jan-2013)
Still no solution.... I changed the way I log out to the django way, and I Am using the signals now... see my own answer below.
but still it gives the brokenpipe error which causes firefox stopping logging out. It's not a caching problem. If I go to another page, or even worse... the admin pages. I Am still logged on. The only way to logout is through the logout on the admin page.... If it's not an admin user... there is no way to get me logged out on the firefox browser.
When logging off using the admin interface, so the signal works fine...
I checked by turning off the signal.... and still the logging out in firefox does not work.
Conclusion: going back to the main page () is causing the problem.
EDIT 7 (4 jan 2013)
I made a simple loggedout view for testing,
this template:
<html>
<head>
<title>
Logged out
</title>
</head>
<body>
You are succesfully logged out.<br>
<br>
Go back to the main page
or<br>
log in again
</body>
</html>
and the logged out view:
class LoggedOutView(TemplateView):
template_name = "iamapps/logged_out.html"
and changed the urls in to:
url(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page': '/desktop/loggedout/'}, name='iamapps.logout'),
#url(r'^logout/$', 'django.contrib.auth.views.logout_then_login', name='iamapps.logout'),
url(r'^loggedout/$', LoggedOutView.as_view(),name='iamapps.loggedout'),
and still, to simplyfy things... I have the signals turned off.
and it's still not working in firefox.... but it works in chrome
In firefox it does not go to the logged out page
I generally just use the contributed view to logout users. Simply add this to your root urls.py file:
# Would be nice to use settings.LOGIN_URL for `next_page` here, too
url(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page': '/login'}),
and you'll be good to go.
Happy Djangoing.
Finally I totally switched to almost back to django defaults...
Using:
in views.py:
from django.contrib.auth.forms import AuthenticationForm
from django.views.generic.edit import FormView
class LoginView(FormView):
"""
This is a class based version of django.contrib.auth.views.login.
"""
form_class = AuthenticationForm
redirect_field_name = REDIRECT_FIELD_NAME
template_name = 'iamapps/login.html'
#method_decorator(csrf_protect)
#method_decorator(never_cache)
def dispatch(self, *args, **kwargs):
return super(LoginView, self).dispatch(*args, **kwargs)
def form_valid(self, form):
"""
The user has provided valid credentials (this was checked in AuthenticationForm.is_valid()). So now we
can check the test cookie stuff and log him in.
"""
self.check_and_delete_test_cookie()
login(self.request, form.get_user())
return super(LoginView, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(LoginView, self).get_context_data(**kwargs)
apps_settings=iamapps_settings()
if apps_settings[LOGON_BASE_APP_NAME]:
self.extend_template="%s/base.html" % apps_settings[LOGON_BASE_APP_NAME]
else:
self.extend_template="iamapps/base.html"
context['extend_template']=self.extend_template
return context
def form_invalid(self, form):
"""
The user has provided invalid credentials (this was checked in AuthenticationForm.is_valid()). So now we
set the test cookie again and re-render the form with errors.
"""
self.set_test_cookie()
return super(LoginView, self).form_invalid(form)
def get_success_url(self):
if self.success_url:
redirect_to = self.success_url
else:
redirect_to = self.request.REQUEST.get(self.redirect_field_name, '')
netloc = urlparse.urlparse(redirect_to)[1]
if not redirect_to:
redirect_to = settings.LOGIN_REDIRECT_URL
# Security check -- don't allow redirection to a different host.
elif netloc and netloc != self.request.get_host():
redirect_to = settings.LOGIN_REDIRECT_URL
return redirect_to
def set_test_cookie(self):
self.request.session.set_test_cookie()
def check_and_delete_test_cookie(self):
if self.request.session.test_cookie_worked():
self.request.session.delete_test_cookie()
return True
return False
def get(self, request, *args, **kwargs):
"""
Same as django.views.generic.edit.ProcessFormView.get(), but adds test cookie stuff
"""
self.set_test_cookie()
return super(LoginView, self).get(request, *args, **kwargs)
and urls:
url(r'^login/$', LoginView.as_view(), name='login'),
This solved all my troubles... about loggin and logiing off on...
the login and logout signals just working fine:
from django.contrib.auth.signals import user_logged_out, user_logged_in
# Note, these login and logout signals are registered in imamstats views
def iam_logged_out_actions(sender, user, request, **kwargs):
try:
# ... do my logging out actiosn (stats etc.)
except Exception, e:
logger.error("Logging logout action error: %s" % e)
# Note, these login and logout signals are registered in imamstats views
def iam_logged_in_actions(sender, user, request, **kwargs):
try:
# ... do my log in stats etc. things
except Exception, e:
logger.error("Logging login action error: %s" % e)
browsing to stackoverflow... (did another search)
I found this one: .... see django.contrib.auth.logout in Django ..
But is is even worse.... I found this... astonished... but explains it all:
Django, Logout_URL doesn't redirect well
The I found out it's a won't fix bug (###$%%) not allowed to curse on christmas eve....
So the solution to do my custom stuff is in the signals in stead of using my own view.
Do the default view and redirect...
and use this documentation to create a signal.. https://docs.djangoproject.com/en/dev/topics/auth/#login-and-logout-signals
Adding the signals is quite easy, i put it in models.py off my main app (iamapps):
import logging
from django.contrib.auth.signals import user_logged_out
from django.contrib.auth.signals import user_logged_in
logger = logging.getLogger(__name__)
def iam_logged_out_actions(sender, user, request, **kwargs):
#whatever...
logger.debug("Logging out: user = %s" % user)
user_logged_out.connect(iam_logged_out_actions)
def iam_logged_in_actions(sender, user, request, **kwargs):
#whatever...
logger.debug("Logging in: user = %s" % user)
user_logged_in.connect(iam_logged_in_actions)
This works....however it does not solve the broken pipe which I think might cause the failure on the logging out... so logging out in firefox still fails... and in chrome it works...
Logging out from django admin page works in firefox.. and the signal has another pro: also from logging out in the admin interface, the signal is being called...
for logging out i use now this urls.py:
url(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}, name='iamapps.logout'),
My suspicion is that the original logout view returns a response that clears cookie or something like that, and you're throwing that response out. Could you try simply returning its response to the user, like this?
def my_logout(request):
# something...
return logout(request)
The verified answer work well for the mentioned version but it is not working in django 2.2 version any more. so in order to do successful redirect after logout you have to define the attributes.
from django.contrib import admin
from django.urls import path, include
from dark_bot import views
from django.contrib.auth import views as v
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index, name="index"),
path('contact/', views.contact, name="contact"),
path('search/', include('search.urls')),
path('user/', include('accounts.urls')),
path('dashboard/', include('dashboard.urls')),
path('accounts/login/', v.LoginView.as_view(), name="login"),
path('accounts/logout/',v.LogoutView.as_view(next_page='/'),name="logout")
# path('dashboard/', include('dashboard.urls')),
]
This is how you can see I passed the next_page attribute to the class LogoutView which will tell where to redirect or go after successfull logout.
Hope this may help someone.
Happy Coding!

Django 1.4 Local 500 Error Page

Since moving to Django 1.4 with DEBUG = True and TEMPLATE_DEBUG = True, I no longer see the typical yellow error screen with traceback when I encounter an error locally. Instead I get a plain white screen that says, "An error has occurred. Please check your logs . . . ". Is this the new behavior or have I screwed something up by combining 1.3 and 1.4 files and settings.
Here's an example of my local settings.
The error handler
is located in django.core.handler.base try to debug the handle_uncaught_exception function.
def handle_uncaught_exception(self, request, resolver, exc_info):
"""
Processing for any otherwise uncaught exceptions (those that will
generate HTTP 500 responses). Can be overridden by subclasses who want
customised 500 handling.
Be *very* careful when overriding this because the error could be
caused by anything, so assuming something like the database is always
available would be an error.
"""
from django.conf import settings
if settings.DEBUG_PROPAGATE_EXCEPTIONS:
raise
logger.error('Internal Server Error: %s', request.path,
exc_info=exc_info,
extra={
'status_code': 500,
'request': request
}
)
if settings.DEBUG:
from django.views import debug
check if you pass here
return debug.technical_500_response(request, *exc_info)
# If Http500 handler is not installed, re-raise last exception
if resolver.urlconf_module is None:
raise exc_info[1], None, exc_info[2]
# Return an HttpResponse that displays a friendly error message.
callback, param_dict = resolver.resolve500()
return callback(request, **param_dict)
check with the debugger that you pass in debug.technical_500_response

django 1.3 upgrade problem

I recently updgraded to django 1.3. After the upgrade, I get the following error whenever I used request.POST:
Traceback (most recent call last):
File "/usr/lib/python2.4/site-packages/django/core/handlers/base.py", line 86, in get_response
response = None
File "/public/gdp/trunk/src/ukl/lis/process/utils/error_handler.py", line 15, in __call__
return self.function(*args, **kwargs)
File "/usr/lib/python2.4/site-packages/django/views/decorators/cache.py", line 30, in _cache_controlled
# and this:
File "/public/gdp/trunk/src/ukl/lis/process/authentication/views.py", line 438, in login
form = loginForm(request.POST)
File "/usr/lib/python2.4/site-packages/django/core/handlers/modpython.py", line 101, in _get_post
self._load_post_and_files()
AttributeError: 'ModPythonRequest' object has no attribute '_load_post_and_files'
Once I reverted back to django 1.0 the error is fixed.
Why is django 1.3 alone throwing this error? How to correct it?
Stepping from Django 1.0 to Django 1.3 is a big jump, a lot of items might have been deprecated or no longer used, I recommend you to just check some of the documentation for the middleware_classes
Django Middleware documentation
I tried re-installing my mod-python and now the error is fixed. Now thinking of migrating to mod_wsgi.